1 #include "../src/cbor.h"
2 
3 #include <sys/stat.h>
4 #include <assert.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 
readfile(const char * fname,size_t * size)9 static uint8_t *readfile(const char *fname, size_t *size)
10 {
11     struct stat st;
12     FILE *f = fopen(fname, "rb");
13     if (!f)
14         return NULL;
15     if (fstat(fileno(f), &st) == -1)
16         return NULL;
17     uint8_t *buf = malloc(st.st_size);
18     *size = fread(buf, st.st_size, 1, f);
19     fclose(f);
20     return buf;
21 }
22 
indent(int nestingLevel)23 static void indent(int nestingLevel)
24 {
25     while (nestingLevel--)
26         puts("  ");
27 }
28 
dumpbytes(const uint8_t * buf,size_t len)29 static void dumpbytes(const uint8_t *buf, size_t len)
30 {
31     while (len--)
32         printf("%02X ", *buf++);
33 }
34 
dumprecursive(CborValue * it,int nestingLevel)35 static bool dumprecursive(CborValue *it, int nestingLevel)
36 {
37     while (!cbor_value_at_end(it)) {
38         CborError err;
39         CborType type = cbor_value_get_type(it);
40 
41         indent(nestingLevel);
42         switch (type) {
43         case CborArrayType:
44         case CborMapType: {
45             // recursive type
46             CborValue recursed;
47             assert(cbor_value_is_container(it));
48             puts(type == CborArrayType ? "Array[" : "Map[");
49             err = cbor_value_enter_container(it, &recursed);
50             if (err)
51                 return err;       // parse error
52             err = dumprecursive(&recursed, nestingLevel + 1);
53             if (err)
54                 return err;       // parse error
55             err = cbor_value_leave_container(it, &recursed);
56             if (err)
57                 return err;       // parse error
58             indent(nestingLevel);
59             puts("]");
60             continue;
61         }
62 
63         case CborIntegerType: {
64             int64_t val;
65             cbor_value_get_int64(it, &val);     // can't fail
66             printf("%lld\n", (long long)val);
67             break;
68         }
69 
70         case CborByteStringType: {
71             uint8_t *buf;
72             size_t n;
73             err = cbor_value_dup_byte_string(it, &buf, &n, it);
74             if (err)
75                 return err;     // parse error
76             dumpbytes(buf, n);
77             puts("");
78             free(buf);
79             continue;
80         }
81 
82         case CborTextStringType: {
83             char *buf;
84             size_t n;
85             err = cbor_value_dup_text_string(it, &buf, &n, it);
86             if (err)
87                 return err;     // parse error
88             puts(buf);
89             free(buf);
90             continue;
91         }
92 
93         case CborTagType: {
94             CborTag tag;
95             cbor_value_get_tag(it, &tag);       // can't fail
96             printf("Tag(%lld)\n", (long long)tag);
97             break;
98         }
99 
100         case CborSimpleType: {
101             uint8_t type;
102             cbor_value_get_simple_type(it, &type);  // can't fail
103             printf("simple(%u)\n", type);
104             break;
105         }
106 
107         case CborNullType:
108             puts("null");
109             break;
110 
111         case CborUndefinedType:
112             puts("undefined");
113             break;
114 
115         case CborBooleanType: {
116             bool val;
117             cbor_value_get_boolean(it, &val);       // can't fail
118             puts(val ? "true" : "false");
119             break;
120         }
121 
122         case CborDoubleType: {
123             double val;
124             if (false) {
125                 float f;
126         case CborFloatType:
127                 cbor_value_get_float(it, &f);
128                 val = f;
129             } else {
130                 cbor_value_get_double(it, &val);
131             }
132             printf("%g\n", val);
133             break;
134         }
135         case CborHalfFloatType: {
136             uint16_t val;
137             cbor_value_get_half_float(it, &val);
138             printf("__f16(%04x)\n", val);
139             break;
140         }
141 
142         case CborInvalidType:
143             assert(false);      // can't happen
144             break;
145         }
146 
147         err = cbor_value_advance_fixed(it);
148         if (err)
149             return err;
150     }
151     return CborNoError;
152 }
153 
main(int argc,char ** argv)154 int main(int argc, char **argv)
155 {
156     if (argc == 1) {
157         puts("simplereader <filename>");
158         return 0;
159     }
160 
161     size_t length;
162     uint8_t *buf = readfile(argv[1], &length);
163     if (!buf) {
164         perror("readfile");
165         return 1;
166     }
167 
168     CborParser parser;
169     CborValue it;
170     CborError err = cbor_parser_init(buf, length, 0, &parser, &it);
171     if (!err)
172         err = dumprecursive(&it, 0);
173     free(buf);
174 
175     if (err) {
176         fprintf(stderr, "CBOR parsing failure at offset %ld: %s\n",
177                 it.ptr - buf, cbor_error_string(err));
178         return 1;
179     }
180     return 0;
181 }
182