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