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