Line data Source code
1 : /*
2 : * Copyright (C) 2011 Andrea Mazzoleni
3 : *
4 : * This program is free software: you can redistribute it and/or modify
5 : * it under the terms of the GNU General Public License as published by
6 : * the Free Software Foundation, either version 3 of the License, or
7 : * (at your option) any later version.
8 : *
9 : * This program is distributed in the hope that it will be useful,
10 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : * GNU General Public License for more details.
13 : *
14 : * You should have received a copy of the GNU General Public License
15 : * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 : */
17 :
18 : #ifndef __STREAM_H
19 : #define __STREAM_H
20 :
21 : #include "util.h"
22 :
23 : /****************************************************************************/
24 : /* stream */
25 :
26 : /**
27 : * Size of the buffer of the stream.
28 : *
29 : * It's not a constant for testing purpose.
30 : */
31 : unsigned STREAM_SIZE;
32 :
33 : #define STREAM_STATE_READ 0 /**< The stream is in a normal state of read. */
34 : #define STREAM_STATE_WRITE 1 /**< The stream is in a normal state of write. */
35 : #define STREAM_STATE_ERROR -1 /**< An error was encountered. */
36 : #define STREAM_STATE_EOF 2 /**< The end of file was encountered. */
37 :
38 : struct stream_handle {
39 : int f; /**< Handle of the file. */
40 : char path[PATH_MAX]; /**< Path of the file. */
41 : };
42 :
43 : struct stream {
44 : unsigned char* buffer; /**< Buffer of the stream. */
45 : unsigned char* pos; /**< Current position in the buffer. */
46 : unsigned char* end; /**< End position of the buffer. */
47 : int state; /**< State of the stream. One of STREAM_STATE. */
48 : int state_index; /**< Index of the handle causing a state change. */
49 : unsigned handle_size; /**< Number of handles. */
50 : struct stream_handle* handle; /**< Set of handles. */
51 : off_t offset; /**< Offset into the file. */
52 : off_t offset_uncached; /**< Offset into the file excluding the cached data. */
53 :
54 : /**
55 : * CRC of the data read or written in the file.
56 : *
57 : * If reading, it's the CRC of all data read from the file,
58 : * including the one in the buffer.
59 : * If writing it's all the data wrote to the file,
60 : * excluding the one still in buffer yet to be written.
61 : */
62 : uint32_t crc;
63 :
64 : /**
65 : * CRC of the file excluding the cached data in the buffer.
66 : *
67 : * If reading, it's the CRC of the data read from the file,
68 : * excluding the one in the buffer.
69 : * If writing it's all the data wrote to the file,
70 : * excluding the one still in buffer yet to be written.
71 : */
72 : uint32_t crc_uncached;
73 :
74 : /**
75 : * CRC of the data written to the stream.
76 : *
77 : * This is an extra check of the data that is written to
78 : * file to ensure that it's consistent even in case
79 : * of memory errors.
80 : *
81 : * This extra check takes about 2 seconds for each GB of
82 : * content file with the Intel CRC instruction,
83 : * and about 4 seconds without it.
84 : * But usually this doesn't slow down the write process,
85 : * as the disk is the bottle-neck.
86 : *
87 : * Note that this CRC doesn't have the IV processing.
88 : *
89 : * Not used in reading.
90 : * In writing, it's all the data wrote calling sput() functions.
91 : */
92 : uint32_t crc_stream;
93 : };
94 :
95 : /**
96 : * Opaque STREAM type. Like ::FILE.
97 : */
98 : typedef struct stream STREAM;
99 :
100 : /**
101 : * Open a stream for reading. Like fopen("r").
102 : */
103 : STREAM* sopen_read(const char* file);
104 :
105 : /**
106 : * Open a stream for writing. Like fopen("w").
107 : */
108 : STREAM* sopen_write(const char* file);
109 :
110 : /**
111 : * Open a set of streams for writing. Like fopen("w").
112 : */
113 : STREAM* sopen_multi_write(unsigned count);
114 :
115 : /**
116 : * Specify the file to open.
117 : */
118 : int sopen_multi_file(STREAM* s, unsigned i, const char* file);
119 :
120 : /**
121 : * Close a stream. Like fclose().
122 : */
123 : int sclose(STREAM* s);
124 :
125 : /**
126 : * Return the handle of the file.
127 : * In case of multi file, the first one is returned.
128 : */
129 : int shandle(STREAM* s);
130 :
131 : /**
132 : * Read the stream until the end, and return the latest 4 chars.
133 : * The CRC of the file is also computed, and you can get it using scrc().
134 : * \return 0 on success, or EOF on error.
135 : */
136 : int sdeplete(STREAM* s, unsigned char* last);
137 :
138 : /**
139 : * Flush the write stream buffer.
140 : * \return 0 on success, or EOF on error.
141 : */
142 : int sflush(STREAM* s);
143 :
144 : /**
145 : * Get the file pointer.
146 : */
147 : int64_t stell(STREAM* s);
148 :
149 : /**
150 : * Get the CRC of the processed data.
151 : */
152 : uint32_t scrc(STREAM* s);
153 :
154 : /**
155 : * Get the CRC of the processed data in put.
156 : */
157 : uint32_t scrc_stream(STREAM* s);
158 :
159 : /**
160 : * Check if the buffer has enough data loaded.
161 : */
162 33540491 : static inline int sptrlookup(STREAM* s, int size)
163 : {
164 33540491 : return s->pos + size <= s->end;
165 : }
166 :
167 : /**
168 : * Get the current stream ptr.
169 : */
170 33502235 : static inline unsigned char* sptrget(STREAM* s)
171 : {
172 33502235 : return s->pos;
173 : }
174 :
175 : /**
176 : * Set the current stream ptr.
177 : */
178 33502235 : static inline void sptrset(STREAM* s, unsigned char* ptr)
179 : {
180 33502235 : s->pos = ptr;
181 33502235 : }
182 :
183 : /**
184 : * Check the error status. Like ferror().
185 : */
186 3635426 : static inline int serror(STREAM* s)
187 : {
188 3635426 : return s->state == STREAM_STATE_ERROR;
189 : }
190 :
191 : /**
192 : * Check the eof status. Like feof().
193 : */
194 1 : static inline int seof(STREAM* s)
195 : {
196 1 : return s->state == STREAM_STATE_EOF;
197 : }
198 :
199 : /**
200 : * Get the index of the handle that caused the error.
201 : */
202 : static inline int serrorindex(STREAM* s)
203 : {
204 : return s->state_index;
205 : }
206 :
207 : /**
208 : * Get the path of the handle that caused the error.
209 : */
210 0 : static inline const char* serrorfile(STREAM* s)
211 : {
212 0 : return s->handle[s->state_index].path;
213 : }
214 :
215 : /**
216 : * Sync the stream. Like fsync().
217 : */
218 : int ssync(STREAM* s);
219 :
220 : /****************************************************************************/
221 : /* get */
222 :
223 : /**
224 : * \internal Used by sgetc().
225 : * \note Don't call this directly, but use sgetc().
226 : */
227 : int sgetc_uncached(STREAM* s);
228 :
229 : /**
230 : * Read a char. Like fgetc().
231 : */
232 84976655 : static inline int sgetc(STREAM* s)
233 : {
234 84976655 : if (tommy_unlikely(s->pos == s->end))
235 298863 : return sgetc_uncached(s);
236 84677792 : return *s->pos++;
237 : }
238 :
239 : /**
240 : * Unread a char.
241 : * Like ungetc() but you have to unget the same char read.
242 : */
243 34584 : static inline void sungetc(int c, STREAM* s)
244 : {
245 34584 : if (c != EOF)
246 33789 : --s->pos;
247 34584 : }
248 :
249 : /**
250 : * Read a fixed amount of chars.
251 : * Return 0 on success, or -1 on error.
252 : */
253 : int sread(STREAM* f, void* void_data, unsigned size);
254 :
255 : /**
256 : * Get a char from a stream, ignoring one '\r'.
257 : */
258 6244 : static inline int sgeteol(STREAM* f)
259 : {
260 : int c;
261 :
262 6244 : c = sgetc(f);
263 6244 : if (c == '\r')
264 0 : c = sgetc(f);
265 :
266 6244 : return c;
267 : }
268 :
269 : /**
270 : * Read all the spaces and tabs.
271 : * Return the number of spaces and tabs read.
272 : */
273 20685 : static inline int sgetspace(STREAM* f)
274 : {
275 20685 : int count = 0;
276 : int c;
277 :
278 20685 : c = sgetc(f);
279 49035 : while (c == ' ' || c == '\t') {
280 7665 : ++count;
281 7665 : c = sgetc(f);
282 : }
283 :
284 20685 : sungetc(c, f);
285 20685 : return count;
286 : }
287 :
288 : /**
289 : * Read until the first space or tab.
290 : * Stop at the first ' ', '\t', '\n' or EOF.
291 : * Return <0 if the buffer is too small, or the number of chars read.
292 : */
293 : int sgettok(STREAM* f, char* str, int size);
294 :
295 : /**
296 : * Read until the end of line.
297 : * Stop at the first '\n' or EOF. Note that '\n' is left in the stream.
298 : * Return <0 if the buffer is too small, or the number of chars read.
299 : */
300 : int sgetline(STREAM* f, char* str, int size);
301 :
302 : /**
303 : * Like sgetline() but remove ' ' and '\t' at the end.
304 : */
305 : int sgetlasttok(STREAM* f, char* str, int size);
306 :
307 : /**
308 : * Read a 32 bit number.
309 : * Stop at the first not digit char or EOF.
310 : * Return <0 if there isn't enough to read.
311 : */
312 : int sgetu32(STREAM* f, uint32_t* value);
313 :
314 : /****************************************************************************/
315 : /* binary get */
316 :
317 : /**
318 : * Read a binary 32 bit number in packet format.
319 : * Return <0 if there isn't enough to read.
320 : */
321 : int sgetb32(STREAM* f, uint32_t* value);
322 :
323 : /**
324 : * Read a binary 64 bit number in packet format.
325 : * Return <0 if there isn't enough to read.
326 : */
327 : int sgetb64(STREAM* f, uint64_t* value);
328 :
329 : /**
330 : * Read a binary 32 bit number in little endian format.
331 : * Return <0 if there isn't enough to read.
332 : */
333 : int sgetble32(STREAM* f, uint32_t* value);
334 :
335 : /**
336 : * Read a binary string.
337 : * Return -1 on error or if the buffer is too small, or the number of chars read.
338 : */
339 : int sgetbs(STREAM* f, char* str, int size);
340 :
341 : /****************************************************************************/
342 : /* put */
343 :
344 : /**
345 : * Write a char. Like fputc().
346 : * Return 0 on success or -1 on error.
347 : */
348 3809331 : static inline int sputc(int c, STREAM* s)
349 : {
350 3809331 : if (s->pos == s->end) {
351 38580 : if (sflush(s) != 0)
352 0 : return -1;
353 : }
354 :
355 : /**
356 : * Update the crc *before* writing the data in the buffer
357 : *
358 : * This must be done before the memory write,
359 : * to be able to detect memory errors on the buffer,
360 : * happening before we write it on the file.
361 : */
362 3809331 : s->crc_stream = crc32c_plain_char(s->crc_stream, c);
363 :
364 3809331 : *s->pos++ = c;
365 :
366 3809331 : return 0;
367 : }
368 :
369 : /**
370 : * Write a end of line.
371 : * Return 0 on success or -1 on error.
372 : */
373 : static inline int sputeol(STREAM* s)
374 : {
375 : #ifdef _WIN32
376 : if (sputc('\r', s) != 0)
377 : return -1;
378 : #endif
379 : return sputc('\n', s);
380 : }
381 :
382 : /**
383 : * Write a sized string.
384 : * Return 0 on success or -1 on error.
385 : */
386 : int swrite(const void* data, unsigned size, STREAM* f);
387 :
388 : /****************************************************************************/
389 : /* binary put */
390 :
391 : /**
392 : * Write a binary 32 bit number in packed format.
393 : * Return 0 on success or -1 on error.
394 : */
395 : int sputb32(uint32_t value, STREAM* s);
396 :
397 : /**
398 : * Write a binary 64 bit number in packed format.
399 : * Return 0 on success or -1 on error.
400 : */
401 : int sputb64(uint64_t value, STREAM* s);
402 :
403 : /**
404 : * Write a binary 32 bit number in little endian format.
405 : * Return 0 on success or -1 on error.
406 : */
407 : int sputble32(uint32_t value, STREAM* s);
408 :
409 : /**
410 : * Write a binary string.
411 : * Return 0 on success or -1 on error.
412 : */
413 : int sputbs(const char* str, STREAM* s);
414 :
415 : #endif
416 :
|