blob: 042e8dd47ecb10fe8141d2b02ad31a00083c179d [file] [log] [blame]
Angel Ponsebda03e2020-04-02 23:48:05 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin88b26b82017-03-24 17:10:51 -05002
3#include <commonlib/endian.h>
4#include <commonlib/iobuf.h>
5#include <string.h>
6
7static int ibuf_check_size(const struct ibuf *ib, size_t sz)
8{
9 if (ibuf_remaining(ib) < sz)
10 return -1;
11
12 return 0;
13}
14
15void ibuf_init(struct ibuf *ib, const void *b, size_t sz)
16{
17 ib->b = b;
18 ib->n_read = 0;
19 ib->capacity = sz;
20}
21
22void ibuf_from_obuf(struct ibuf *ib, const struct obuf *ob)
23{
24 ibuf_init(ib, ob->b, ob->n_written);
25}
26
27int ibuf_splice(const struct ibuf *src, struct ibuf *dst, size_t off, size_t sz)
28{
29 size_t end = off + sz;
30 size_t capacity = ibuf_capacity(src);
31 size_t nr_read = ibuf_nr_read(src);
32
33 if (end < off || end < sz || end > capacity)
34 return -1;
35
36 ibuf_init(dst, &src->b[off], sz);
37
38 /* Handle previously read data in src. */
39 if (off < nr_read)
40 dst->n_read = nr_read - off;
41
42 return 0;
43}
44
45int ibuf_splice_current(const struct ibuf *src, struct ibuf *dst, size_t sz)
46{
47 return ibuf_splice(src, dst, ibuf_nr_read(src), sz);
48}
49
50int ibuf_split(const struct ibuf *src, struct ibuf *a, struct ibuf *b,
51 size_t boundary)
52{
53 if (ibuf_splice(src, a, 0, boundary))
54 return -1;
55
56 return ibuf_splice(src, b, boundary, ibuf_capacity(src) - boundary);
57}
58
59const void *ibuf_oob_drain(struct ibuf *ib, size_t sz)
60{
61 const void *b;
62
63 if (ibuf_check_size(ib, sz))
64 return NULL;
65
66 b = &ib->b[ib->n_read];
67 ib->n_read += sz;
68
69 return b;
70}
71
72int ibuf_read(struct ibuf *ib, void *data, size_t sz)
73{
74 const void *b = ibuf_oob_drain(ib, sz);
75
76 if (b == NULL)
77 return -1;
78
79 memcpy(data, b, sz);
80
81 return 0;
82}
83
84int ibuf_read_be8(struct ibuf *ib, uint8_t *v)
85{
86 size_t sz = sizeof(*v);
87
88 if (ibuf_check_size(ib, sz))
89 return -1;
90
91 *v = read_at_be8(ib->b, ib->n_read);
92 ib->n_read += sz;
93
94 return 0;
95}
96
97int ibuf_read_be16(struct ibuf *ib, uint16_t *v)
98{
99 size_t sz = sizeof(*v);
100
101 if (ibuf_check_size(ib, sz))
102 return -1;
103
104 *v = read_at_be16(ib->b, ib->n_read);
105 ib->n_read += sz;
106
107 return 0;
108}
109
110int ibuf_read_be32(struct ibuf *ib, uint32_t *v)
111{
112 size_t sz = sizeof(*v);
113
114 if (ibuf_check_size(ib, sz))
115 return -1;
116
117 *v = read_at_be32(ib->b, ib->n_read);
118 ib->n_read += sz;
119
120 return 0;
121}
122
123int ibuf_read_be64(struct ibuf *ib, uint64_t *v)
124{
125 size_t sz = sizeof(*v);
126
127 if (ibuf_check_size(ib, sz))
128 return -1;
129
130 *v = read_at_be64(ib->b, ib->n_read);
131 ib->n_read += sz;
132
133 return 0;
134}
135
136int ibuf_read_le8(struct ibuf *ib, uint8_t *v)
137{
138 size_t sz = sizeof(*v);
139
140 if (ibuf_check_size(ib, sz))
141 return -1;
142
143 *v = read_at_le8(ib->b, ib->n_read);
144 ib->n_read += sz;
145
146 return 0;
147}
148
149int ibuf_read_le16(struct ibuf *ib, uint16_t *v)
150{
151 size_t sz = sizeof(*v);
152
153 if (ibuf_check_size(ib, sz))
154 return -1;
155
156 *v = read_at_le16(ib->b, ib->n_read);
157 ib->n_read += sz;
158
159 return 0;
160}
161
162int ibuf_read_le32(struct ibuf *ib, uint32_t *v)
163{
164 size_t sz = sizeof(*v);
165
166 if (ibuf_check_size(ib, sz))
167 return -1;
168
169 *v = read_at_le32(ib->b, ib->n_read);
170 ib->n_read += sz;
171
172 return 0;
173}
174
175int ibuf_read_le64(struct ibuf *ib, uint64_t *v)
176{
177 size_t sz = sizeof(*v);
178
179 if (ibuf_check_size(ib, sz))
180 return -1;
181
182 *v = read_at_le64(ib->b, ib->n_read);
183 ib->n_read += sz;
184
185 return 0;
186}
187
188int ibuf_read_n8(struct ibuf *ib, uint8_t *v)
189{
190 return ibuf_read(ib, v, sizeof(*v));
191}
192
193int ibuf_read_n16(struct ibuf *ib, uint16_t *v)
194{
195 return ibuf_read(ib, v, sizeof(*v));
196}
197
198int ibuf_read_n32(struct ibuf *ib, uint32_t *v)
199{
200 return ibuf_read(ib, v, sizeof(*v));
201}
202
203int ibuf_read_n64(struct ibuf *ib, uint64_t *v)
204{
205 return ibuf_read(ib, v, sizeof(*v));
206}
207
208static int obuf_check_size(const struct obuf *ob, size_t sz)
209{
210 if (obuf_remaining(ob) < sz)
211 return -1;
212
213 return 0;
214}
215
216void obuf_init(struct obuf *ob, void *b, size_t sz)
217{
218 ob->b = b;
219 ob->n_written = 0;
220 ob->capacity = sz;
221}
222
223int obuf_splice(const struct obuf *src, struct obuf *dst, size_t off, size_t sz)
224{
225 size_t end = off + sz;
226 size_t capacity = obuf_capacity(src);
227 size_t nr_written = obuf_nr_written(src);
228
229 if (end < off || end < sz || end > capacity)
230 return -1;
231
232 obuf_init(dst, &src->b[off], sz);
233
234 /* Handle previously written data in src. */
235 if (off < nr_written)
236 dst->n_written = nr_written - off;
237
238 return 0;
239}
240
241int obuf_splice_current(const struct obuf *src, struct obuf *dst, size_t sz)
242{
243 return obuf_splice(src, dst, obuf_nr_written(src), sz);
244}
245
246int obuf_split(const struct obuf *src, struct obuf *a, struct obuf *b,
247 size_t boundary)
248{
249 if (obuf_splice(src, a, 0, boundary))
250 return -1;
251
252 return obuf_splice(src, b, boundary, obuf_capacity(src) - boundary);
253}
254
255void *obuf_oob_fill(struct obuf *ob, size_t sz)
256{
257 void *b;
258
259 if (obuf_check_size(ob, sz))
260 return NULL;
261
262 b = &ob->b[ob->n_written];
263 ob->n_written += sz;
264
265 return b;
266}
267
268int obuf_write(struct obuf *ob, const void *data, size_t sz)
269{
270 void *b;
271
272 b = obuf_oob_fill(ob, sz);
273 if (b == NULL)
274 return -1;
275
276 memcpy(b, data, sz);
277
278 return 0;
279}
280
281int obuf_write_be8(struct obuf *ob, uint8_t v)
282{
283 size_t sz = sizeof(v);
284
285 if (obuf_check_size(ob, sz))
286 return -1;
287
288 write_at_be8(ob->b, v, ob->n_written);
289 ob->n_written += sz;
290
291 return 0;
292}
293
294int obuf_write_be16(struct obuf *ob, uint16_t v)
295{
296 size_t sz = sizeof(v);
297
298 if (obuf_check_size(ob, sz))
299 return -1;
300
301 write_at_be16(ob->b, v, ob->n_written);
302 ob->n_written += sz;
303
304 return 0;
305}
306
307int obuf_write_be32(struct obuf *ob, uint32_t v)
308{
309 size_t sz = sizeof(v);
310
311 if (obuf_check_size(ob, sz))
312 return -1;
313
314 write_at_be32(ob->b, v, ob->n_written);
315 ob->n_written += sz;
316
317 return 0;
318}
319
320int obuf_write_be64(struct obuf *ob, uint64_t v)
321{
322 size_t sz = sizeof(v);
323
324 if (obuf_check_size(ob, sz))
325 return -1;
326
327 write_at_be64(ob->b, v, ob->n_written);
328 ob->n_written += sz;
329
330 return 0;
331}
332
333int obuf_write_le8(struct obuf *ob, uint8_t v)
334{
335 size_t sz = sizeof(v);
336
337 if (obuf_check_size(ob, sz))
338 return -1;
339
340 write_at_le8(ob->b, v, ob->n_written);
341 ob->n_written += sz;
342
343 return 0;
344}
345
346int obuf_write_le16(struct obuf *ob, uint16_t v)
347{
348 size_t sz = sizeof(v);
349
350 if (obuf_check_size(ob, sz))
351 return -1;
352
353 write_at_le16(ob->b, v, ob->n_written);
354 ob->n_written += sz;
355
356 return 0;
357}
358
359int obuf_write_le32(struct obuf *ob, uint32_t v)
360{
361 size_t sz = sizeof(v);
362
363 if (obuf_check_size(ob, sz))
364 return -1;
365
366 write_at_le32(ob->b, v, ob->n_written);
367 ob->n_written += sz;
368
369 return 0;
370}
371
372int obuf_write_le64(struct obuf *ob, uint64_t v)
373{
374 size_t sz = sizeof(v);
375
376 if (obuf_check_size(ob, sz))
377 return -1;
378
379 write_at_le64(ob->b, v, ob->n_written);
380 ob->n_written += sz;
381
382 return 0;
383}
384
385int obuf_write_n8(struct obuf *ob, uint8_t v)
386{
387 return obuf_write(ob, &v, sizeof(v));
388}
389
390int obuf_write_n16(struct obuf *ob, uint16_t v)
391{
392 return obuf_write(ob, &v, sizeof(v));
393}
394
395int obuf_write_n32(struct obuf *ob, uint32_t v)
396{
397 return obuf_write(ob, &v, sizeof(v));
398}
399
400int obuf_write_n64(struct obuf *ob, uint64_t v)
401{
402 return obuf_write(ob, &v, sizeof(v));
403}
404
405const void *obuf_contents(const struct obuf *ob, size_t *sz)
406{
407 *sz = obuf_nr_written(ob);
408 return ob->b;
409}