/* * decompress.h: interface to decompression abstraction layer * * Copyright (C) 2007 Colin Watson. * * This file is part of man-db. * * man-db is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * man-db is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with man-db; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef MAN_DECOMPRESS_H #define MAN_DECOMPRESS_H #include #include "pipeline.h" struct decompress; typedef struct decompress decompress; /* Flags, combined using bitwise-or. */ enum { /* Allow the resulting decompressor to be constructed by reading and * buffering the decompressed file contents in-process, rather than * by starting a subprocess and streaming the output. This is * suitable if and only if the file contents are only going to be * handled in-process rather than being passed as input to some * other program, but if that is the case then this is a significant * optimization. */ DECOMPRESS_ALLOW_INPROCESS = 1 }; /* Open a decompressor reading from FILENAME. The caller must start the * resulting decompressor. If the DECOMPRESS_ALLOW_INPROCESS flag is given, * then the resulting decompressor may be in-process (in which case * decompress_get_pipeline will fail). */ decompress *decompress_open (const char *filename, int flags); /* Open a decompressor reading from file descriptor FD. The caller must * start the resulting decompressor. This always uses pipeline-based * decompression, since if it attempted to decompress data in process it * would be unable to recover if it found that the data was too large. */ decompress *decompress_fdopen (int fd); /* Return true if and only if this is a pipeline-based decompressor. */ bool decompress_is_pipeline (decompress *d); /* Get the pipeline corresponding to a decompressor. Raises an assertion * failure if this is not a pipeline-based decompressor. */ pipeline *decompress_get_pipeline (decompress *d); /* Return the start of the buffer stored in an in-process decompressor. * Raises an assertion failure if this is not an in-process decompressor. */ const char *decompress_inprocess_buf (decompress *d); /* Return the total number of uncompressed bytes stored in an in-process * decompressor. Raises an assertion failure if this is not an in-process * decompressor. */ size_t decompress_inprocess_len (decompress *d); /* Replace an in-process decompressor's entire buffered file contents. * * In-process decompression works by buffering the whole file in memory, * which works because we constrain it to only ever dealing with small * files, and allows us to emulate streaming without having to resort to * subprocesses, threads, or coroutines. However, there are some cases * (notably encoding conversion) where it's useful to be able to do some * kind of processing on the file contents in a way that similarly looks * like streaming to its consumers. To allow for this, we allow consumers * of decompressed data to replace the buffered file contents and reset the * read offset so that their consumers in turn get the same useful read/peek * API. * * This is of course a hack, and wouldn't be a wise thing to include in a * general-purpose library API, but this is only used within man-db. */ void decompress_inprocess_replace (decompress *d, char *buf, size_t len); /* Start the processes in a pipeline-based decompressor. Does nothing for * in-process decompressors. */ void decompress_start (decompress *d); /* Read len bytes of data from the decompressor, returning the data block. * len is updated with the number of bytes read. */ const char *decompress_read (decompress *d, size_t *len); /* Look ahead in the decompressor's output for len bytes of data, returning * the data block. len is updated with the number of bytes read. The * starting position of the next read or peek is not affected by this call. */ const char *decompress_peek (decompress *d, size_t *len); /* Skip over and discard len bytes of data from the peek cache. Asserts that * enough data is available to skip, so you may want to check using * pipeline_peek_size first. */ void decompress_peek_skip (decompress *d, size_t len); /* Read a line of data from the decompressor, returning it. */ const char *decompress_readline (decompress *d); /* Look ahead in the decompressor's output for a line of data, returning it. * The starting position of the next read or peek is not affected by this * call. */ const char *decompress_peekline (decompress *d); /* Wait for a decompressor to complete and return its combined exit status. * For in-process decompressors, simply returns 0. */ int decompress_wait (decompress *d); /* Destroy a decompressor. Safely does nothing on NULL. For pipeline-based * decompressors, may wait for the pipeline to complete if it has not already * done so. */ void decompress_free (decompress *d); #endif /* MAN_DECOMPRESS_H */