xref: /freebsd/contrib/libcbor/src/cbor/streaming.c (revision 1323ec57)
1 /*
2  * Copyright (c) 2014-2020 Pavel Kalvoda <me@pavelkalvoda.com>
3  *
4  * libcbor is free software; you can redistribute it and/or modify
5  * it under the terms of the MIT license. See LICENSE for details.
6  */
7 
8 #include "streaming.h"
9 #include "internal/loaders.h"
10 
11 bool static claim_bytes(size_t required, size_t provided,
12                         struct cbor_decoder_result *result) {
13   if (required > (provided - result->read)) {
14     result->required = required + result->read;
15     result->read = 0;
16     result->status = CBOR_DECODER_NEDATA;
17     return false;
18   } else {
19     result->read += required;
20     result->required = 0;
21     return true;
22   }
23 }
24 
25 struct cbor_decoder_result cbor_stream_decode(
26     cbor_data source, size_t source_size,
27     const struct cbor_callbacks *callbacks, void *context) {
28   // Attempt to claim the initial MTB byte
29   struct cbor_decoder_result result = {.status = CBOR_DECODER_FINISHED};
30   if (!claim_bytes(1, source_size, &result)) {
31     return result;
32   }
33 
34   switch (*source) {
35     case 0x00: /* Fallthrough */
36     case 0x01: /* Fallthrough */
37     case 0x02: /* Fallthrough */
38     case 0x03: /* Fallthrough */
39     case 0x04: /* Fallthrough */
40     case 0x05: /* Fallthrough */
41     case 0x06: /* Fallthrough */
42     case 0x07: /* Fallthrough */
43     case 0x08: /* Fallthrough */
44     case 0x09: /* Fallthrough */
45     case 0x0A: /* Fallthrough */
46     case 0x0B: /* Fallthrough */
47     case 0x0C: /* Fallthrough */
48     case 0x0D: /* Fallthrough */
49     case 0x0E: /* Fallthrough */
50     case 0x0F: /* Fallthrough */
51     case 0x10: /* Fallthrough */
52     case 0x11: /* Fallthrough */
53     case 0x12: /* Fallthrough */
54     case 0x13: /* Fallthrough */
55     case 0x14: /* Fallthrough */
56     case 0x15: /* Fallthrough */
57     case 0x16: /* Fallthrough */
58     case 0x17:
59       /* Embedded one byte unsigned integer */
60       {
61         callbacks->uint8(context, _cbor_load_uint8(source));
62         return result;
63       }
64     case 0x18:
65       /* One byte unsigned integer */
66       {
67         if (claim_bytes(1, source_size, &result)) {
68           callbacks->uint8(context, _cbor_load_uint8(source + 1));
69         }
70         return result;
71       }
72     case 0x19:
73       /* Two bytes unsigned integer */
74       {
75         if (claim_bytes(2, source_size, &result)) {
76           callbacks->uint16(context, _cbor_load_uint16(source + 1));
77         }
78         return result;
79       }
80     case 0x1A:
81       /* Four bytes unsigned integer */
82       {
83         if (claim_bytes(4, source_size, &result)) {
84           callbacks->uint32(context, _cbor_load_uint32(source + 1));
85         }
86         return result;
87       }
88     case 0x1B:
89       /* Eight bytes unsigned integer */
90       {
91         if (claim_bytes(8, source_size, &result)) {
92           callbacks->uint64(context, _cbor_load_uint64(source + 1));
93         }
94         return result;
95       }
96     case 0x1C: /* Fallthrough */
97     case 0x1D: /* Fallthrough */
98     case 0x1E: /* Fallthrough */
99     case 0x1F:
100       /* Reserved */
101       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
102     case 0x20: /* Fallthrough */
103     case 0x21: /* Fallthrough */
104     case 0x22: /* Fallthrough */
105     case 0x23: /* Fallthrough */
106     case 0x24: /* Fallthrough */
107     case 0x25: /* Fallthrough */
108     case 0x26: /* Fallthrough */
109     case 0x27: /* Fallthrough */
110     case 0x28: /* Fallthrough */
111     case 0x29: /* Fallthrough */
112     case 0x2A: /* Fallthrough */
113     case 0x2B: /* Fallthrough */
114     case 0x2C: /* Fallthrough */
115     case 0x2D: /* Fallthrough */
116     case 0x2E: /* Fallthrough */
117     case 0x2F: /* Fallthrough */
118     case 0x30: /* Fallthrough */
119     case 0x31: /* Fallthrough */
120     case 0x32: /* Fallthrough */
121     case 0x33: /* Fallthrough */
122     case 0x34: /* Fallthrough */
123     case 0x35: /* Fallthrough */
124     case 0x36: /* Fallthrough */
125     case 0x37:
126       /* Embedded one byte negative integer */
127       {
128         callbacks->negint8(context,
129                            _cbor_load_uint8(source) - 0x20); /* 0x20 offset */
130         return result;
131       }
132     case 0x38:
133       /* One byte negative integer */
134       {
135         if (claim_bytes(1, source_size, &result)) {
136           callbacks->negint8(context, _cbor_load_uint8(source + 1));
137         }
138         return result;
139       }
140     case 0x39:
141       /* Two bytes negative integer */
142       {
143         if (claim_bytes(2, source_size, &result)) {
144           callbacks->negint16(context, _cbor_load_uint16(source + 1));
145         }
146         return result;
147       }
148     case 0x3A:
149       /* Four bytes negative integer */
150       {
151         if (claim_bytes(4, source_size, &result)) {
152           callbacks->negint32(context, _cbor_load_uint32(source + 1));
153         }
154         return result;
155       }
156     case 0x3B:
157       /* Eight bytes negative integer */
158       {
159         if (claim_bytes(8, source_size, &result)) {
160           callbacks->negint64(context, _cbor_load_uint64(source + 1));
161         }
162         return result;
163       }
164     case 0x3C: /* Fallthrough */
165     case 0x3D: /* Fallthrough */
166     case 0x3E: /* Fallthrough */
167     case 0x3F:
168       /* Reserved */
169       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
170     case 0x40: /* Fallthrough */
171     case 0x41: /* Fallthrough */
172     case 0x42: /* Fallthrough */
173     case 0x43: /* Fallthrough */
174     case 0x44: /* Fallthrough */
175     case 0x45: /* Fallthrough */
176     case 0x46: /* Fallthrough */
177     case 0x47: /* Fallthrough */
178     case 0x48: /* Fallthrough */
179     case 0x49: /* Fallthrough */
180     case 0x4A: /* Fallthrough */
181     case 0x4B: /* Fallthrough */
182     case 0x4C: /* Fallthrough */
183     case 0x4D: /* Fallthrough */
184     case 0x4E: /* Fallthrough */
185     case 0x4F: /* Fallthrough */
186     case 0x50: /* Fallthrough */
187     case 0x51: /* Fallthrough */
188     case 0x52: /* Fallthrough */
189     case 0x53: /* Fallthrough */
190     case 0x54: /* Fallthrough */
191     case 0x55: /* Fallthrough */
192     case 0x56: /* Fallthrough */
193     case 0x57:
194       /* Embedded length byte string */
195       {
196         size_t length =
197             (size_t)_cbor_load_uint8(source) - 0x40; /* 0x40 offset */
198         if (claim_bytes(length, source_size, &result)) {
199           callbacks->byte_string(context, source + 1, length);
200         }
201         return result;
202       }
203     case 0x58:
204       /* One byte length byte string */
205       // TODO template this?
206       {
207         if (claim_bytes(1, source_size, &result)) {
208           size_t length = (size_t)_cbor_load_uint8(source + 1);
209           if (claim_bytes(length, source_size, &result)) {
210             callbacks->byte_string(context, source + 1 + 1, length);
211           }
212         }
213         return result;
214       }
215     case 0x59:
216       /* Two bytes length byte string */
217       {
218         if (claim_bytes(2, source_size, &result)) {
219           size_t length = (size_t)_cbor_load_uint16(source + 1);
220           if (claim_bytes(length, source_size, &result)) {
221             callbacks->byte_string(context, source + 1 + 2, length);
222           }
223         }
224         return result;
225       }
226     case 0x5A:
227       /* Four bytes length byte string */
228       {
229         if (claim_bytes(4, source_size, &result)) {
230           size_t length = (size_t)_cbor_load_uint32(source + 1);
231           if (claim_bytes(length, source_size, &result)) {
232             callbacks->byte_string(context, source + 1 + 4, length);
233           }
234         }
235         return result;
236       }
237     case 0x5B:
238       /* Eight bytes length byte string */
239       {
240         if (claim_bytes(8, source_size, &result)) {
241           size_t length = (size_t)_cbor_load_uint64(source + 1);
242           if (claim_bytes(length, source_size, &result)) {
243             callbacks->byte_string(context, source + 1 + 8, length);
244           }
245         }
246         return result;
247       }
248     case 0x5C: /* Fallthrough */
249     case 0x5D: /* Fallthrough */
250     case 0x5E:
251       /* Reserved */
252       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
253     case 0x5F:
254       /* Indefinite byte string */
255       {
256         callbacks->byte_string_start(context);
257         return result;
258       }
259     case 0x60: /* Fallthrough */
260     case 0x61: /* Fallthrough */
261     case 0x62: /* Fallthrough */
262     case 0x63: /* Fallthrough */
263     case 0x64: /* Fallthrough */
264     case 0x65: /* Fallthrough */
265     case 0x66: /* Fallthrough */
266     case 0x67: /* Fallthrough */
267     case 0x68: /* Fallthrough */
268     case 0x69: /* Fallthrough */
269     case 0x6A: /* Fallthrough */
270     case 0x6B: /* Fallthrough */
271     case 0x6C: /* Fallthrough */
272     case 0x6D: /* Fallthrough */
273     case 0x6E: /* Fallthrough */
274     case 0x6F: /* Fallthrough */
275     case 0x70: /* Fallthrough */
276     case 0x71: /* Fallthrough */
277     case 0x72: /* Fallthrough */
278     case 0x73: /* Fallthrough */
279     case 0x74: /* Fallthrough */
280     case 0x75: /* Fallthrough */
281     case 0x76: /* Fallthrough */
282     case 0x77:
283       /* Embedded one byte length string */
284       {
285         size_t length =
286             (size_t)_cbor_load_uint8(source) - 0x60; /* 0x60 offset */
287         if (claim_bytes(length, source_size, &result)) {
288           callbacks->string(context, source + 1, length);
289         }
290         return result;
291       }
292     case 0x78:
293       /* One byte length string */
294       {
295         if (claim_bytes(1, source_size, &result)) {
296           size_t length = (size_t)_cbor_load_uint8(source + 1);
297           if (claim_bytes(length, source_size, &result)) {
298             callbacks->string(context, source + 1 + 1, length);
299           }
300         }
301         return result;
302       }
303     case 0x79:
304       /* Two bytes length string */
305       {
306         if (claim_bytes(2, source_size, &result)) {
307           size_t length = (size_t)_cbor_load_uint16(source + 1);
308           if (claim_bytes(length, source_size, &result)) {
309             callbacks->string(context, source + 1 + 2, length);
310           }
311         }
312         return result;
313       }
314     case 0x7A:
315       /* Four bytes length string */
316       {
317         if (claim_bytes(4, source_size, &result)) {
318           size_t length = (size_t)_cbor_load_uint32(source + 1);
319           if (claim_bytes(length, source_size, &result)) {
320             callbacks->string(context, source + 1 + 4, length);
321           }
322         }
323         return result;
324       }
325     case 0x7B:
326       /* Eight bytes length string */
327       {
328         if (claim_bytes(8, source_size, &result)) {
329           size_t length = (size_t)_cbor_load_uint64(source + 1);
330           if (claim_bytes(length, source_size, &result)) {
331             callbacks->string(context, source + 1 + 8, length);
332           }
333         }
334         return result;
335       }
336     case 0x7C: /* Fallthrough */
337     case 0x7D: /* Fallthrough */
338     case 0x7E:
339       /* Reserved */
340       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
341     case 0x7F:
342       /* Indefinite length string */
343       {
344         callbacks->string_start(context);
345         return result;
346       }
347     case 0x80: /* Fallthrough */
348     case 0x81: /* Fallthrough */
349     case 0x82: /* Fallthrough */
350     case 0x83: /* Fallthrough */
351     case 0x84: /* Fallthrough */
352     case 0x85: /* Fallthrough */
353     case 0x86: /* Fallthrough */
354     case 0x87: /* Fallthrough */
355     case 0x88: /* Fallthrough */
356     case 0x89: /* Fallthrough */
357     case 0x8A: /* Fallthrough */
358     case 0x8B: /* Fallthrough */
359     case 0x8C: /* Fallthrough */
360     case 0x8D: /* Fallthrough */
361     case 0x8E: /* Fallthrough */
362     case 0x8F: /* Fallthrough */
363     case 0x90: /* Fallthrough */
364     case 0x91: /* Fallthrough */
365     case 0x92: /* Fallthrough */
366     case 0x93: /* Fallthrough */
367     case 0x94: /* Fallthrough */
368     case 0x95: /* Fallthrough */
369     case 0x96: /* Fallthrough */
370     case 0x97:
371       /* Embedded one byte length array */
372       {
373         callbacks->array_start(
374             context, (size_t)_cbor_load_uint8(source) - 0x80); /* 0x40 offset */
375         return result;
376       }
377     case 0x98:
378       /* One byte length array */
379       {
380         if (claim_bytes(1, source_size, &result)) {
381           callbacks->array_start(context, (size_t)_cbor_load_uint8(source + 1));
382         }
383         return result;
384       }
385     case 0x99:
386       /* Two bytes length array */
387       {
388         if (claim_bytes(2, source_size, &result)) {
389           callbacks->array_start(context,
390                                  (size_t)_cbor_load_uint16(source + 1));
391         }
392         return result;
393       }
394     case 0x9A:
395       /* Four bytes length array */
396       {
397         if (claim_bytes(4, source_size, &result)) {
398           callbacks->array_start(context,
399                                  (size_t)_cbor_load_uint32(source + 1));
400         }
401         return result;
402       }
403     case 0x9B:
404       /* Eight bytes length array */
405       {
406         if (claim_bytes(8, source_size, &result)) {
407           callbacks->array_start(context,
408                                  (size_t)_cbor_load_uint64(source + 1));
409         }
410         return result;
411       }
412     case 0x9C: /* Fallthrough */
413     case 0x9D: /* Fallthrough */
414     case 0x9E:
415       /* Reserved */
416       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
417     case 0x9F:
418       /* Indefinite length array */
419       {
420         callbacks->indef_array_start(context);
421         return result;
422       }
423     case 0xA0: /* Fallthrough */
424     case 0xA1: /* Fallthrough */
425     case 0xA2: /* Fallthrough */
426     case 0xA3: /* Fallthrough */
427     case 0xA4: /* Fallthrough */
428     case 0xA5: /* Fallthrough */
429     case 0xA6: /* Fallthrough */
430     case 0xA7: /* Fallthrough */
431     case 0xA8: /* Fallthrough */
432     case 0xA9: /* Fallthrough */
433     case 0xAA: /* Fallthrough */
434     case 0xAB: /* Fallthrough */
435     case 0xAC: /* Fallthrough */
436     case 0xAD: /* Fallthrough */
437     case 0xAE: /* Fallthrough */
438     case 0xAF: /* Fallthrough */
439     case 0xB0: /* Fallthrough */
440     case 0xB1: /* Fallthrough */
441     case 0xB2: /* Fallthrough */
442     case 0xB3: /* Fallthrough */
443     case 0xB4: /* Fallthrough */
444     case 0xB5: /* Fallthrough */
445     case 0xB6: /* Fallthrough */
446     case 0xB7:
447       /* Embedded one byte length map */
448       {
449         callbacks->map_start(
450             context, (size_t)_cbor_load_uint8(source) - 0xA0); /* 0xA0 offset */
451         return result;
452       }
453     case 0xB8:
454       /* One byte length map */
455       {
456         if (claim_bytes(1, source_size, &result)) {
457           callbacks->map_start(context, (size_t)_cbor_load_uint8(source + 1));
458         }
459         return result;
460       }
461     case 0xB9:
462       /* Two bytes length map */
463       {
464         if (claim_bytes(2, source_size, &result)) {
465           callbacks->map_start(context, (size_t)_cbor_load_uint16(source + 1));
466         }
467         return result;
468       }
469     case 0xBA:
470       /* Four bytes length map */
471       {
472         if (claim_bytes(4, source_size, &result)) {
473           callbacks->map_start(context, (size_t)_cbor_load_uint32(source + 1));
474         }
475         return result;
476       }
477     case 0xBB:
478       /* Eight bytes length map */
479       {
480         if (claim_bytes(8, source_size, &result)) {
481           callbacks->map_start(context, (size_t)_cbor_load_uint64(source + 1));
482         }
483         return result;
484       }
485     case 0xBC: /* Fallthrough */
486     case 0xBD: /* Fallthrough */
487     case 0xBE:
488       /* Reserved */
489       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
490     case 0xBF:
491       /* Indefinite length map */
492       {
493         callbacks->indef_map_start(context);
494         return result;
495       }
496     case 0xC0:
497       /* Text date/time - RFC 3339 tag, fallthrough */
498     case 0xC1:
499       /* Epoch date tag, fallthrough */
500     case 0xC2:
501       /* Positive bignum tag, fallthrough */
502     case 0xC3:
503       /* Negative bignum tag, fallthrough */
504     case 0xC4:
505       /* Fraction, fallthrough */
506     case 0xC5:
507       /* Big float */
508       {
509         callbacks->tag(context,
510                        _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */
511         return result;
512       }
513     case 0xC6: /* Fallthrough */
514     case 0xC7: /* Fallthrough */
515     case 0xC8: /* Fallthrough */
516     case 0xC9: /* Fallthrough */
517     case 0xCA: /* Fallthrough */
518     case 0xCB: /* Fallthrough */
519     case 0xCC: /* Fallthrough */
520     case 0xCD: /* Fallthrough */
521     case 0xCE: /* Fallthrough */
522     case 0xCF: /* Fallthrough */
523     case 0xD0: /* Fallthrough */
524     case 0xD1: /* Fallthrough */
525     case 0xD2: /* Fallthrough */
526     case 0xD3: /* Fallthrough */
527     case 0xD4: /* Unassigned tag value */
528     {
529       return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR};
530     }
531     case 0xD5: /* Expected b64url conversion tag - fallthrough */
532     case 0xD6: /* Expected b64 conversion tag - fallthrough */
533     case 0xD7: /* Expected b16 conversion tag */
534     {
535       callbacks->tag(context,
536                      _cbor_load_uint8(source) - 0xC0); /* 0xC0 offset */
537       return result;
538     }
539     case 0xD8: /* 1B tag */
540     {
541       if (claim_bytes(1, source_size, &result)) {
542         callbacks->tag(context, _cbor_load_uint8(source + 1));
543       }
544       return result;
545     }
546     case 0xD9: /* 2B tag */
547     {
548       if (claim_bytes(2, source_size, &result)) {
549         callbacks->tag(context, _cbor_load_uint16(source + 1));
550       }
551       return result;
552     }
553     case 0xDA: /* 4B tag */
554     {
555       if (claim_bytes(4, source_size, &result)) {
556         callbacks->tag(context, _cbor_load_uint32(source + 1));
557       }
558       return result;
559     }
560     case 0xDB: /* 8B tag */
561     {
562       if (claim_bytes(8, source_size, &result)) {
563         callbacks->tag(context, _cbor_load_uint64(source + 1));
564       }
565       return result;
566     }
567     case 0xDC: /* Fallthrough */
568     case 0xDD: /* Fallthrough */
569     case 0xDE: /* Fallthrough */
570     case 0xDF: /* Reserved */
571     {
572       return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR};
573     }
574     case 0xE0: /* Fallthrough */
575     case 0xE1: /* Fallthrough */
576     case 0xE2: /* Fallthrough */
577     case 0xE3: /* Fallthrough */
578     case 0xE4: /* Fallthrough */
579     case 0xE5: /* Fallthrough */
580     case 0xE6: /* Fallthrough */
581     case 0xE7: /* Fallthrough */
582     case 0xE8: /* Fallthrough */
583     case 0xE9: /* Fallthrough */
584     case 0xEA: /* Fallthrough */
585     case 0xEB: /* Fallthrough */
586     case 0xEC: /* Fallthrough */
587     case 0xED: /* Fallthrough */
588     case 0xEE: /* Fallthrough */
589     case 0xEF: /* Fallthrough */
590     case 0xF0: /* Fallthrough */
591     case 0xF1: /* Fallthrough */
592     case 0xF2: /* Fallthrough */
593     case 0xF3: /* Simple value - unassigned */
594     {
595       return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR};
596     }
597     case 0xF4:
598       /* False */
599       {
600         callbacks->boolean(context, false);
601         return result;
602       }
603     case 0xF5:
604       /* True */
605       {
606         callbacks->boolean(context, true);
607         return result;
608       }
609     case 0xF6:
610       /* Null */
611       {
612         callbacks->null(context);
613         return result;
614       }
615     case 0xF7:
616       /* Undefined */
617       {
618         callbacks->undefined(context);
619         return result;
620       }
621     case 0xF8:
622       /* 1B simple value, unassigned */
623       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
624     case 0xF9:
625       /* 2B float */
626       {
627         if (claim_bytes(2, source_size, &result)) {
628           callbacks->float2(context, _cbor_load_half(source + 1));
629         }
630         return result;
631       }
632     case 0xFA:
633       /* 4B float */
634       {
635         if (claim_bytes(4, source_size, &result)) {
636           callbacks->float4(context, _cbor_load_float(source + 1));
637         }
638         return result;
639       }
640     case 0xFB:
641       /* 8B float */
642       {
643         if (claim_bytes(8, source_size, &result)) {
644           callbacks->float8(context, _cbor_load_double(source + 1));
645         }
646         return result;
647       }
648     case 0xFC: /* Fallthrough */
649     case 0xFD: /* Fallthrough */
650     case 0xFE:
651       /* Reserved */
652       { return (struct cbor_decoder_result){0, CBOR_DECODER_ERROR}; }
653     case 0xFF:
654       /* Break */
655       {
656         callbacks->indef_break(context);
657         return result;
658       }
659     default: /* Never happens - this shuts up the compiler */
660     {
661       return result;
662     }
663   }
664 }
665