1 /* vim: set expandtab ts=4 sw=4: */
2 /*
3  * You may redistribute this program and/or modify it under the terms of
4  * the GNU General Public License as published by the Free Software Foundation,
5  * either version 3 of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
14  */
15 #ifndef Reader_H
16 #define Reader_H
17 
18 #include <stdint.h>
19 
20 /**
21  * Reader interface which reads data from a source and fails safe rather than overreading.
22  */
23 struct Reader {
24     /**
25      * Read some content from a buffer or other source.
26      *
27      * @param thisReader the Reader which is being called.
28      * @param readInto a pointer to a memory location which will have content written to it.
29      * @param length the number of bytes to read. If this number is 0 then the next
30      *               byte will be returned without incrementing the pointer.
31      * @return 0 if read went well, -1 if the content ran out and no more could be read.
32      */
33     int (* const read)(struct Reader* thisReader, void* readInto, unsigned long length);
34 
35     /**
36      * Advance the pointer a number of bytes without reading any.
37      * This function will happily skip off the end of the source and the next read will fail.
38      *
39      * @param thisReader the Reader which is being called.
40      * @param byteCount how far to advance the pointer.
41      */
42     void (* const skip)(struct Reader* thisReader, unsigned long byteCount);
43 
44     /** The total number of bytes which have been read OR SKIPPED by this reader. */
45     uint64_t bytesRead;
46 };
47 
48 
49 #define Reader_readGeneric(bytes) \
50     static inline uint##bytes##_t Reader_read##bytes (struct Reader* reader) \
51     {                                                                        \
52         uint##bytes##_t num;                                                 \
53         reader->read(reader, &num, bytes/8);                                 \
54         return num;                                                          \
55     }
56 
57 Reader_readGeneric(8)
58 Reader_readGeneric(16)
59 Reader_readGeneric(32)
60 Reader_readGeneric(64)
61 
62 
63 #define Reader_read(reader, readInto, bytes) \
64     (reader)->read((reader), (readInto), (bytes))
65 
66 #define Reader_skip(reader, bytes) \
67     (reader)->skip((reader), (bytes))
68 
69 #define Reader_bytesRead(reader) \
70     ((reader)->bytesRead + 0)
71 
72 #endif
73