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