xref: /aosp_15_r20/external/cn-cbor/src/cn-cbor.c (revision 254b1274ba1d768fbd68f5671e61c44001b5d4a8)
1*254b1274SAndroid Build Coastguard Worker #ifndef CN_CBOR_C
2*254b1274SAndroid Build Coastguard Worker #define CN_CBOR_C
3*254b1274SAndroid Build Coastguard Worker 
4*254b1274SAndroid Build Coastguard Worker #ifdef  __cplusplus
5*254b1274SAndroid Build Coastguard Worker extern "C" {
6*254b1274SAndroid Build Coastguard Worker #endif
7*254b1274SAndroid Build Coastguard Worker #ifdef EMACS_INDENTATION_HELPER
8*254b1274SAndroid Build Coastguard Worker } /* Duh. */
9*254b1274SAndroid Build Coastguard Worker #endif
10*254b1274SAndroid Build Coastguard Worker 
11*254b1274SAndroid Build Coastguard Worker #include <stdlib.h>
12*254b1274SAndroid Build Coastguard Worker #include <stdint.h>
13*254b1274SAndroid Build Coastguard Worker #include <string.h>
14*254b1274SAndroid Build Coastguard Worker #include <assert.h>
15*254b1274SAndroid Build Coastguard Worker #include <math.h>
16*254b1274SAndroid Build Coastguard Worker #include <arpa/inet.h> // needed for ntohl (e.g.) on Linux
17*254b1274SAndroid Build Coastguard Worker 
18*254b1274SAndroid Build Coastguard Worker #include "cn-cbor/cn-cbor.h"
19*254b1274SAndroid Build Coastguard Worker #include "cbor.h"
20*254b1274SAndroid Build Coastguard Worker 
21*254b1274SAndroid Build Coastguard Worker #define CN_CBOR_FAIL(code) do { pb->err = code;  goto fail; } while(0)
22*254b1274SAndroid Build Coastguard Worker 
cn_cbor_free(cn_cbor * cb CBOR_CONTEXT)23*254b1274SAndroid Build Coastguard Worker void cn_cbor_free(cn_cbor* cb CBOR_CONTEXT) {
24*254b1274SAndroid Build Coastguard Worker   cn_cbor* p = cb;
25*254b1274SAndroid Build Coastguard Worker   assert(!p || !p->parent);
26*254b1274SAndroid Build Coastguard Worker   while (p) {
27*254b1274SAndroid Build Coastguard Worker     cn_cbor* p1;
28*254b1274SAndroid Build Coastguard Worker     while ((p1 = p->first_child)) { /* go down */
29*254b1274SAndroid Build Coastguard Worker       p = p1;
30*254b1274SAndroid Build Coastguard Worker     }
31*254b1274SAndroid Build Coastguard Worker     if (!(p1 = p->next)) {   /* go up next */
32*254b1274SAndroid Build Coastguard Worker       if ((p1 = p->parent))
33*254b1274SAndroid Build Coastguard Worker         p1->first_child = 0;
34*254b1274SAndroid Build Coastguard Worker     }
35*254b1274SAndroid Build Coastguard Worker     CN_CBOR_FREE_CONTEXT(p);
36*254b1274SAndroid Build Coastguard Worker     p = p1;
37*254b1274SAndroid Build Coastguard Worker   }
38*254b1274SAndroid Build Coastguard Worker }
39*254b1274SAndroid Build Coastguard Worker 
40*254b1274SAndroid Build Coastguard Worker #ifndef CBOR_NO_FLOAT
decode_half(int half)41*254b1274SAndroid Build Coastguard Worker static double decode_half(int half) {
42*254b1274SAndroid Build Coastguard Worker   int exp = (half >> 10) & 0x1f;
43*254b1274SAndroid Build Coastguard Worker   int mant = half & 0x3ff;
44*254b1274SAndroid Build Coastguard Worker   double val;
45*254b1274SAndroid Build Coastguard Worker   if (exp == 0) val = ldexp(mant, -24);
46*254b1274SAndroid Build Coastguard Worker   else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
47*254b1274SAndroid Build Coastguard Worker   else val = mant == 0 ? INFINITY : NAN;
48*254b1274SAndroid Build Coastguard Worker   return half & 0x8000 ? -val : val;
49*254b1274SAndroid Build Coastguard Worker }
50*254b1274SAndroid Build Coastguard Worker #endif /* CBOR_NO_FLOAT */
51*254b1274SAndroid Build Coastguard Worker 
52*254b1274SAndroid Build Coastguard Worker #define ntoh8p(p) (*(unsigned char*)(p))
53*254b1274SAndroid Build Coastguard Worker 
54*254b1274SAndroid Build Coastguard Worker #ifndef CBOR_ALIGN_READS
55*254b1274SAndroid Build Coastguard Worker #define ntoh16p(p) (ntohs(*(unsigned short*)(p)))
56*254b1274SAndroid Build Coastguard Worker #define ntoh32p(p) (ntohl(*(uint32_t*)(p)))
57*254b1274SAndroid Build Coastguard Worker #else
ntoh16p(unsigned char * p)58*254b1274SAndroid Build Coastguard Worker static uint16_t ntoh16p(unsigned char *p) {
59*254b1274SAndroid Build Coastguard Worker     uint16_t tmp;
60*254b1274SAndroid Build Coastguard Worker     memcpy(&tmp, p, sizeof(tmp));
61*254b1274SAndroid Build Coastguard Worker     return ntohs(tmp);
62*254b1274SAndroid Build Coastguard Worker }
63*254b1274SAndroid Build Coastguard Worker 
ntoh32p(unsigned char * p)64*254b1274SAndroid Build Coastguard Worker static uint32_t ntoh32p(unsigned char *p) {
65*254b1274SAndroid Build Coastguard Worker     uint32_t tmp;
66*254b1274SAndroid Build Coastguard Worker     memcpy(&tmp, p, sizeof(tmp));
67*254b1274SAndroid Build Coastguard Worker     return ntohl(tmp);
68*254b1274SAndroid Build Coastguard Worker }
69*254b1274SAndroid Build Coastguard Worker #endif /* CBOR_ALIGN_READS */
70*254b1274SAndroid Build Coastguard Worker 
ntoh64p(unsigned char * p)71*254b1274SAndroid Build Coastguard Worker static uint64_t ntoh64p(unsigned char *p) {
72*254b1274SAndroid Build Coastguard Worker   uint64_t ret = ntoh32p(p);
73*254b1274SAndroid Build Coastguard Worker   ret <<= 32;
74*254b1274SAndroid Build Coastguard Worker   ret += ntoh32p(p+4);
75*254b1274SAndroid Build Coastguard Worker   return ret;
76*254b1274SAndroid Build Coastguard Worker }
77*254b1274SAndroid Build Coastguard Worker 
78*254b1274SAndroid Build Coastguard Worker static cn_cbor_type mt_trans[] = {
79*254b1274SAndroid Build Coastguard Worker   CN_CBOR_UINT,    CN_CBOR_INT,
80*254b1274SAndroid Build Coastguard Worker   CN_CBOR_BYTES,   CN_CBOR_TEXT,
81*254b1274SAndroid Build Coastguard Worker   CN_CBOR_ARRAY,   CN_CBOR_MAP,
82*254b1274SAndroid Build Coastguard Worker   CN_CBOR_TAG,     CN_CBOR_SIMPLE,
83*254b1274SAndroid Build Coastguard Worker };
84*254b1274SAndroid Build Coastguard Worker 
85*254b1274SAndroid Build Coastguard Worker struct parse_buf {
86*254b1274SAndroid Build Coastguard Worker   unsigned char *buf;
87*254b1274SAndroid Build Coastguard Worker   unsigned char *ebuf;
88*254b1274SAndroid Build Coastguard Worker   cn_cbor_error err;
89*254b1274SAndroid Build Coastguard Worker };
90*254b1274SAndroid Build Coastguard Worker 
91*254b1274SAndroid Build Coastguard Worker #define TAKE(pos, ebuf, n, stmt)                \
92*254b1274SAndroid Build Coastguard Worker   if (n > (size_t)(ebuf - pos))                 \
93*254b1274SAndroid Build Coastguard Worker     CN_CBOR_FAIL(CN_CBOR_ERR_OUT_OF_DATA);      \
94*254b1274SAndroid Build Coastguard Worker   stmt;                                         \
95*254b1274SAndroid Build Coastguard Worker   pos += n;
96*254b1274SAndroid Build Coastguard Worker 
decode_item(struct parse_buf * pb CBOR_CONTEXT,cn_cbor * top_parent)97*254b1274SAndroid Build Coastguard Worker static cn_cbor *decode_item (struct parse_buf *pb CBOR_CONTEXT, cn_cbor* top_parent) {
98*254b1274SAndroid Build Coastguard Worker   unsigned char *pos = pb->buf;
99*254b1274SAndroid Build Coastguard Worker   unsigned char *ebuf = pb->ebuf;
100*254b1274SAndroid Build Coastguard Worker   cn_cbor* parent = top_parent;
101*254b1274SAndroid Build Coastguard Worker   int ib;
102*254b1274SAndroid Build Coastguard Worker   unsigned int mt;
103*254b1274SAndroid Build Coastguard Worker   int ai;
104*254b1274SAndroid Build Coastguard Worker   uint64_t val;
105*254b1274SAndroid Build Coastguard Worker   cn_cbor* cb = NULL;
106*254b1274SAndroid Build Coastguard Worker #ifndef CBOR_NO_FLOAT
107*254b1274SAndroid Build Coastguard Worker   union {
108*254b1274SAndroid Build Coastguard Worker     float f;
109*254b1274SAndroid Build Coastguard Worker     uint32_t u;
110*254b1274SAndroid Build Coastguard Worker   } u32;
111*254b1274SAndroid Build Coastguard Worker   union {
112*254b1274SAndroid Build Coastguard Worker     double d;
113*254b1274SAndroid Build Coastguard Worker     uint64_t u;
114*254b1274SAndroid Build Coastguard Worker   } u64;
115*254b1274SAndroid Build Coastguard Worker #endif /* CBOR_NO_FLOAT */
116*254b1274SAndroid Build Coastguard Worker 
117*254b1274SAndroid Build Coastguard Worker again:
118*254b1274SAndroid Build Coastguard Worker   TAKE(pos, ebuf, 1, ib = ntoh8p(pos) );
119*254b1274SAndroid Build Coastguard Worker   if (ib == IB_BREAK) {
120*254b1274SAndroid Build Coastguard Worker     if (!(parent->flags & CN_CBOR_FL_INDEF))
121*254b1274SAndroid Build Coastguard Worker       CN_CBOR_FAIL(CN_CBOR_ERR_BREAK_OUTSIDE_INDEF);
122*254b1274SAndroid Build Coastguard Worker     switch (parent->type) {
123*254b1274SAndroid Build Coastguard Worker     case CN_CBOR_BYTES: case CN_CBOR_TEXT:
124*254b1274SAndroid Build Coastguard Worker       parent->type += 2;            /* CN_CBOR_* -> CN_CBOR_*_CHUNKED */
125*254b1274SAndroid Build Coastguard Worker       break;
126*254b1274SAndroid Build Coastguard Worker     case CN_CBOR_MAP:
127*254b1274SAndroid Build Coastguard Worker       if (parent->length & 1)
128*254b1274SAndroid Build Coastguard Worker         CN_CBOR_FAIL(CN_CBOR_ERR_ODD_SIZE_INDEF_MAP);
129*254b1274SAndroid Build Coastguard Worker     default:;
130*254b1274SAndroid Build Coastguard Worker     }
131*254b1274SAndroid Build Coastguard Worker     goto complete;
132*254b1274SAndroid Build Coastguard Worker   }
133*254b1274SAndroid Build Coastguard Worker   mt = ib >> 5;
134*254b1274SAndroid Build Coastguard Worker   ai = ib & 0x1f;
135*254b1274SAndroid Build Coastguard Worker   val = ai;
136*254b1274SAndroid Build Coastguard Worker 
137*254b1274SAndroid Build Coastguard Worker   cb = CN_CALLOC_CONTEXT();
138*254b1274SAndroid Build Coastguard Worker   if (!cb)
139*254b1274SAndroid Build Coastguard Worker     CN_CBOR_FAIL(CN_CBOR_ERR_OUT_OF_MEMORY);
140*254b1274SAndroid Build Coastguard Worker 
141*254b1274SAndroid Build Coastguard Worker   cb->type = mt_trans[mt];
142*254b1274SAndroid Build Coastguard Worker 
143*254b1274SAndroid Build Coastguard Worker   cb->parent = parent;
144*254b1274SAndroid Build Coastguard Worker   if (parent->last_child) {
145*254b1274SAndroid Build Coastguard Worker     parent->last_child->next = cb;
146*254b1274SAndroid Build Coastguard Worker   } else {
147*254b1274SAndroid Build Coastguard Worker     parent->first_child = cb;
148*254b1274SAndroid Build Coastguard Worker   }
149*254b1274SAndroid Build Coastguard Worker   parent->last_child = cb;
150*254b1274SAndroid Build Coastguard Worker   parent->length++;
151*254b1274SAndroid Build Coastguard Worker 
152*254b1274SAndroid Build Coastguard Worker   switch (ai) {
153*254b1274SAndroid Build Coastguard Worker   case AI_1: TAKE(pos, ebuf, 1, val = ntoh8p(pos)) ; break;
154*254b1274SAndroid Build Coastguard Worker   case AI_2: TAKE(pos, ebuf, 2, val = ntoh16p(pos)) ; break;
155*254b1274SAndroid Build Coastguard Worker   case AI_4: TAKE(pos, ebuf, 4, val = ntoh32p(pos)) ; break;
156*254b1274SAndroid Build Coastguard Worker   case AI_8: TAKE(pos, ebuf, 8, val = ntoh64p(pos)) ; break;
157*254b1274SAndroid Build Coastguard Worker   case 28: case 29: case 30: CN_CBOR_FAIL(CN_CBOR_ERR_RESERVED_AI);
158*254b1274SAndroid Build Coastguard Worker   case AI_INDEF:
159*254b1274SAndroid Build Coastguard Worker     if ((mt - MT_BYTES) <= MT_MAP) {
160*254b1274SAndroid Build Coastguard Worker       cb->flags |= CN_CBOR_FL_INDEF;
161*254b1274SAndroid Build Coastguard Worker       goto push;
162*254b1274SAndroid Build Coastguard Worker     } else {
163*254b1274SAndroid Build Coastguard Worker       CN_CBOR_FAIL(CN_CBOR_ERR_MT_UNDEF_FOR_INDEF);
164*254b1274SAndroid Build Coastguard Worker     }
165*254b1274SAndroid Build Coastguard Worker   }
166*254b1274SAndroid Build Coastguard Worker   // process content
167*254b1274SAndroid Build Coastguard Worker   switch (mt) {
168*254b1274SAndroid Build Coastguard Worker   case MT_UNSIGNED:
169*254b1274SAndroid Build Coastguard Worker     cb->v.uint = val;           /* to do: Overflow check */
170*254b1274SAndroid Build Coastguard Worker     break;
171*254b1274SAndroid Build Coastguard Worker   case MT_NEGATIVE:
172*254b1274SAndroid Build Coastguard Worker     cb->v.sint = ~val;          /* to do: Overflow check */
173*254b1274SAndroid Build Coastguard Worker     break;
174*254b1274SAndroid Build Coastguard Worker   case MT_BYTES: case MT_TEXT:
175*254b1274SAndroid Build Coastguard Worker     cb->v.str = (char *) pos;
176*254b1274SAndroid Build Coastguard Worker     cb->length = val;
177*254b1274SAndroid Build Coastguard Worker     TAKE(pos, ebuf, val, ;);
178*254b1274SAndroid Build Coastguard Worker     break;
179*254b1274SAndroid Build Coastguard Worker   case MT_MAP:
180*254b1274SAndroid Build Coastguard Worker     val <<= 1;
181*254b1274SAndroid Build Coastguard Worker     /* fall through */
182*254b1274SAndroid Build Coastguard Worker   case MT_ARRAY:
183*254b1274SAndroid Build Coastguard Worker     if ((cb->v.count = val)) {
184*254b1274SAndroid Build Coastguard Worker       cb->flags |= CN_CBOR_FL_COUNT;
185*254b1274SAndroid Build Coastguard Worker       goto push;
186*254b1274SAndroid Build Coastguard Worker     }
187*254b1274SAndroid Build Coastguard Worker     break;
188*254b1274SAndroid Build Coastguard Worker   case MT_TAG:
189*254b1274SAndroid Build Coastguard Worker     cb->v.uint = val;
190*254b1274SAndroid Build Coastguard Worker     goto push;
191*254b1274SAndroid Build Coastguard Worker   case MT_PRIM:
192*254b1274SAndroid Build Coastguard Worker     switch (ai) {
193*254b1274SAndroid Build Coastguard Worker     case VAL_FALSE: cb->type = CN_CBOR_FALSE; break;
194*254b1274SAndroid Build Coastguard Worker     case VAL_TRUE:  cb->type = CN_CBOR_TRUE;  break;
195*254b1274SAndroid Build Coastguard Worker     case VAL_NIL:   cb->type = CN_CBOR_NULL;  break;
196*254b1274SAndroid Build Coastguard Worker     case VAL_UNDEF: cb->type = CN_CBOR_UNDEF; break;
197*254b1274SAndroid Build Coastguard Worker     case AI_2:
198*254b1274SAndroid Build Coastguard Worker #ifndef CBOR_NO_FLOAT
199*254b1274SAndroid Build Coastguard Worker       cb->type = CN_CBOR_DOUBLE;
200*254b1274SAndroid Build Coastguard Worker       cb->v.dbl = decode_half(val);
201*254b1274SAndroid Build Coastguard Worker #else /*  CBOR_NO_FLOAT */
202*254b1274SAndroid Build Coastguard Worker       CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
203*254b1274SAndroid Build Coastguard Worker #endif /*  CBOR_NO_FLOAT */
204*254b1274SAndroid Build Coastguard Worker       break;
205*254b1274SAndroid Build Coastguard Worker     case AI_4:
206*254b1274SAndroid Build Coastguard Worker #ifndef CBOR_NO_FLOAT
207*254b1274SAndroid Build Coastguard Worker       cb->type = CN_CBOR_DOUBLE;
208*254b1274SAndroid Build Coastguard Worker       u32.u = val;
209*254b1274SAndroid Build Coastguard Worker       cb->v.dbl = u32.f;
210*254b1274SAndroid Build Coastguard Worker #else /*  CBOR_NO_FLOAT */
211*254b1274SAndroid Build Coastguard Worker       CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
212*254b1274SAndroid Build Coastguard Worker #endif /*  CBOR_NO_FLOAT */
213*254b1274SAndroid Build Coastguard Worker       break;
214*254b1274SAndroid Build Coastguard Worker     case AI_8:
215*254b1274SAndroid Build Coastguard Worker #ifndef CBOR_NO_FLOAT
216*254b1274SAndroid Build Coastguard Worker       cb->type = CN_CBOR_DOUBLE;
217*254b1274SAndroid Build Coastguard Worker       u64.u = val;
218*254b1274SAndroid Build Coastguard Worker       cb->v.dbl = u64.d;
219*254b1274SAndroid Build Coastguard Worker #else /*  CBOR_NO_FLOAT */
220*254b1274SAndroid Build Coastguard Worker       CN_CBOR_FAIL(CN_CBOR_ERR_FLOAT_NOT_SUPPORTED);
221*254b1274SAndroid Build Coastguard Worker #endif /*  CBOR_NO_FLOAT */
222*254b1274SAndroid Build Coastguard Worker       break;
223*254b1274SAndroid Build Coastguard Worker     default: cb->v.uint = val;
224*254b1274SAndroid Build Coastguard Worker     }
225*254b1274SAndroid Build Coastguard Worker   }
226*254b1274SAndroid Build Coastguard Worker fill:                           /* emulate loops */
227*254b1274SAndroid Build Coastguard Worker   if (parent->flags & CN_CBOR_FL_INDEF) {
228*254b1274SAndroid Build Coastguard Worker     if (parent->type == CN_CBOR_BYTES || parent->type == CN_CBOR_TEXT)
229*254b1274SAndroid Build Coastguard Worker       if (cb->type != parent->type)
230*254b1274SAndroid Build Coastguard Worker           CN_CBOR_FAIL(CN_CBOR_ERR_WRONG_NESTING_IN_INDEF_STRING);
231*254b1274SAndroid Build Coastguard Worker     goto again;
232*254b1274SAndroid Build Coastguard Worker   }
233*254b1274SAndroid Build Coastguard Worker   if (parent->flags & CN_CBOR_FL_COUNT) {
234*254b1274SAndroid Build Coastguard Worker     if (--parent->v.count)
235*254b1274SAndroid Build Coastguard Worker       goto again;
236*254b1274SAndroid Build Coastguard Worker   }
237*254b1274SAndroid Build Coastguard Worker   /* so we are done filling parent. */
238*254b1274SAndroid Build Coastguard Worker complete:                       /* emulate return from call */
239*254b1274SAndroid Build Coastguard Worker   if (parent == top_parent) {
240*254b1274SAndroid Build Coastguard Worker     if (pos != ebuf)            /* XXX do this outside */
241*254b1274SAndroid Build Coastguard Worker       CN_CBOR_FAIL(CN_CBOR_ERR_NOT_ALL_DATA_CONSUMED);
242*254b1274SAndroid Build Coastguard Worker     pb->buf = pos;
243*254b1274SAndroid Build Coastguard Worker     return cb;
244*254b1274SAndroid Build Coastguard Worker   }
245*254b1274SAndroid Build Coastguard Worker   cb = parent;
246*254b1274SAndroid Build Coastguard Worker   parent = parent->parent;
247*254b1274SAndroid Build Coastguard Worker   goto fill;
248*254b1274SAndroid Build Coastguard Worker push:                           /* emulate recursive call */
249*254b1274SAndroid Build Coastguard Worker   parent = cb;
250*254b1274SAndroid Build Coastguard Worker   goto again;
251*254b1274SAndroid Build Coastguard Worker fail:
252*254b1274SAndroid Build Coastguard Worker   pb->buf = pos;
253*254b1274SAndroid Build Coastguard Worker   return 0;
254*254b1274SAndroid Build Coastguard Worker }
255*254b1274SAndroid Build Coastguard Worker 
cn_cbor_decode(const unsigned char * buf,size_t len CBOR_CONTEXT,cn_cbor_errback * errp)256*254b1274SAndroid Build Coastguard Worker cn_cbor* cn_cbor_decode(const unsigned char* buf, size_t len CBOR_CONTEXT, cn_cbor_errback *errp) {
257*254b1274SAndroid Build Coastguard Worker   cn_cbor catcher = {CN_CBOR_INVALID, 0, {0}, 0, NULL, NULL, NULL, NULL};
258*254b1274SAndroid Build Coastguard Worker   struct parse_buf pb;
259*254b1274SAndroid Build Coastguard Worker   cn_cbor* ret;
260*254b1274SAndroid Build Coastguard Worker 
261*254b1274SAndroid Build Coastguard Worker   pb.buf  = (unsigned char *)buf;
262*254b1274SAndroid Build Coastguard Worker   pb.ebuf = (unsigned char *)buf+len;
263*254b1274SAndroid Build Coastguard Worker   pb.err  = CN_CBOR_NO_ERROR;
264*254b1274SAndroid Build Coastguard Worker   ret = decode_item(&pb CBOR_CONTEXT_PARAM, &catcher);
265*254b1274SAndroid Build Coastguard Worker   if (ret != NULL) {
266*254b1274SAndroid Build Coastguard Worker     /* mark as top node */
267*254b1274SAndroid Build Coastguard Worker     ret->parent = NULL;
268*254b1274SAndroid Build Coastguard Worker   } else {
269*254b1274SAndroid Build Coastguard Worker     if (catcher.first_child) {
270*254b1274SAndroid Build Coastguard Worker       catcher.first_child->parent = 0;
271*254b1274SAndroid Build Coastguard Worker       cn_cbor_free(catcher.first_child CBOR_CONTEXT_PARAM);
272*254b1274SAndroid Build Coastguard Worker     }
273*254b1274SAndroid Build Coastguard Worker //fail:
274*254b1274SAndroid Build Coastguard Worker     if (errp) {
275*254b1274SAndroid Build Coastguard Worker       errp->err = pb.err;
276*254b1274SAndroid Build Coastguard Worker       errp->pos = pb.buf - (unsigned char *)buf;
277*254b1274SAndroid Build Coastguard Worker     }
278*254b1274SAndroid Build Coastguard Worker     return NULL;
279*254b1274SAndroid Build Coastguard Worker   }
280*254b1274SAndroid Build Coastguard Worker   return ret;
281*254b1274SAndroid Build Coastguard Worker }
282*254b1274SAndroid Build Coastguard Worker 
283*254b1274SAndroid Build Coastguard Worker #ifdef  __cplusplus
284*254b1274SAndroid Build Coastguard Worker }
285*254b1274SAndroid Build Coastguard Worker #endif
286*254b1274SAndroid Build Coastguard Worker 
287*254b1274SAndroid Build Coastguard Worker #endif  /* CN_CBOR_C */
288