1 /*
2 * decompress.h: interface to decompression abstraction layer
3 *
4 * Copyright (C) 2007 Colin Watson.
5 *
6 * This file is part of man-db.
7 *
8 * man-db is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * man-db is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with man-db; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
23 #ifndef MAN_DECOMPRESS_H
24 #define MAN_DECOMPRESS_H
25
26 #include <stdbool.h>
27
28 #include "pipeline.h"
29
30 struct decompress;
31 typedef struct decompress decompress;
32
33 /* Flags, combined using bitwise-or. */
34 enum {
35 /* Allow the resulting decompressor to be constructed by reading and
36 * buffering the decompressed file contents in-process, rather than
37 * by starting a subprocess and streaming the output. This is
38 * suitable if and only if the file contents are only going to be
39 * handled in-process rather than being passed as input to some
40 * other program, but if that is the case then this is a significant
41 * optimization.
42 */
43 DECOMPRESS_ALLOW_INPROCESS = 1
44 };
45
46 /* Open a decompressor reading from FILENAME. The caller must start the
47 * resulting decompressor. If the DECOMPRESS_ALLOW_INPROCESS flag is given,
48 * then the resulting decompressor may be in-process (in which case
49 * decompress_get_pipeline will fail).
50 */
51 decompress *decompress_open (const char *filename, int flags);
52
53 /* Open a decompressor reading from file descriptor FD. The caller must
54 * start the resulting decompressor. This always uses pipeline-based
55 * decompression, since if it attempted to decompress data in process it
56 * would be unable to recover if it found that the data was too large.
57 */
58 decompress *decompress_fdopen (int fd);
59
60 /* Return true if and only if this is a pipeline-based decompressor. */
61 bool decompress_is_pipeline (decompress *d);
62
63 /* Get the pipeline corresponding to a decompressor. Raises an assertion
64 * failure if this is not a pipeline-based decompressor.
65 */
66 pipeline *decompress_get_pipeline (decompress *d);
67
68 /* Return the start of the buffer stored in an in-process decompressor.
69 * Raises an assertion failure if this is not an in-process decompressor.
70 */
71 const char *decompress_inprocess_buf (decompress *d);
72
73 /* Return the total number of uncompressed bytes stored in an in-process
74 * decompressor. Raises an assertion failure if this is not an in-process
75 * decompressor.
76 */
77 size_t decompress_inprocess_len (decompress *d);
78
79 /* Replace an in-process decompressor's entire buffered file contents.
80 *
81 * In-process decompression works by buffering the whole file in memory,
82 * which works because we constrain it to only ever dealing with small
83 * files, and allows us to emulate streaming without having to resort to
84 * subprocesses, threads, or coroutines. However, there are some cases
85 * (notably encoding conversion) where it's useful to be able to do some
86 * kind of processing on the file contents in a way that similarly looks
87 * like streaming to its consumers. To allow for this, we allow consumers
88 * of decompressed data to replace the buffered file contents and reset the
89 * read offset so that their consumers in turn get the same useful read/peek
90 * API.
91 *
92 * This is of course a hack, and wouldn't be a wise thing to include in a
93 * general-purpose library API, but this is only used within man-db.
94 */
95 void decompress_inprocess_replace (decompress *d, char *buf, size_t len);
96
97 /* Start the processes in a pipeline-based decompressor. Does nothing for
98 * in-process decompressors.
99 */
100 void decompress_start (decompress *d);
101
102 /* Read len bytes of data from the decompressor, returning the data block.
103 * len is updated with the number of bytes read.
104 */
105 const char *decompress_read (decompress *d, size_t *len);
106
107 /* Look ahead in the decompressor's output for len bytes of data, returning
108 * the data block. len is updated with the number of bytes read. The
109 * starting position of the next read or peek is not affected by this call.
110 */
111 const char *decompress_peek (decompress *d, size_t *len);
112
113 /* Skip over and discard len bytes of data from the peek cache. Asserts that
114 * enough data is available to skip, so you may want to check using
115 * pipeline_peek_size first.
116 */
117 void decompress_peek_skip (decompress *d, size_t len);
118
119 /* Read a line of data from the decompressor, returning it. */
120 const char *decompress_readline (decompress *d);
121
122 /* Look ahead in the decompressor's output for a line of data, returning it.
123 * The starting position of the next read or peek is not affected by this
124 * call.
125 */
126 const char *decompress_peekline (decompress *d);
127
128 /* Wait for a decompressor to complete and return its combined exit status.
129 * For in-process decompressors, simply returns 0.
130 */
131 int decompress_wait (decompress *d);
132
133 /* Destroy a decompressor. Safely does nothing on NULL. For pipeline-based
134 * decompressors, may wait for the pipeline to complete if it has not already
135 * done so.
136 */
137 void decompress_free (decompress *d);
138
139 #endif /* MAN_DECOMPRESS_H */