xref: /freebsd/contrib/libxo/encoder/cbor/enc_cbor.c (revision 76afb20c58adb296f09857aed214b91464242264)
1d1a0d267SMarcel Moolenaar /*
2d1a0d267SMarcel Moolenaar  * Copyright (c) 2015, Juniper Networks, Inc.
3d1a0d267SMarcel Moolenaar  * All rights reserved.
4d1a0d267SMarcel Moolenaar  * This SOFTWARE is licensed under the LICENSE provided in the
5d1a0d267SMarcel Moolenaar  * ../Copyright file. By downloading, installing, copying, or otherwise
6d1a0d267SMarcel Moolenaar  * using the SOFTWARE, you agree to be bound by the terms of that
7d1a0d267SMarcel Moolenaar  * LICENSE.
8d1a0d267SMarcel Moolenaar  * Phil Shafer, August 2015
9d1a0d267SMarcel Moolenaar  */
10d1a0d267SMarcel Moolenaar 
11d1a0d267SMarcel Moolenaar /*
12d1a0d267SMarcel Moolenaar  * CBOR (RFC 7049) mades a suitable test case for libxo's external
13d1a0d267SMarcel Moolenaar  * encoder API.  It's simple, streaming, well documented, and an
14d1a0d267SMarcel Moolenaar  * IETF standard.
15d1a0d267SMarcel Moolenaar  *
16d1a0d267SMarcel Moolenaar  * This encoder uses the "pretty" flag for diagnostics, which isn't
17d1a0d267SMarcel Moolenaar  * really kosher, but it's example code.
18d1a0d267SMarcel Moolenaar  */
19d1a0d267SMarcel Moolenaar 
20d1a0d267SMarcel Moolenaar #include <string.h>
21d1a0d267SMarcel Moolenaar #include <sys/types.h>
22d1a0d267SMarcel Moolenaar #include <unistd.h>
23d1a0d267SMarcel Moolenaar #include <stdint.h>
24d1a0d267SMarcel Moolenaar #include <ctype.h>
25d1a0d267SMarcel Moolenaar #include <stdlib.h>
26d1a0d267SMarcel Moolenaar #include <limits.h>
27d1a0d267SMarcel Moolenaar 
28d1a0d267SMarcel Moolenaar #include "xo.h"
29d1a0d267SMarcel Moolenaar #include "xo_encoder.h"
30d1a0d267SMarcel Moolenaar #include "xo_buf.h"
31d1a0d267SMarcel Moolenaar 
32d1a0d267SMarcel Moolenaar /*
33d1a0d267SMarcel Moolenaar  * memdump(): dump memory contents in hex/ascii
34d1a0d267SMarcel Moolenaar 0         1         2         3         4         5         6         7
35d1a0d267SMarcel Moolenaar 0123456789012345678901234567890123456789012345678901234567890123456789012345
36d1a0d267SMarcel Moolenaar XX XX XX XX  XX XX XX XX - XX XX XX XX  XX XX XX XX abcdefghijklmnop
37d1a0d267SMarcel Moolenaar  */
38d1a0d267SMarcel Moolenaar static void
cbor_memdump(FILE * fp,const char * title,const char * data,size_t len,const char * tag,int indent)39d1a0d267SMarcel Moolenaar cbor_memdump (FILE *fp, const char *title, const char *data,
40d1a0d267SMarcel Moolenaar          size_t len, const char *tag, int indent)
41d1a0d267SMarcel Moolenaar {
42d1a0d267SMarcel Moolenaar     enum { MAX_PER_LINE = 16 };
43d1a0d267SMarcel Moolenaar     char buf[ 80 ];
44d1a0d267SMarcel Moolenaar     char text[ 80 ];
45d1a0d267SMarcel Moolenaar     char *bp, *tp;
46d1a0d267SMarcel Moolenaar     size_t i;
47d1a0d267SMarcel Moolenaar #if 0
48d1a0d267SMarcel Moolenaar     static const int ends[ MAX_PER_LINE ] = { 2, 5, 8, 11, 15, 18, 21, 24,
49d1a0d267SMarcel Moolenaar                                               29, 32, 35, 38, 42, 45, 48, 51 };
50d1a0d267SMarcel Moolenaar #endif
51d1a0d267SMarcel Moolenaar 
52d1a0d267SMarcel Moolenaar     if (fp == NULL)
53d1a0d267SMarcel Moolenaar 	fp = stdout;
54d1a0d267SMarcel Moolenaar     if (tag == NULL)
55d1a0d267SMarcel Moolenaar 	tag = "";
56d1a0d267SMarcel Moolenaar 
57d1a0d267SMarcel Moolenaar     fprintf(fp, "%*s[%s] @ %p (%lx/%lu)\n", indent + 1, tag,
58d1a0d267SMarcel Moolenaar             title, data, (unsigned long) len, (unsigned long) len);
59d1a0d267SMarcel Moolenaar 
60d1a0d267SMarcel Moolenaar     while (len > 0) {
61d1a0d267SMarcel Moolenaar         bp = buf;
62d1a0d267SMarcel Moolenaar         tp = text;
63d1a0d267SMarcel Moolenaar 
64d1a0d267SMarcel Moolenaar         for (i = 0; i < MAX_PER_LINE && i < len; i++) {
65d1a0d267SMarcel Moolenaar             if (i && (i % 4) == 0) *bp++ = ' ';
66d1a0d267SMarcel Moolenaar             if (i == 8) {
67d1a0d267SMarcel Moolenaar                 *bp++ = '-';
68d1a0d267SMarcel Moolenaar                 *bp++ = ' ';
69d1a0d267SMarcel Moolenaar             }
70d1a0d267SMarcel Moolenaar             sprintf(bp, "%02x ", (unsigned char) *data);
71d1a0d267SMarcel Moolenaar             bp += strlen(bp);
72d1a0d267SMarcel Moolenaar             *tp++ = (isprint((int) *data) && *data >= ' ') ? *data : '.';
73d1a0d267SMarcel Moolenaar             data += 1;
74d1a0d267SMarcel Moolenaar         }
75d1a0d267SMarcel Moolenaar 
76d1a0d267SMarcel Moolenaar         *tp = 0;
77d1a0d267SMarcel Moolenaar         *bp = 0;
78d1a0d267SMarcel Moolenaar         fprintf(fp, "%*s%-54s%s\n", indent + 1, tag, buf, text);
79d1a0d267SMarcel Moolenaar         len -= i;
80d1a0d267SMarcel Moolenaar     }
81d1a0d267SMarcel Moolenaar }
82d1a0d267SMarcel Moolenaar 
83d1a0d267SMarcel Moolenaar /*
84d1a0d267SMarcel Moolenaar  * CBOR breaks the first byte into two pieces, the major type in the
85d1a0d267SMarcel Moolenaar  * top 3 bits and the minor value in the low 5 bits.  The value can be
86d1a0d267SMarcel Moolenaar  * a small value (0 .. 23), an 8-bit value (24), a 16-bit value (25),
87d1a0d267SMarcel Moolenaar  * a 32-bit value (26), or a 64-bit value (27).  A value of 31
88d1a0d267SMarcel Moolenaar  * represents an unknown length, which we'll use extensively for
89d1a0d267SMarcel Moolenaar  * streaming our content.
90d1a0d267SMarcel Moolenaar  */
91d1a0d267SMarcel Moolenaar #define CBOR_MAJOR_MASK	0xE0
92d1a0d267SMarcel Moolenaar #define CBOR_MINOR_MASK	0x1F
93d1a0d267SMarcel Moolenaar #define CBOR_MAJOR_SHIFT	5
94d1a0d267SMarcel Moolenaar 
95d1a0d267SMarcel Moolenaar #define CBOR_MAJOR(_x)	  ((_x) & CBOR_MAJOR_MASK)
96d1a0d267SMarcel Moolenaar #define CBOR_MAJOR_VAL(_x) ((_x) << CBOR_MAJOR_SHIFT)
97d1a0d267SMarcel Moolenaar #define CBOR_MINOR_VAL(_x) ((_x) & CBOR_MINOR_MASK)
98d1a0d267SMarcel Moolenaar 
99d1a0d267SMarcel Moolenaar /* Major type codes */
100d1a0d267SMarcel Moolenaar #define CBOR_UNSIGNED	CBOR_MAJOR_VAL(0) /* 0x00 */
101d1a0d267SMarcel Moolenaar #define CBOR_NEGATIVE	CBOR_MAJOR_VAL(1) /* 0x20 */
102d1a0d267SMarcel Moolenaar #define CBOR_BYTES	CBOR_MAJOR_VAL(2) /* 0x40 */
103d1a0d267SMarcel Moolenaar #define CBOR_STRING	CBOR_MAJOR_VAL(3) /* 0x60 */
104d1a0d267SMarcel Moolenaar #define CBOR_ARRAY	CBOR_MAJOR_VAL(4) /* 0x80 */
105d1a0d267SMarcel Moolenaar #define CBOR_MAP	CBOR_MAJOR_VAL(5) /* 0xa0 */
106d1a0d267SMarcel Moolenaar #define CBOR_SEMANTIC	CBOR_MAJOR_VAL(6) /* 0xc0 */
107d1a0d267SMarcel Moolenaar #define CBOR_SPECIAL	CBOR_MAJOR_VAL(7) /* 0xe0 */
108d1a0d267SMarcel Moolenaar 
109d1a0d267SMarcel Moolenaar #define CBOR_ULIMIT	24	/* Largest unsigned value */
110d1a0d267SMarcel Moolenaar #define CBOR_NLIMIT	23	/* Largest negative value */
111d1a0d267SMarcel Moolenaar 
112d1a0d267SMarcel Moolenaar #define CBOR_BREAK	0xFF
113d1a0d267SMarcel Moolenaar #define CBOR_INDEF	0x1F
114d1a0d267SMarcel Moolenaar 
115d1a0d267SMarcel Moolenaar #define CBOR_FALSE	0xF4
116d1a0d267SMarcel Moolenaar #define CBOR_TRUE	0xF5
117d1a0d267SMarcel Moolenaar #define CBOR_NULL	0xF6
118d1a0d267SMarcel Moolenaar #define CBOR_UNDEF	0xF7
119d1a0d267SMarcel Moolenaar 
120d1a0d267SMarcel Moolenaar #define CBOR_LEN8	0x18	/* 24 - 8-bit value */
121d1a0d267SMarcel Moolenaar #define CBOR_LEN16	0x19	/* 25 - 16-bit value */
122d1a0d267SMarcel Moolenaar #define CBOR_LEN32	0x1a	/* 26 - 32-bit value */
123d1a0d267SMarcel Moolenaar #define CBOR_LEN64	0x1b	/* 27 - 64-bit value */
124d1a0d267SMarcel Moolenaar #define CBOR_LEN128	0x1c	/* 28 - 128-bit value */
125d1a0d267SMarcel Moolenaar 
126d1a0d267SMarcel Moolenaar typedef struct cbor_private_s {
127d1a0d267SMarcel Moolenaar     xo_buffer_t c_data;		/* Our data buffer */
128d1a0d267SMarcel Moolenaar     unsigned c_indent;		/* Indent level */
129d1a0d267SMarcel Moolenaar     unsigned c_open_leaf_list;	/* Open leaf list construct? */
130d1a0d267SMarcel Moolenaar } cbor_private_t;
131d1a0d267SMarcel Moolenaar 
132d1a0d267SMarcel Moolenaar static void
cbor_encode_uint(xo_buffer_t * xbp,uint64_t minor,unsigned limit)133d1a0d267SMarcel Moolenaar cbor_encode_uint (xo_buffer_t *xbp, uint64_t minor, unsigned limit)
134d1a0d267SMarcel Moolenaar {
135d1a0d267SMarcel Moolenaar     char *bp = xbp->xb_curp;
136d1a0d267SMarcel Moolenaar     int i, m;
137d1a0d267SMarcel Moolenaar 
13842ff34c3SPhil Shafer     if (minor > (1ULL << 32)) {
139d1a0d267SMarcel Moolenaar 	*bp++ |= CBOR_LEN64;
140d1a0d267SMarcel Moolenaar 	m = 64;
141d1a0d267SMarcel Moolenaar 
142d1a0d267SMarcel Moolenaar     } else if (minor > (1<<16)) {
143d1a0d267SMarcel Moolenaar 	*bp++ |= CBOR_LEN32;
144d1a0d267SMarcel Moolenaar 	m = 32;
145d1a0d267SMarcel Moolenaar 
146d1a0d267SMarcel Moolenaar     } else if (minor > (1<<8)) {
147d1a0d267SMarcel Moolenaar 	*bp++ |= CBOR_LEN16;
148d1a0d267SMarcel Moolenaar 	m = 16;
149d1a0d267SMarcel Moolenaar 
150d1a0d267SMarcel Moolenaar     } else if (minor > limit) {
151d1a0d267SMarcel Moolenaar 	*bp++ |= CBOR_LEN8;
152d1a0d267SMarcel Moolenaar 	m = 8;
153d1a0d267SMarcel Moolenaar     } else {
154d1a0d267SMarcel Moolenaar 	*bp++ |= minor & CBOR_MINOR_MASK;
155d1a0d267SMarcel Moolenaar 	m = 0;
156d1a0d267SMarcel Moolenaar     }
157d1a0d267SMarcel Moolenaar 
158d1a0d267SMarcel Moolenaar     if (m) {
159d1a0d267SMarcel Moolenaar 	for (i = m - 8; i >= 0; i -= 8)
160d1a0d267SMarcel Moolenaar 	    *bp++ = minor >> i;
161d1a0d267SMarcel Moolenaar     }
162d1a0d267SMarcel Moolenaar 
163d1a0d267SMarcel Moolenaar     xbp->xb_curp = bp;
164d1a0d267SMarcel Moolenaar }
165d1a0d267SMarcel Moolenaar 
166d1a0d267SMarcel Moolenaar static void
cbor_append(xo_handle_t * xop,cbor_private_t * cbor,xo_buffer_t * xbp,unsigned major,unsigned minor,const char * data)167d1a0d267SMarcel Moolenaar cbor_append (xo_handle_t *xop, cbor_private_t *cbor, xo_buffer_t *xbp,
168d1a0d267SMarcel Moolenaar 	     unsigned major, unsigned minor, const char *data)
169d1a0d267SMarcel Moolenaar {
170d1a0d267SMarcel Moolenaar     if (!xo_buf_has_room(xbp, minor + 2))
171d1a0d267SMarcel Moolenaar 	return;
172d1a0d267SMarcel Moolenaar 
173d1a0d267SMarcel Moolenaar     unsigned offset = xo_buf_offset(xbp);
174d1a0d267SMarcel Moolenaar 
175d1a0d267SMarcel Moolenaar     *xbp->xb_curp = major;
176d1a0d267SMarcel Moolenaar     cbor_encode_uint(xbp, minor, CBOR_ULIMIT);
177d1a0d267SMarcel Moolenaar     if (data)
178d1a0d267SMarcel Moolenaar 	xo_buf_append(xbp, data, minor);
179d1a0d267SMarcel Moolenaar 
180d1a0d267SMarcel Moolenaar     if (xo_get_flags(xop) & XOF_PRETTY)
181d1a0d267SMarcel Moolenaar 	cbor_memdump(stdout, "append", xo_buf_data(xbp, offset),
182d1a0d267SMarcel Moolenaar 		     xbp->xb_curp - xbp->xb_bufp - offset, "",
183d1a0d267SMarcel Moolenaar 		     cbor->c_indent * 2);
184d1a0d267SMarcel Moolenaar }
185d1a0d267SMarcel Moolenaar 
186d1a0d267SMarcel Moolenaar static int
cbor_create(xo_handle_t * xop)187d1a0d267SMarcel Moolenaar cbor_create (xo_handle_t *xop)
188d1a0d267SMarcel Moolenaar {
189d1a0d267SMarcel Moolenaar     cbor_private_t *cbor = xo_realloc(NULL, sizeof(*cbor));
190d1a0d267SMarcel Moolenaar     if (cbor == NULL)
191d1a0d267SMarcel Moolenaar 	return -1;
192d1a0d267SMarcel Moolenaar 
193d1a0d267SMarcel Moolenaar     bzero(cbor, sizeof(*cbor));
194d1a0d267SMarcel Moolenaar     xo_buf_init(&cbor->c_data);
195d1a0d267SMarcel Moolenaar 
196d1a0d267SMarcel Moolenaar     xo_set_private(xop, cbor);
197d1a0d267SMarcel Moolenaar 
198d1a0d267SMarcel Moolenaar     cbor_append(xop, cbor, &cbor->c_data, CBOR_MAP | CBOR_INDEF, 0, NULL);
199d1a0d267SMarcel Moolenaar 
200d1a0d267SMarcel Moolenaar     return 0;
201d1a0d267SMarcel Moolenaar }
202d1a0d267SMarcel Moolenaar 
203d1a0d267SMarcel Moolenaar static int
cbor_content(xo_handle_t * xop,cbor_private_t * cbor,xo_buffer_t * xbp,const char * value)204d1a0d267SMarcel Moolenaar cbor_content (xo_handle_t *xop, cbor_private_t *cbor, xo_buffer_t *xbp,
205d1a0d267SMarcel Moolenaar 	      const char *value)
206d1a0d267SMarcel Moolenaar {
207d1a0d267SMarcel Moolenaar     int rc = 0;
208d1a0d267SMarcel Moolenaar 
209d1a0d267SMarcel Moolenaar     unsigned offset = xo_buf_offset(xbp);
210d1a0d267SMarcel Moolenaar 
211*76afb20cSPhil Shafer     if (value == NULL || *value == '\0' || xo_streq(value, "true"))
212d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, &cbor->c_data, CBOR_TRUE, 0, NULL);
213*76afb20cSPhil Shafer     else if (xo_streq(value, "false"))
214d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, &cbor->c_data, CBOR_FALSE, 0, NULL);
215d1a0d267SMarcel Moolenaar     else {
216d1a0d267SMarcel Moolenaar 	int negative = 0;
217d1a0d267SMarcel Moolenaar 	if (*value == '-') {
218d1a0d267SMarcel Moolenaar 	    value += 1;
219d1a0d267SMarcel Moolenaar 	    negative = 1;
220d1a0d267SMarcel Moolenaar 	}
221d1a0d267SMarcel Moolenaar 
222d1a0d267SMarcel Moolenaar 	char *ep;
223d1a0d267SMarcel Moolenaar 	unsigned long long ival;
224d1a0d267SMarcel Moolenaar 	ival = strtoull(value, &ep, 0);
225d1a0d267SMarcel Moolenaar 	if (ival == ULLONG_MAX)	/* Sometimes a string is just a string */
226d1a0d267SMarcel Moolenaar 	    cbor_append(xop, cbor, xbp, CBOR_STRING, strlen(value), value);
227d1a0d267SMarcel Moolenaar 	else {
228d1a0d267SMarcel Moolenaar 	    *xbp->xb_curp = negative ? CBOR_NEGATIVE : CBOR_UNSIGNED;
229d1a0d267SMarcel Moolenaar 	    if (negative)
230d1a0d267SMarcel Moolenaar 		ival -= 1;	/* Don't waste a negative zero */
231d1a0d267SMarcel Moolenaar 	    cbor_encode_uint(xbp, ival, negative ? CBOR_NLIMIT : CBOR_ULIMIT);
232d1a0d267SMarcel Moolenaar 	}
233d1a0d267SMarcel Moolenaar     }
234d1a0d267SMarcel Moolenaar 
235d1a0d267SMarcel Moolenaar     if (xo_get_flags(xop) & XOF_PRETTY)
236d1a0d267SMarcel Moolenaar 	cbor_memdump(stdout, "content", xo_buf_data(xbp, offset),
237d1a0d267SMarcel Moolenaar 		     xbp->xb_curp - xbp->xb_bufp - offset, "",
238d1a0d267SMarcel Moolenaar 		     cbor->c_indent * 2);
239d1a0d267SMarcel Moolenaar 
240d1a0d267SMarcel Moolenaar     return rc;
241d1a0d267SMarcel Moolenaar }
242d1a0d267SMarcel Moolenaar 
243d1a0d267SMarcel Moolenaar static int
cbor_handler(XO_ENCODER_HANDLER_ARGS)244d1a0d267SMarcel Moolenaar cbor_handler (XO_ENCODER_HANDLER_ARGS)
245d1a0d267SMarcel Moolenaar {
246d1a0d267SMarcel Moolenaar     int rc = 0;
247d1a0d267SMarcel Moolenaar     cbor_private_t *cbor = private;
248d1a0d267SMarcel Moolenaar     xo_buffer_t *xbp = cbor ? &cbor->c_data : NULL;
249d1a0d267SMarcel Moolenaar 
250d1a0d267SMarcel Moolenaar     if (xo_get_flags(xop) & XOF_PRETTY) {
251d1a0d267SMarcel Moolenaar 	printf("%*sop %s: [%s] [%s]\n", cbor ? cbor->c_indent * 2 + 4 : 0, "",
252f2b7bf8aSPhil Shafer 	       xo_encoder_op_name(op), name, value);
253d1a0d267SMarcel Moolenaar 	fflush(stdout);
254d1a0d267SMarcel Moolenaar     }
255d1a0d267SMarcel Moolenaar 
256d1a0d267SMarcel Moolenaar     /* If we don't have private data, we're sunk */
257d1a0d267SMarcel Moolenaar     if (cbor == NULL && op != XO_OP_CREATE)
258d1a0d267SMarcel Moolenaar 	return -1;
259d1a0d267SMarcel Moolenaar 
260d1a0d267SMarcel Moolenaar     switch (op) {
261d1a0d267SMarcel Moolenaar     case XO_OP_CREATE:		/* Called when the handle is init'd */
262d1a0d267SMarcel Moolenaar 	rc = cbor_create(xop);
263d1a0d267SMarcel Moolenaar 	break;
264d1a0d267SMarcel Moolenaar 
265d1a0d267SMarcel Moolenaar     case XO_OP_OPEN_CONTAINER:
266d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_STRING, strlen(name), name);
267d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_MAP | CBOR_INDEF, 0, NULL);
268d1a0d267SMarcel Moolenaar 	cbor->c_indent += 1;
269d1a0d267SMarcel Moolenaar 	break;
270d1a0d267SMarcel Moolenaar 
271d1a0d267SMarcel Moolenaar     case XO_OP_CLOSE_CONTAINER:
272d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_BREAK, 0, NULL);
273d1a0d267SMarcel Moolenaar 	cbor->c_indent -= 1;
274d1a0d267SMarcel Moolenaar 	break;
275d1a0d267SMarcel Moolenaar 
276d1a0d267SMarcel Moolenaar     case XO_OP_OPEN_LIST:
277d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_STRING, strlen(name), name);
278d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_ARRAY | CBOR_INDEF, 0, NULL);
279d1a0d267SMarcel Moolenaar 	cbor->c_indent += 1;
280d1a0d267SMarcel Moolenaar 	break;
281d1a0d267SMarcel Moolenaar 
282d1a0d267SMarcel Moolenaar     case XO_OP_CLOSE_LIST:
283d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_BREAK, 0, NULL);
284d1a0d267SMarcel Moolenaar 	cbor->c_indent -= 1;
285d1a0d267SMarcel Moolenaar 	break;
286d1a0d267SMarcel Moolenaar 
287d1a0d267SMarcel Moolenaar     case XO_OP_OPEN_LEAF_LIST:
288d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_STRING, strlen(name), name);
289d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_ARRAY | CBOR_INDEF, 0, NULL);
290d1a0d267SMarcel Moolenaar 	cbor->c_indent += 1;
291d1a0d267SMarcel Moolenaar 	cbor->c_open_leaf_list = 1;
292d1a0d267SMarcel Moolenaar 	break;
293d1a0d267SMarcel Moolenaar 
294d1a0d267SMarcel Moolenaar     case XO_OP_CLOSE_LEAF_LIST:
295d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_BREAK, 0, NULL);
296d1a0d267SMarcel Moolenaar 	cbor->c_indent -= 1;
297d1a0d267SMarcel Moolenaar 	cbor->c_open_leaf_list = 0;
298d1a0d267SMarcel Moolenaar 	break;
299d1a0d267SMarcel Moolenaar 
300d1a0d267SMarcel Moolenaar     case XO_OP_OPEN_INSTANCE:
301d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_MAP | CBOR_INDEF, 0, NULL);
302d1a0d267SMarcel Moolenaar 	cbor->c_indent += 1;
303d1a0d267SMarcel Moolenaar 	break;
304d1a0d267SMarcel Moolenaar 
305d1a0d267SMarcel Moolenaar     case XO_OP_CLOSE_INSTANCE:
306d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_BREAK, 0, NULL);
307d1a0d267SMarcel Moolenaar 	cbor->c_indent -= 1;
308d1a0d267SMarcel Moolenaar 	break;
309d1a0d267SMarcel Moolenaar 
310d1a0d267SMarcel Moolenaar     case XO_OP_STRING:		   /* Quoted UTF-8 string */
311d1a0d267SMarcel Moolenaar 	if (!cbor->c_open_leaf_list)
312d1a0d267SMarcel Moolenaar 	    cbor_append(xop, cbor, xbp, CBOR_STRING, strlen(name), name);
313d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_STRING, strlen(value), value);
314d1a0d267SMarcel Moolenaar 	break;
315d1a0d267SMarcel Moolenaar 
316d1a0d267SMarcel Moolenaar     case XO_OP_CONTENT:		   /* Other content */
317d1a0d267SMarcel Moolenaar 	if (!cbor->c_open_leaf_list)
318d1a0d267SMarcel Moolenaar 	    cbor_append(xop, cbor, xbp, CBOR_STRING, strlen(name), name);
319d1a0d267SMarcel Moolenaar 
320d1a0d267SMarcel Moolenaar 	/*
321d1a0d267SMarcel Moolenaar 	 * It's content, not string, so we need to look at the
322d1a0d267SMarcel Moolenaar 	 * string and build some content.  Turns out we only
323d1a0d267SMarcel Moolenaar 	 * care about true, false, null, and numbers.
324d1a0d267SMarcel Moolenaar 	 */
325d1a0d267SMarcel Moolenaar 	cbor_content(xop, cbor, xbp, value);
326d1a0d267SMarcel Moolenaar 	break;
327d1a0d267SMarcel Moolenaar 
328d1a0d267SMarcel Moolenaar     case XO_OP_FINISH:		   /* Clean up function */
329d1a0d267SMarcel Moolenaar 	cbor_append(xop, cbor, xbp, CBOR_BREAK, 0, NULL);
330d1a0d267SMarcel Moolenaar 	cbor->c_indent -= 1;
331d1a0d267SMarcel Moolenaar 	break;
332d1a0d267SMarcel Moolenaar 
333d1a0d267SMarcel Moolenaar     case XO_OP_FLUSH:		   /* Clean up function */
334d1a0d267SMarcel Moolenaar 	if (xo_get_flags(xop) & XOF_PRETTY)
335d1a0d267SMarcel Moolenaar 	    cbor_memdump(stdout, "cbor",
336d1a0d267SMarcel Moolenaar 			xbp->xb_bufp, xbp->xb_curp - xbp->xb_bufp,
337d1a0d267SMarcel Moolenaar 			">", 0);
338d1a0d267SMarcel Moolenaar 	else {
339d1a0d267SMarcel Moolenaar 	    rc = write(1, xbp->xb_bufp, xbp->xb_curp - xbp->xb_bufp);
340d1a0d267SMarcel Moolenaar 	    if (rc > 0)
341d1a0d267SMarcel Moolenaar 		rc = 0;
342d1a0d267SMarcel Moolenaar 	}
343d1a0d267SMarcel Moolenaar 	break;
344d1a0d267SMarcel Moolenaar 
345d1a0d267SMarcel Moolenaar     case XO_OP_DESTROY:		   /* Clean up function */
346d1a0d267SMarcel Moolenaar 	break;
347d1a0d267SMarcel Moolenaar 
348d1a0d267SMarcel Moolenaar     case XO_OP_ATTRIBUTE:	   /* Attribute name/value */
349d1a0d267SMarcel Moolenaar 	break;
350d1a0d267SMarcel Moolenaar 
351d1a0d267SMarcel Moolenaar     case XO_OP_VERSION:		/* Version string */
352d1a0d267SMarcel Moolenaar 	break;
353d1a0d267SMarcel Moolenaar 
354d1a0d267SMarcel Moolenaar     }
355d1a0d267SMarcel Moolenaar 
356d1a0d267SMarcel Moolenaar     return rc;
357d1a0d267SMarcel Moolenaar }
358d1a0d267SMarcel Moolenaar 
359d1a0d267SMarcel Moolenaar int
xo_encoder_library_init(XO_ENCODER_INIT_ARGS)360d1a0d267SMarcel Moolenaar xo_encoder_library_init (XO_ENCODER_INIT_ARGS)
361d1a0d267SMarcel Moolenaar {
362d1a0d267SMarcel Moolenaar     arg->xei_handler = cbor_handler;
363*76afb20cSPhil Shafer     arg->xei_version = XO_ENCODER_VERSION;
364d1a0d267SMarcel Moolenaar 
365d1a0d267SMarcel Moolenaar     return 0;
366d1a0d267SMarcel Moolenaar }
367