xref: /aosp_15_r20/external/cn-cbor/src/cn-encoder.c (revision 254b1274ba1d768fbd68f5671e61c44001b5d4a8)
1*254b1274SAndroid Build Coastguard Worker #ifndef CN_ENCODER_C
2*254b1274SAndroid Build Coastguard Worker #define CN_ENCODER_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 <arpa/inet.h>
12*254b1274SAndroid Build Coastguard Worker #include <string.h>
13*254b1274SAndroid Build Coastguard Worker #include <strings.h>
14*254b1274SAndroid Build Coastguard Worker #include <stdbool.h>
15*254b1274SAndroid Build Coastguard Worker #include <assert.h>
16*254b1274SAndroid Build Coastguard Worker 
17*254b1274SAndroid Build Coastguard Worker #include "cn-cbor/cn-cbor.h"
18*254b1274SAndroid Build Coastguard Worker #include "cbor.h"
19*254b1274SAndroid Build Coastguard Worker 
20*254b1274SAndroid Build Coastguard Worker #define hton8p(p) (*(uint8_t*)(p))
21*254b1274SAndroid Build Coastguard Worker #define hton16p(p) (htons(*(uint16_t*)(p)))
22*254b1274SAndroid Build Coastguard Worker #define hton32p(p) (htonl(*(uint32_t*)(p)))
hton64p(const uint8_t * p)23*254b1274SAndroid Build Coastguard Worker static uint64_t hton64p(const uint8_t *p) {
24*254b1274SAndroid Build Coastguard Worker   /* TODO: does this work on both BE and LE systems? */
25*254b1274SAndroid Build Coastguard Worker   uint64_t ret = hton32p(p);
26*254b1274SAndroid Build Coastguard Worker   ret <<= 32;
27*254b1274SAndroid Build Coastguard Worker   ret |= hton32p(p+4);
28*254b1274SAndroid Build Coastguard Worker   return ret;
29*254b1274SAndroid Build Coastguard Worker }
30*254b1274SAndroid Build Coastguard Worker 
31*254b1274SAndroid Build Coastguard Worker typedef struct _write_state
32*254b1274SAndroid Build Coastguard Worker {
33*254b1274SAndroid Build Coastguard Worker   uint8_t *buf;
34*254b1274SAndroid Build Coastguard Worker   ssize_t offset;
35*254b1274SAndroid Build Coastguard Worker   ssize_t size;
36*254b1274SAndroid Build Coastguard Worker } cn_write_state;
37*254b1274SAndroid Build Coastguard Worker 
38*254b1274SAndroid Build Coastguard Worker #define ensure_writable(sz) if ((ws->offset<0) || (ws->offset + (sz) >= ws->size)) { \
39*254b1274SAndroid Build Coastguard Worker   ws->offset = -1; \
40*254b1274SAndroid Build Coastguard Worker   return; \
41*254b1274SAndroid Build Coastguard Worker }
42*254b1274SAndroid Build Coastguard Worker 
43*254b1274SAndroid Build Coastguard Worker #define write_byte_and_data(b, data, sz) \
44*254b1274SAndroid Build Coastguard Worker ws->buf[ws->offset++] = (b); \
45*254b1274SAndroid Build Coastguard Worker memcpy(ws->buf+ws->offset, (data), (sz)); \
46*254b1274SAndroid Build Coastguard Worker ws->offset += sz;
47*254b1274SAndroid Build Coastguard Worker 
48*254b1274SAndroid Build Coastguard Worker #define write_byte(b) \
49*254b1274SAndroid Build Coastguard Worker ws->buf[ws->offset++] = (b); \
50*254b1274SAndroid Build Coastguard Worker 
51*254b1274SAndroid Build Coastguard Worker #define write_byte_ensured(b) \
52*254b1274SAndroid Build Coastguard Worker ensure_writable(1); \
53*254b1274SAndroid Build Coastguard Worker write_byte(b); \
54*254b1274SAndroid Build Coastguard Worker 
55*254b1274SAndroid Build Coastguard Worker static uint8_t _xlate[] = {
56*254b1274SAndroid Build Coastguard Worker   IB_FALSE,    /* CN_CBOR_FALSE */
57*254b1274SAndroid Build Coastguard Worker   IB_TRUE,     /* CN_CBOR_TRUE */
58*254b1274SAndroid Build Coastguard Worker   IB_NIL,      /* CN_CBOR_NULL */
59*254b1274SAndroid Build Coastguard Worker   IB_UNDEF,    /* CN_CBOR_UNDEF */
60*254b1274SAndroid Build Coastguard Worker   IB_UNSIGNED, /* CN_CBOR_UINT */
61*254b1274SAndroid Build Coastguard Worker   IB_NEGATIVE, /* CN_CBOR_INT */
62*254b1274SAndroid Build Coastguard Worker   IB_BYTES,    /* CN_CBOR_BYTES */
63*254b1274SAndroid Build Coastguard Worker   IB_TEXT,     /* CN_CBOR_TEXT */
64*254b1274SAndroid Build Coastguard Worker   IB_BYTES,    /* CN_CBOR_BYTES_CHUNKED */
65*254b1274SAndroid Build Coastguard Worker   IB_TEXT,     /* CN_CBOR_TEXT_CHUNKED */
66*254b1274SAndroid Build Coastguard Worker   IB_ARRAY,    /* CN_CBOR_ARRAY */
67*254b1274SAndroid Build Coastguard Worker   IB_MAP,      /* CN_CBOR_MAP */
68*254b1274SAndroid Build Coastguard Worker   IB_TAG,      /* CN_CBOR_TAG */
69*254b1274SAndroid Build Coastguard Worker   IB_PRIM,     /* CN_CBOR_SIMPLE */
70*254b1274SAndroid Build Coastguard Worker   0xFF,        /* CN_CBOR_DOUBLE */
71*254b1274SAndroid Build Coastguard Worker   0xFF         /* CN_CBOR_INVALID */
72*254b1274SAndroid Build Coastguard Worker };
73*254b1274SAndroid Build Coastguard Worker 
is_indefinite(const cn_cbor * cb)74*254b1274SAndroid Build Coastguard Worker static inline bool is_indefinite(const cn_cbor *cb)
75*254b1274SAndroid Build Coastguard Worker {
76*254b1274SAndroid Build Coastguard Worker   return (cb->flags & CN_CBOR_FL_INDEF) != 0;
77*254b1274SAndroid Build Coastguard Worker }
78*254b1274SAndroid Build Coastguard Worker 
_write_positive(cn_write_state * ws,cn_cbor_type typ,uint64_t val)79*254b1274SAndroid Build Coastguard Worker static void _write_positive(cn_write_state *ws, cn_cbor_type typ, uint64_t val) {
80*254b1274SAndroid Build Coastguard Worker   uint8_t ib;
81*254b1274SAndroid Build Coastguard Worker 
82*254b1274SAndroid Build Coastguard Worker   assert((size_t)typ < sizeof(_xlate));
83*254b1274SAndroid Build Coastguard Worker 
84*254b1274SAndroid Build Coastguard Worker   ib = _xlate[typ];
85*254b1274SAndroid Build Coastguard Worker   if (ib == 0xFF) {
86*254b1274SAndroid Build Coastguard Worker     ws->offset = -1;
87*254b1274SAndroid Build Coastguard Worker     return;
88*254b1274SAndroid Build Coastguard Worker   }
89*254b1274SAndroid Build Coastguard Worker 
90*254b1274SAndroid Build Coastguard Worker   if (val < 24) {
91*254b1274SAndroid Build Coastguard Worker     ensure_writable(1);
92*254b1274SAndroid Build Coastguard Worker     write_byte(ib | val);
93*254b1274SAndroid Build Coastguard Worker   } else if (val < 256) {
94*254b1274SAndroid Build Coastguard Worker     ensure_writable(2);
95*254b1274SAndroid Build Coastguard Worker     write_byte(ib | 24);
96*254b1274SAndroid Build Coastguard Worker     write_byte((uint8_t)val);
97*254b1274SAndroid Build Coastguard Worker   } else if (val < 65536) {
98*254b1274SAndroid Build Coastguard Worker     uint16_t be16 = (uint16_t)val;
99*254b1274SAndroid Build Coastguard Worker     ensure_writable(3);
100*254b1274SAndroid Build Coastguard Worker     be16 = hton16p(&be16);
101*254b1274SAndroid Build Coastguard Worker     write_byte_and_data(ib | 25, (const void*)&be16, 2);
102*254b1274SAndroid Build Coastguard Worker   } else if (val < 0x100000000L) {
103*254b1274SAndroid Build Coastguard Worker     uint32_t be32 = (uint32_t)val;
104*254b1274SAndroid Build Coastguard Worker     ensure_writable(5);
105*254b1274SAndroid Build Coastguard Worker     be32 = hton32p(&be32);
106*254b1274SAndroid Build Coastguard Worker     write_byte_and_data(ib | 26, (const void*)&be32, 4);
107*254b1274SAndroid Build Coastguard Worker   } else {
108*254b1274SAndroid Build Coastguard Worker     uint64_t be64;
109*254b1274SAndroid Build Coastguard Worker     ensure_writable(9);
110*254b1274SAndroid Build Coastguard Worker     be64 = hton64p((const uint8_t*)&val);
111*254b1274SAndroid Build Coastguard Worker     write_byte_and_data(ib | 27, (const void*)&be64, 8);
112*254b1274SAndroid Build Coastguard Worker   }
113*254b1274SAndroid Build Coastguard Worker }
114*254b1274SAndroid Build Coastguard Worker 
115*254b1274SAndroid Build Coastguard Worker #ifndef CBOR_NO_FLOAT
_write_double(cn_write_state * ws,double val)116*254b1274SAndroid Build Coastguard Worker static void _write_double(cn_write_state *ws, double val)
117*254b1274SAndroid Build Coastguard Worker {
118*254b1274SAndroid Build Coastguard Worker   float float_val = val;
119*254b1274SAndroid Build Coastguard Worker   if (float_val == val) {                /* 32 bits is enough and we aren't NaN */
120*254b1274SAndroid Build Coastguard Worker     uint32_t be32;
121*254b1274SAndroid Build Coastguard Worker     uint16_t be16, u16;
122*254b1274SAndroid Build Coastguard Worker     union {
123*254b1274SAndroid Build Coastguard Worker       float f;
124*254b1274SAndroid Build Coastguard Worker       uint32_t u;
125*254b1274SAndroid Build Coastguard Worker     } u32;
126*254b1274SAndroid Build Coastguard Worker     u32.f = float_val;
127*254b1274SAndroid Build Coastguard Worker     if ((u32.u & 0x1FFF) == 0) { /* worth trying half */
128*254b1274SAndroid Build Coastguard Worker       int s16 = (u32.u >> 16) & 0x8000;
129*254b1274SAndroid Build Coastguard Worker       int exp = (u32.u >> 23) & 0xff;
130*254b1274SAndroid Build Coastguard Worker       int mant = u32.u & 0x7fffff;
131*254b1274SAndroid Build Coastguard Worker       if (exp == 0 && mant == 0)
132*254b1274SAndroid Build Coastguard Worker         ;              /* 0.0, -0.0 */
133*254b1274SAndroid Build Coastguard Worker       else if (exp >= 113 && exp <= 142) /* normalized */
134*254b1274SAndroid Build Coastguard Worker         s16 += ((exp - 112) << 10) + (mant >> 13);
135*254b1274SAndroid Build Coastguard Worker       else if (exp >= 103 && exp < 113) { /* denorm, exp16 = 0 */
136*254b1274SAndroid Build Coastguard Worker         if (mant & ((1 << (126 - exp)) - 1))
137*254b1274SAndroid Build Coastguard Worker           goto float32;         /* loss of precision */
138*254b1274SAndroid Build Coastguard Worker         s16 += ((mant + 0x800000) >> (126 - exp));
139*254b1274SAndroid Build Coastguard Worker       } else if (exp == 255 && mant == 0) { /* Inf */
140*254b1274SAndroid Build Coastguard Worker         s16 += 0x7c00;
141*254b1274SAndroid Build Coastguard Worker       } else
142*254b1274SAndroid Build Coastguard Worker         goto float32;           /* loss of range */
143*254b1274SAndroid Build Coastguard Worker 
144*254b1274SAndroid Build Coastguard Worker       ensure_writable(3);
145*254b1274SAndroid Build Coastguard Worker       u16 = s16;
146*254b1274SAndroid Build Coastguard Worker       be16 = hton16p((const uint8_t*)&u16);
147*254b1274SAndroid Build Coastguard Worker 
148*254b1274SAndroid Build Coastguard Worker       write_byte_and_data(IB_PRIM | 25, (const void*)&be16, 2);
149*254b1274SAndroid Build Coastguard Worker       return;
150*254b1274SAndroid Build Coastguard Worker     }
151*254b1274SAndroid Build Coastguard Worker   float32:
152*254b1274SAndroid Build Coastguard Worker     ensure_writable(5);
153*254b1274SAndroid Build Coastguard Worker     be32 = hton32p((const uint8_t*)&u32.u);
154*254b1274SAndroid Build Coastguard Worker 
155*254b1274SAndroid Build Coastguard Worker     write_byte_and_data(IB_PRIM | 26, (const void*)&be32, 4);
156*254b1274SAndroid Build Coastguard Worker 
157*254b1274SAndroid Build Coastguard Worker   } else if (val != val) {      /* NaN -- we always write a half NaN*/
158*254b1274SAndroid Build Coastguard Worker     ensure_writable(3);
159*254b1274SAndroid Build Coastguard Worker     write_byte_and_data(IB_PRIM | 25, (const void*)"\x7e\x00", 2);
160*254b1274SAndroid Build Coastguard Worker   } else {
161*254b1274SAndroid Build Coastguard Worker     uint64_t be64;
162*254b1274SAndroid Build Coastguard Worker     /* Copy the same problematic implementation from the decoder. */
163*254b1274SAndroid Build Coastguard Worker     union {
164*254b1274SAndroid Build Coastguard Worker       double d;
165*254b1274SAndroid Build Coastguard Worker       uint64_t u;
166*254b1274SAndroid Build Coastguard Worker     } u64;
167*254b1274SAndroid Build Coastguard Worker 
168*254b1274SAndroid Build Coastguard Worker     u64.d = val;
169*254b1274SAndroid Build Coastguard Worker 
170*254b1274SAndroid Build Coastguard Worker     ensure_writable(9);
171*254b1274SAndroid Build Coastguard Worker     be64 = hton64p((const uint8_t*)&u64.u);
172*254b1274SAndroid Build Coastguard Worker 
173*254b1274SAndroid Build Coastguard Worker     write_byte_and_data(IB_PRIM | 27, (const void*)&be64, 8);
174*254b1274SAndroid Build Coastguard Worker 
175*254b1274SAndroid Build Coastguard Worker   }
176*254b1274SAndroid Build Coastguard Worker }
177*254b1274SAndroid Build Coastguard Worker #endif /* CBOR_NO_FLOAT */
178*254b1274SAndroid Build Coastguard Worker 
179*254b1274SAndroid Build Coastguard Worker // TODO: make public?
180*254b1274SAndroid Build Coastguard Worker typedef void (*cn_visit_func)(const cn_cbor *cb, int depth, void *context);
_visit(const cn_cbor * cb,cn_visit_func visitor,cn_visit_func breaker,void * context)181*254b1274SAndroid Build Coastguard Worker static void _visit(const cn_cbor *cb,
182*254b1274SAndroid Build Coastguard Worker                    cn_visit_func visitor,
183*254b1274SAndroid Build Coastguard Worker                    cn_visit_func breaker,
184*254b1274SAndroid Build Coastguard Worker                    void *context)
185*254b1274SAndroid Build Coastguard Worker {
186*254b1274SAndroid Build Coastguard Worker     const cn_cbor *p = cb;
187*254b1274SAndroid Build Coastguard Worker     int depth = 0;
188*254b1274SAndroid Build Coastguard Worker     while (p)
189*254b1274SAndroid Build Coastguard Worker     {
190*254b1274SAndroid Build Coastguard Worker visit:
191*254b1274SAndroid Build Coastguard Worker       visitor(p, depth, context);
192*254b1274SAndroid Build Coastguard Worker       if (p->first_child) {
193*254b1274SAndroid Build Coastguard Worker         p = p->first_child;
194*254b1274SAndroid Build Coastguard Worker         depth++;
195*254b1274SAndroid Build Coastguard Worker       } else{
196*254b1274SAndroid Build Coastguard Worker         // Empty indefinite
197*254b1274SAndroid Build Coastguard Worker         if (is_indefinite(p)) {
198*254b1274SAndroid Build Coastguard Worker           breaker(p->parent, depth, context);
199*254b1274SAndroid Build Coastguard Worker         }
200*254b1274SAndroid Build Coastguard Worker         if (p->next) {
201*254b1274SAndroid Build Coastguard Worker           p = p->next;
202*254b1274SAndroid Build Coastguard Worker         } else {
203*254b1274SAndroid Build Coastguard Worker           while (p->parent) {
204*254b1274SAndroid Build Coastguard Worker             depth--;
205*254b1274SAndroid Build Coastguard Worker             if (is_indefinite(p->parent)) {
206*254b1274SAndroid Build Coastguard Worker               breaker(p->parent, depth, context);
207*254b1274SAndroid Build Coastguard Worker             }
208*254b1274SAndroid Build Coastguard Worker             if (p->parent->next) {
209*254b1274SAndroid Build Coastguard Worker               p = p->parent->next;
210*254b1274SAndroid Build Coastguard Worker               goto visit;
211*254b1274SAndroid Build Coastguard Worker             }
212*254b1274SAndroid Build Coastguard Worker             p = p->parent;
213*254b1274SAndroid Build Coastguard Worker           }
214*254b1274SAndroid Build Coastguard Worker           return;
215*254b1274SAndroid Build Coastguard Worker         }
216*254b1274SAndroid Build Coastguard Worker       }
217*254b1274SAndroid Build Coastguard Worker     }
218*254b1274SAndroid Build Coastguard Worker }
219*254b1274SAndroid Build Coastguard Worker 
220*254b1274SAndroid Build Coastguard Worker #define CHECK(st) (st); \
221*254b1274SAndroid Build Coastguard Worker if (ws->offset < 0) { return; }
222*254b1274SAndroid Build Coastguard Worker 
_encoder_visitor(const cn_cbor * cb,int depth,void * context)223*254b1274SAndroid Build Coastguard Worker void _encoder_visitor(const cn_cbor *cb, int depth, void *context)
224*254b1274SAndroid Build Coastguard Worker {
225*254b1274SAndroid Build Coastguard Worker   cn_write_state *ws = context;
226*254b1274SAndroid Build Coastguard Worker   UNUSED_PARAM(depth);
227*254b1274SAndroid Build Coastguard Worker 
228*254b1274SAndroid Build Coastguard Worker   switch (cb->type) {
229*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_ARRAY:
230*254b1274SAndroid Build Coastguard Worker     if (is_indefinite(cb)) {
231*254b1274SAndroid Build Coastguard Worker       write_byte_ensured(IB_ARRAY | AI_INDEF);
232*254b1274SAndroid Build Coastguard Worker     } else {
233*254b1274SAndroid Build Coastguard Worker       CHECK(_write_positive(ws, CN_CBOR_ARRAY, cb->length));
234*254b1274SAndroid Build Coastguard Worker     }
235*254b1274SAndroid Build Coastguard Worker     break;
236*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_MAP:
237*254b1274SAndroid Build Coastguard Worker     if (is_indefinite(cb)) {
238*254b1274SAndroid Build Coastguard Worker       write_byte_ensured(IB_MAP | AI_INDEF);
239*254b1274SAndroid Build Coastguard Worker     } else {
240*254b1274SAndroid Build Coastguard Worker       CHECK(_write_positive(ws, CN_CBOR_MAP, cb->length/2));
241*254b1274SAndroid Build Coastguard Worker     }
242*254b1274SAndroid Build Coastguard Worker     break;
243*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_BYTES_CHUNKED:
244*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_TEXT_CHUNKED:
245*254b1274SAndroid Build Coastguard Worker     write_byte_ensured(_xlate[cb->type] | AI_INDEF);
246*254b1274SAndroid Build Coastguard Worker     break;
247*254b1274SAndroid Build Coastguard Worker 
248*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_TEXT:
249*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_BYTES:
250*254b1274SAndroid Build Coastguard Worker     CHECK(_write_positive(ws, cb->type, cb->length));
251*254b1274SAndroid Build Coastguard Worker     ensure_writable(cb->length);
252*254b1274SAndroid Build Coastguard Worker     memcpy(ws->buf+ws->offset, cb->v.str, cb->length);
253*254b1274SAndroid Build Coastguard Worker     ws->offset += cb->length;
254*254b1274SAndroid Build Coastguard Worker     break;
255*254b1274SAndroid Build Coastguard Worker 
256*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_FALSE:
257*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_TRUE:
258*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_NULL:
259*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_UNDEF:
260*254b1274SAndroid Build Coastguard Worker     write_byte_ensured(_xlate[cb->type]);
261*254b1274SAndroid Build Coastguard Worker     break;
262*254b1274SAndroid Build Coastguard Worker 
263*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_TAG:
264*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_UINT:
265*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_SIMPLE:
266*254b1274SAndroid Build Coastguard Worker     CHECK(_write_positive(ws, cb->type, cb->v.uint));
267*254b1274SAndroid Build Coastguard Worker     break;
268*254b1274SAndroid Build Coastguard Worker 
269*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_INT:
270*254b1274SAndroid Build Coastguard Worker     assert(cb->v.sint < 0);
271*254b1274SAndroid Build Coastguard Worker     CHECK(_write_positive(ws, CN_CBOR_INT, ~(cb->v.sint)));
272*254b1274SAndroid Build Coastguard Worker     break;
273*254b1274SAndroid Build Coastguard Worker 
274*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_DOUBLE:
275*254b1274SAndroid Build Coastguard Worker #ifndef CBOR_NO_FLOAT
276*254b1274SAndroid Build Coastguard Worker     CHECK(_write_double(ws, cb->v.dbl));
277*254b1274SAndroid Build Coastguard Worker #endif /* CBOR_NO_FLOAT */
278*254b1274SAndroid Build Coastguard Worker     break;
279*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_FLOAT:
280*254b1274SAndroid Build Coastguard Worker #ifndef CBOR_NO_FLOAT
281*254b1274SAndroid Build Coastguard Worker     CHECK(_write_double(ws, cb->v.f));
282*254b1274SAndroid Build Coastguard Worker #endif /* CBOR_NO_FLOAT */
283*254b1274SAndroid Build Coastguard Worker     break;
284*254b1274SAndroid Build Coastguard Worker 
285*254b1274SAndroid Build Coastguard Worker   case CN_CBOR_INVALID:
286*254b1274SAndroid Build Coastguard Worker     ws->offset = -1;
287*254b1274SAndroid Build Coastguard Worker     break;
288*254b1274SAndroid Build Coastguard Worker   }
289*254b1274SAndroid Build Coastguard Worker }
290*254b1274SAndroid Build Coastguard Worker 
_encoder_breaker(const cn_cbor * cb,int depth,void * context)291*254b1274SAndroid Build Coastguard Worker void _encoder_breaker(const cn_cbor *cb, int depth, void *context)
292*254b1274SAndroid Build Coastguard Worker {
293*254b1274SAndroid Build Coastguard Worker   cn_write_state *ws = context;
294*254b1274SAndroid Build Coastguard Worker   UNUSED_PARAM(cb);
295*254b1274SAndroid Build Coastguard Worker   UNUSED_PARAM(depth);
296*254b1274SAndroid Build Coastguard Worker   write_byte_ensured(IB_BREAK);
297*254b1274SAndroid Build Coastguard Worker }
298*254b1274SAndroid Build Coastguard Worker 
cn_cbor_encoder_write(uint8_t * buf,size_t buf_offset,size_t buf_size,const cn_cbor * cb)299*254b1274SAndroid Build Coastguard Worker ssize_t cn_cbor_encoder_write(uint8_t *buf,
300*254b1274SAndroid Build Coastguard Worker 			      size_t buf_offset,
301*254b1274SAndroid Build Coastguard Worker 			      size_t buf_size,
302*254b1274SAndroid Build Coastguard Worker 			      const cn_cbor *cb)
303*254b1274SAndroid Build Coastguard Worker {
304*254b1274SAndroid Build Coastguard Worker   cn_write_state ws = { buf, buf_offset, buf_size };
305*254b1274SAndroid Build Coastguard Worker   _visit(cb, _encoder_visitor, _encoder_breaker, &ws);
306*254b1274SAndroid Build Coastguard Worker   if (ws.offset < 0) { return -1; }
307*254b1274SAndroid Build Coastguard Worker   return ws.offset - buf_offset;
308*254b1274SAndroid Build Coastguard Worker }
309*254b1274SAndroid Build Coastguard Worker 
310*254b1274SAndroid Build Coastguard Worker #ifdef  __cplusplus
311*254b1274SAndroid Build Coastguard Worker }
312*254b1274SAndroid Build Coastguard Worker #endif
313*254b1274SAndroid Build Coastguard Worker 
314*254b1274SAndroid Build Coastguard Worker #endif  /* CN_CBOR_C */
315