Allow for static initialisation.
[libeze] / ez-blob-io.h
1 /* ez-blob-io.h: Common i/o utilities for serialisers
2
3    Copyright (C) 2019 Michael Zucchi
4
5    This program is free software: you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public License
7    as published by the Free Software Foundation, either version 3 of
8    the License, or (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with this program. If not, see
17    <http://www.gnu.org/licenses/>.
18 */
19
20 // Grow output as necessary
21 #define BLOBIO_WRITE_ALLOC 0
22 // Writing to pre-existing buffer
23 #define BLOBIO_WRITE_FIXED 1
24 // Calculating size only
25 #define BLOBIO_WRITE_SIZE 2
26 // Read mode
27 #define BLOBIO_READ 3
28
29 struct ez_blobio {
30         size_t index;
31         uint8_t *data;
32
33         // for read: upper limit
34         // for write: allocation size
35         size_t size;
36
37         // on read, non-zero means invalid
38         int error;
39         // io mode.
40         int mode;
41 };
42
43 /**
44  * Reserve write-space.
45  *
46  * For BLOBIO_WRITE_ALLOC mode this will fail if any allocation fails.
47  * 
48  * For BLOBIO_WRITE_FIXED this will fail if there is a buffer
49  * overflow.
50  *
51  * For BLOBIO_WRITE_SIZE this will never fail.
52  *
53  * @param io
54  * @param len length required
55  * @return base of memory, or NULL on error.
56  */
57 void *blobio_reserve(struct ez_blobio *io, size_t len);
58
59 /**
60  * Take read-space.
61  *
62  * For BLOBIO_READ this will fail if there is a buffer underflow.
63  *
64  * @param io
65  * @param len Length required.
66  * @return base of memory or NULL on error.
67  */
68 void *blobio_take(struct ez_blobio *io, size_t len);
69
70 /**
71  * Align write output.
72  *
73  * Data is padded with 0 bytes.
74  *
75  * @param io
76  * @param step must be power of 2.
77  */
78 void blobio_write_align(struct ez_blobio *io, unsigned int step);
79
80 /**
81  * Align read input.
82  *
83  * @param io
84  * @param step must be power of 2.
85  */
86 void blobio_read_align(struct ez_blobio *io, unsigned int step);
87
88 /**
89  * Dump binary data in human-readable hex+ascii format.
90  * @todo rename ez_blob_dump(prefix, ez_blob)?
91  */
92 void blobio_dumphex(const char *data, size_t size, const char *prefix);
93
94 /*
95   The read and write functions read or write the type and silently
96   perform no-operation on error.  The error can be checked via
97   io.error being non-zero.
98
99   @todo I don't think there's any point in making these inline if it just
100   calls an external function anyway.
101  */
102
103 static __inline__  void blobio_write(struct ez_blobio *io, const void *data, size_t len) {
104         void *v = blobio_reserve(io, len);
105         if (v) memcpy(v, data, len);
106 }
107
108 static __inline__ void blobio_writeb(struct ez_blobio *io, uint8_t val) {
109         uint8_t *v = blobio_reserve(io, 1);
110         if (v) *v = val;
111 }
112
113 static __inline__ void blobio_write8(struct ez_blobio *io, uint8_t val) {
114         uint8_t *v = blobio_reserve(io, 1);
115         if (v) *v = val;
116 }
117
118 static __inline__ void blobio_write16(struct ez_blobio *io, uint16_t val) {
119         uint16_t *v = blobio_reserve(io, 2);
120         if (v) *v = val;
121 }
122
123 static __inline__ void blobio_write32(struct ez_blobio *io, uint32_t val) {
124         uint32_t *v = blobio_reserve(io, 4);
125         if (v) *v = val;
126 }
127
128 static __inline__ void blobio_write64(struct ez_blobio *io, uint64_t val) {
129         uint64_t *v = blobio_reserve(io, 8);
130         if (v) *v = val;
131 }
132
133 static __inline__ void blobio_writef(struct ez_blobio *io, float val) {
134         float *v = blobio_reserve(io, 4);
135         if (v) *v = val;
136 }
137
138 static __inline__ void blobio_writed(struct ez_blobio *io, double val) {
139         double *v = blobio_reserve(io, 8);
140         if (v) *v = val;
141 }
142
143 static __inline__ uint8_t blobio_readi8(struct ez_blobio *io) {
144         uint8_t *v = blobio_take(io, 1);
145         return v ? *v : 0;
146 }
147
148 static __inline__ uint16_t blobio_readi16(struct ez_blobio *io) {
149         uint16_t *v = blobio_take(io, 2);
150         return v ? *v : 0;
151 }
152
153 static __inline__ uint32_t blobio_readi32(struct ez_blobio *io) {
154         uint32_t *v = blobio_take(io, 4);
155         return v ? *v : 0;
156 }
157
158 static __inline__ uint64_t blobio_readi64(struct ez_blobio *io) {
159         uint64_t *v = blobio_take(io, 8);
160         return v ? *v : 0;
161 }
162
163 static __inline__ float blobio_readf(struct ez_blobio *io) {
164         float *v = blobio_take(io, 4);
165         return v ? *v : 0.0f;
166 }
167
168 static __inline__ double blobio_readd(struct ez_blobio *io) {
169         double *v = blobio_take(io, 8);
170         return v ? *v : 0.0;
171 }