LCOV - code coverage report
Current view: top level - cmdline - stream.h (source / functions) Hit Total Coverage
Test: lcov.info Lines: 37 41 90.2 %
Date: 2017-11-06 22:14:04 Functions: 10 11 90.9 %

          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             : 

Generated by: LCOV version 1.13