Branch data Line data Source code
1 : : /*
2 : : * Runtime support for printing flatbuffers to JSON.
3 : : */
4 : :
5 : : #include <stdio.h>
6 : : #include <assert.h>
7 : : #include <string.h>
8 : : #include <stdlib.h>
9 : :
10 : : #include "flatcc/flatcc_rtconfig.h"
11 : :
12 : : /*
13 : : * Grisu significantly improves printing speed of floating point values
14 : : * and also the overall printing speed when floating point values are
15 : : * present in non-trivial amounts. (Also applies to parsing).
16 : : */
17 : : #if FLATCC_USE_GRISU3 && !defined(PORTABLE_USE_GRISU3)
18 : : #define PORTABLE_USE_GRISU3 1
19 : : #endif
20 : :
21 : : #include "flatcc/flatcc_flatbuffers.h"
22 : : #include "flatcc/flatcc_json_printer.h"
23 : :
24 : : #include "flatcc/portable/pprintint.h"
25 : : #include "flatcc/portable/pprintfp.h"
26 : :
27 : : #define RAISE_ERROR(err) flatcc_json_printer_set_error(ctx, flatcc_json_printer_error_##err)
28 : :
29 [ # # ]: 0 : const char *flatcc_json_printer_error_string(int err)
30 : : {
31 : : switch (err) {
32 : : #define XX(no, str) \
33 : : case flatcc_json_printer_error_##no: \
34 : : return str;
35 : : FLATCC_JSON_PRINT_ERROR_MAP(XX)
36 : : #undef XX
37 : : default:
38 : : return "unknown";
39 : : }
40 : : }
41 : :
42 : : #define uoffset_t flatbuffers_uoffset_t
43 : : #define soffset_t flatbuffers_soffset_t
44 : : #define voffset_t flatbuffers_voffset_t
45 : : #define utype_t flatbuffers_utype_t
46 : :
47 : : #define uoffset_size sizeof(uoffset_t)
48 : : #define soffset_size sizeof(soffset_t)
49 : : #define voffset_size sizeof(voffset_t)
50 : : #define utype_size sizeof(utype_t)
51 : :
52 : : #define offset_size uoffset_size
53 : :
54 : : /* This hardcodes utype to uint8 so change if relevant. */
55 : : #define print_utype print_uint8
56 : :
57 : : static inline const void *read_uoffset_ptr(const void *p)
58 : : {
59 : 109 : return (uint8_t *)p + __flatbuffers_uoffset_read_from_pe(p);
60 : : }
61 : :
62 : : static inline voffset_t read_voffset(const void *p, uoffset_t base)
63 : : {
64 : 330 : return __flatbuffers_voffset_read_from_pe((uint8_t *)p + base);
65 : : }
66 : :
67 : : static inline const void *get_field_ptr(flatcc_json_printer_table_descriptor_t *td, int id)
68 : : {
69 : 1210 : int vo = (id + 2) * sizeof(voffset_t);
70 : :
71 [ + + ][ + + ]: 1210 : if (vo >= td->vsize) {
[ # # ][ + - ]
[ + + ][ + + ]
[ + + ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + + ]
[ + + ][ + + ]
[ + - ][ # # ]
[ + + ][ + + ]
[ - + ][ # # ]
[ + + ]
72 : : return 0;
73 : : }
74 : 330 : vo = read_voffset(td->vtable, vo);
75 [ + + ][ + + ]: 330 : if (vo == 0) {
[ # # ][ + + ]
[ + + ][ + + ]
[ + + ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ - + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ + + ]
[ # # ][ # # ]
[ # # ][ # # ]
[ + + ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ - + ]
[ + + ][ + + ]
[ + + ][ # # ]
[ + + ][ + + ]
[ # # ][ # # ]
[ + - ]
76 : : return 0;
77 : : }
78 : 108 : return (uint8_t *)td->table + vo;
79 : : }
80 : :
81 : : #define print_char(c) *ctx->p++ = (c)
82 : :
83 : : #define print_start(c) do { \
84 : : ++ctx->level; \
85 : : *ctx->p++ = c; \
86 : : } while (0)
87 : :
88 : : #define print_end(c) do { \
89 : : if (ctx->indent) { \
90 : : *ctx->p++ = '\n'; \
91 : : --ctx->level; \
92 : : print_indent(ctx); \
93 : : } \
94 : : *ctx->p++ = c; \
95 : : } while (0)
96 : :
97 : : #define print_space() do { \
98 : : *ctx->p = ' '; \
99 : : ctx->p += !!ctx->indent; \
100 : : } while (0)
101 : :
102 : : #define print_nl() do { \
103 : : if (ctx->indent) { \
104 : : *ctx->p++ = '\n'; \
105 : : print_indent(ctx); \
106 : : } else { \
107 : : flatcc_json_printer_flush_partial(ctx); \
108 : : } \
109 : : } while (0)
110 : :
111 : : /* Call at the end so print_end does not have to check for level. */
112 : : #define print_last_nl() do { \
113 : : if (ctx->indent && ctx->level == 0) { \
114 : : *ctx->p++ = '\n'; \
115 : : } \
116 : : flatcc_json_printer_flush_partial(ctx); \
117 : : } while (0)
118 : :
119 : 0 : int flatcc_json_printer_fmt_float(char *buf, float n)
120 : : {
121 : : #if FLATCC_JSON_PRINT_HEX_FLOAT
122 : : return print_hex_float(buf, n);
123 : : #else
124 : 0 : return print_float(n, buf);
125 : : #endif
126 : : }
127 : :
128 : 0 : int flatcc_json_printer_fmt_double(char *buf, double n)
129 : : {
130 : : #if FLATCC_JSON_PRINT_HEX_FLOAT
131 : : return print_hex_double(buf, n);
132 : : #else
133 : 0 : return print_double(n, buf);
134 : : #endif
135 : : }
136 : :
137 : 0 : int flatcc_json_printer_fmt_bool(char *buf, int n)
138 : : {
139 [ # # ]: 0 : if (n) {
140 : 0 : memcpy(buf, "true", 4);
141 : 0 : return 4;
142 : : }
143 : 0 : memcpy(buf, "false", 5);
144 : 0 : return 5;
145 : : }
146 : :
147 : 97 : static void print_string_part(flatcc_json_printer_t *ctx, const char *name, size_t len)
148 : : {
149 : : size_t k;
150 : :
151 [ - + ]: 97 : if (ctx->p + len >= ctx->pflush) {
152 [ # # ]: 0 : if (ctx->p >= ctx->pflush) {
153 : 0 : ctx->flush(ctx, 0);
154 : : }
155 : : do {
156 : 0 : k = ctx->pflush - ctx->p;
157 : 0 : memcpy(ctx->p, name, k);
158 : 0 : ctx->p += k;
159 : 0 : name += k;
160 : 0 : len -= k;
161 : 0 : ctx->flush(ctx, 0);
162 [ # # ]: 0 : } while (ctx->p + len >= ctx->pflush);
163 : : }
164 : 97 : memcpy(ctx->p, name, len);
165 : 97 : ctx->p += len;
166 : 97 : }
167 : :
168 : : /*
169 : : * Even though we know the the string length, we need to scan for escape
170 : : * characters. There may be embedded zeroes. Beause FlatBuffer strings
171 : : * are always zero terminated, we assume and optimize for this.
172 : : *
173 : : * We enforce \u00xx for control characters, but not for invalid
174 : : * characters like 0xff - this makes it possible to handle some other
175 : : * codepages transparently while formally not valid. (Formally JSON
176 : : * also supports UTF-16/32 little/big endian but flatbuffers only
177 : : * support UTF-8 and we expect this in JSON input/output too).
178 : : */
179 : 53 : static void print_string(flatcc_json_printer_t *ctx, const char *name, size_t len)
180 : : {
181 : : const char *p = name;
182 : : /* Unsigned is important. */
183 : : unsigned char c, x;
184 : : size_t k;
185 : :
186 : 53 : print_char('\"');
187 : : for (;;) {
188 : : /*
189 : : */
190 : 8 : c = *p;
191 [ + + ][ + + ]: 465 : while (c >= 0x20 && c != '\"' && c != '\\') {
192 : 404 : c = *++p;
193 : : }
194 : 61 : k = p - name;
195 : 61 : print_string_part(ctx, name, k);
196 : 61 : len -= k;
197 [ + + ]: 61 : if (len == 0) {
198 : : break;
199 : : }
200 : : name += k;
201 : 8 : print_char('\\');
202 [ + + + + : 8 : switch (c) {
+ + + + ]
203 : 1 : case '"': print_char('\"'); break;
204 : 1 : case '\\': print_char('\\'); break;
205 : 1 : case '\t' : print_char('t'); break;
206 : 1 : case '\f' : print_char('f'); break;
207 : 1 : case '\r' : print_char('r'); break;
208 : 1 : case '\n' : print_char('n'); break;
209 : 1 : case '\b' : print_char('b'); break;
210 : : default:
211 : 1 : print_char('u');
212 : 1 : print_char('0');
213 : 1 : print_char('0');
214 : 1 : x = c >> 4;
215 [ - + ]: 1 : x += x < 10 ? '0' : 'a' - 10;
216 : 1 : print_char(x);
217 : 1 : x = c & 15;
218 [ - + ]: 1 : x += x < 10 ? '0' : 'a' - 10;
219 : 1 : print_char(x);
220 : 1 : break;
221 : : }
222 : 8 : ++p;
223 : 8 : --len;
224 : : ++name;
225 : : }
226 : 53 : print_char('\"');
227 : 53 : }
228 : :
229 : 0 : static void print_indent_ex(flatcc_json_printer_t *ctx, size_t k)
230 : : {
231 : : size_t m;
232 : :
233 [ # # ]: 0 : if (ctx->p >= ctx->pflush) {
234 : 0 : ctx->flush(ctx, 0);
235 : : }
236 : 0 : m = ctx->pflush - ctx->p;
237 [ # # ]: 0 : while (k > m) {
238 : 0 : memset(ctx->p, ' ', m);
239 : 0 : ctx->p += m;
240 : 0 : k -= m;
241 : 0 : ctx->flush(ctx, 0);
242 : 0 : m = ctx->flush_size;
243 : : }
244 : 0 : memset(ctx->p, ' ', k);
245 : 0 : ctx->p += k;
246 : 0 : }
247 : :
248 : 47 : static inline void print_indent(flatcc_json_printer_t *ctx)
249 : : {
250 : 47 : size_t k = ctx->level * ctx->indent;
251 : :
252 [ - + ]: 47 : if (ctx->p + k > ctx->pflush) {
253 : 0 : print_indent_ex(ctx, k);
254 : : } else {
255 : 47 : memset(ctx->p, ' ', k);
256 : 47 : ctx->p += k;
257 : : }
258 : 47 : }
259 : :
260 : : /*
261 : : * Helpers for external use - does not do autmatic pretty printing, but
262 : : * does escape strings.
263 : : */
264 : 0 : void flatcc_json_printer_string(flatcc_json_printer_t *ctx, const char *s, int n)
265 : : {
266 : 0 : print_string(ctx, s, n);
267 : 0 : }
268 : 0 : void flatcc_json_printer_write(flatcc_json_printer_t *ctx, const char *s, int n)
269 : : {
270 : 0 : print_string_part(ctx, s, n);
271 : 0 : }
272 : 0 : void flatcc_json_printer_nl(flatcc_json_printer_t *ctx)
273 : : {
274 : 0 : print_char('\n');
275 : : flatcc_json_printer_flush_partial(ctx);
276 : 0 : }
277 : 0 : void flatcc_json_printer_char(flatcc_json_printer_t *ctx, char c)
278 : : {
279 : 0 : print_char(c);
280 : 0 : }
281 : 0 : void flatcc_json_printer_indent(flatcc_json_printer_t *ctx)
282 : : {
283 : : /*
284 : : * This is only needed when indent is 0 but helps external users
285 : : * to avoid flushing when indenting.
286 : : */
287 : 0 : print_indent(ctx);
288 : 0 : }
289 : 0 : void flatcc_json_printer_add_level(flatcc_json_printer_t *ctx, int n)
290 : : {
291 : 0 : ctx->level += n;
292 : 0 : }
293 : 0 : int flatcc_json_printer_get_level(flatcc_json_printer_t *ctx)
294 : : {
295 : 0 : return ctx->level;
296 : : }
297 : :
298 : 5 : static inline void print_type(flatcc_json_printer_t *ctx, const char *name, size_t len, utype_t type, const char *type_name, size_t type_len)
299 : : {
300 [ + + ]: 5 : print_nl();
301 : 5 : *ctx->p = '\"';
302 : 5 : ctx->p += !ctx->unquote;
303 [ + - ]: 5 : if (ctx->p + len < ctx->pflush) {
304 : 5 : memcpy(ctx->p, name, len);
305 : 5 : ctx->p += len;
306 : : } else {
307 : 0 : print_string_part(ctx, name, len);
308 : : }
309 : 5 : print_string_part(ctx, "_type", 5);
310 : 5 : *ctx->p = '\"';
311 : 5 : ctx->p += !ctx->unquote;
312 : 5 : print_char(':');
313 : 5 : print_space();
314 [ + - ][ - + ]: 5 : if (ctx->noenum || type_name == 0) {
315 : 0 : ctx->p += print_utype(type, ctx->p);
316 : : } else {
317 : 5 : *ctx->p = '\"';
318 : 5 : ctx->p += !ctx->unquote;
319 : 5 : print_string_part(ctx, type_name, type_len);
320 : 5 : *ctx->p = '\"';
321 : 5 : ctx->p += !ctx->unquote;
322 : : }
323 : 5 : }
324 : :
325 : 126 : static inline void print_symbol(flatcc_json_printer_t *ctx, const char *name, size_t len)
326 : : {
327 : 126 : *ctx->p = '\"';
328 : 126 : ctx->p += !ctx->unquote;
329 [ + - ]: 126 : if (ctx->p + len < ctx->pflush) {
330 : 126 : memcpy(ctx->p, name, len);
331 : 126 : ctx->p += len;
332 : : } else {
333 : 0 : print_string_part(ctx, name, len);
334 : : }
335 : 126 : *ctx->p = '\"';
336 : 126 : ctx->p += !ctx->unquote;
337 : 126 : }
338 : :
339 : 126 : static inline void print_name(flatcc_json_printer_t *ctx, const char *name, size_t len)
340 : : {
341 [ + + ]: 126 : print_nl();
342 : 126 : print_symbol(ctx, name, len);
343 : 126 : print_char(':');
344 : 126 : print_space();
345 : 126 : }
346 : :
347 : : #define __flatcc_define_json_printer_scalar(TN, T) \
348 : : void flatcc_json_printer_ ## TN( \
349 : : flatcc_json_printer_t *ctx, T v) \
350 : : { \
351 : : ctx->p += print_ ## TN(v, ctx->p); \
352 : : }
353 : :
354 : 0 : __flatcc_define_json_printer_scalar(uint8, uint8_t)
355 : 0 : __flatcc_define_json_printer_scalar(uint16, uint16_t)
356 : 0 : __flatcc_define_json_printer_scalar(uint32, uint32_t)
357 : 0 : __flatcc_define_json_printer_scalar(uint64, uint64_t)
358 : 4 : __flatcc_define_json_printer_scalar(int8, int8_t)
359 : 0 : __flatcc_define_json_printer_scalar(int16, int16_t)
360 : 0 : __flatcc_define_json_printer_scalar(int32, int32_t)
361 : 0 : __flatcc_define_json_printer_scalar(int64, int64_t)
362 : 0 : __flatcc_define_json_printer_scalar(float, float)
363 : 0 : __flatcc_define_json_printer_scalar(double, double)
364 : :
365 : 0 : void flatcc_json_printer_enum(flatcc_json_printer_t *ctx, const char *symbol, int len)
366 : : {
367 : 0 : print_symbol(ctx, symbol, len);
368 : 0 : }
369 : :
370 : 36 : void flatcc_json_printer_delimit_enum_flags(flatcc_json_printer_t *ctx, int multiple)
371 : : {
372 : : #if FLATCC_JSON_PRINT_ALWAYS_QUOTE_MULTIPLE_FLAGS
373 [ + + ][ + - ]: 36 : int quote = !ctx->unquote || multiple;
374 : : #else
375 : : int quote = !ctx->unquote;
376 : : #endif
377 : 36 : *ctx->p = '"';
378 : 36 : ctx->p += quote;
379 : 36 : }
380 : :
381 : 26 : void flatcc_json_printer_enum_flag(flatcc_json_printer_t *ctx, int count, const char *symbol, int len)
382 : : {
383 : 26 : *ctx->p = ' ';
384 : 26 : ctx->p += count > 0;
385 : 26 : print_string_part(ctx, symbol, len);
386 : 26 : }
387 : :
388 : : static inline void print_string_object(flatcc_json_printer_t *ctx, const void *p)
389 : : {
390 : : size_t len;
391 : : const char *s;
392 : :
393 : 53 : len = (size_t)__flatbuffers_uoffset_read_from_pe(p);
394 : 53 : s = (const char *)p + uoffset_size;
395 : 53 : print_string(ctx, s, len);
396 : : }
397 : :
398 : : #define __define_print_scalar_struct_field(TN, T) \
399 : : void flatcc_json_printer_ ## TN ## _struct_field(flatcc_json_printer_t *ctx,\
400 : : int index, const void *p, size_t offset, \
401 : : const char *name, int len) \
402 : : { \
403 : : T x = flatbuffers_ ## TN ## _read_from_pe((uint8_t *)p + offset); \
404 : : \
405 : : if (index) { \
406 : : print_char(','); \
407 : : } \
408 : : print_name(ctx, name, len); \
409 : : ctx->p += print_ ## TN (x, ctx->p); \
410 : : }
411 : :
412 : : #define __define_print_enum_struct_field(TN, T) \
413 : : void flatcc_json_printer_ ## TN ## _enum_struct_field( \
414 : : flatcc_json_printer_t *ctx, \
415 : : int index, const void *p, size_t offset, \
416 : : const char *name, int len, \
417 : : flatcc_json_printer_ ## TN ##_enum_f *pf) \
418 : : { \
419 : : T x = flatbuffers_ ## TN ## _read_from_pe((uint8_t *)p + offset); \
420 : : \
421 : : if (index) { \
422 : : print_char(','); \
423 : : } \
424 : : print_name(ctx, name, len); \
425 : : if (ctx->noenum) { \
426 : : ctx->p += print_ ## TN (x, ctx->p); \
427 : : } else { \
428 : : pf(ctx, x); \
429 : : } \
430 : : }
431 : :
432 : : #define __define_print_scalar_field(TN, T) \
433 : : void flatcc_json_printer_ ## TN ## _field(flatcc_json_printer_t *ctx, \
434 : : flatcc_json_printer_table_descriptor_t *td, \
435 : : int id, const char *name, int len, T v) \
436 : : { \
437 : : T x; \
438 : : const void *p = get_field_ptr(td, id); \
439 : : \
440 : : if (p) { \
441 : : x = flatbuffers_ ## TN ## _read_from_pe(p); \
442 : : if (x == v && ctx->skip_default) { \
443 : : return; \
444 : : } \
445 : : } else { \
446 : : if (!ctx->force_default) { \
447 : : return; \
448 : : } \
449 : : x = v; \
450 : : } \
451 : : if (td->count++) { \
452 : : print_char(','); \
453 : : } \
454 : : print_name(ctx, name, len); \
455 : : ctx->p += print_ ## TN (x, ctx->p); \
456 : : }
457 : :
458 : : #define __define_print_enum_field(TN, T) \
459 : : void flatcc_json_printer_ ## TN ## _enum_field(flatcc_json_printer_t *ctx, \
460 : : flatcc_json_printer_table_descriptor_t *td, \
461 : : int id, const char *name, int len, T v, \
462 : : flatcc_json_printer_ ## TN ##_enum_f *pf) \
463 : : { \
464 : : T x; \
465 : : const void *p = get_field_ptr(td, id); \
466 : : \
467 : : if (p) { \
468 : : x = flatbuffers_ ## TN ## _read_from_pe(p); \
469 : : if (x == v && ctx->skip_default) { \
470 : : return; \
471 : : } \
472 : : } else { \
473 : : if (!ctx->force_default) { \
474 : : return; \
475 : : } \
476 : : x = v; \
477 : : } \
478 : : if (td->count++) { \
479 : : print_char(','); \
480 : : } \
481 : : print_name(ctx, name, len); \
482 : : if (ctx->noenum) { \
483 : : ctx->p += print_ ## TN (x, ctx->p); \
484 : : } else { \
485 : : pf(ctx, x); \
486 : : } \
487 : : }
488 : :
489 : 52 : static inline void print_table_object(flatcc_json_printer_t *ctx,
490 : : const void *p, int ttl, flatcc_json_printer_table_f pf)
491 : : {
492 : : flatcc_json_printer_table_descriptor_t td;
493 : :
494 [ - + ]: 52 : if (!--ttl) {
495 : : flatcc_json_printer_set_error(ctx, flatcc_json_printer_error_deep_recursion);
496 : 0 : return;
497 : : }
498 : 52 : print_start('{');
499 : 52 : td.count = 0;
500 : 52 : td.ttl = ttl;
501 : 52 : td.table = p;
502 : 52 : td.vtable = (uint8_t *)p - __flatbuffers_soffset_read_from_pe(p);
503 : 52 : td.vsize = __flatbuffers_voffset_read_from_pe(td.vtable);
504 : 52 : pf(ctx, &td);
505 [ + + ]: 52 : print_end('}');
506 : : }
507 : :
508 : 52 : void flatcc_json_printer_string_field(flatcc_json_printer_t *ctx,
509 : : flatcc_json_printer_table_descriptor_t *td,
510 : : int id, const char *name, int len)
511 : : {
512 : : const void *p = get_field_ptr(td, id);
513 : :
514 [ + + ]: 52 : if (p) {
515 [ + + ]: 51 : if (td->count++) {
516 : 8 : print_char(',');
517 : : }
518 : 51 : print_name(ctx, name, len);
519 : : print_string_object(ctx, read_uoffset_ptr(p));
520 : : }
521 : 52 : }
522 : :
523 : : #define __define_print_scalar_vector_field(TN, T) \
524 : : void flatcc_json_printer_ ## TN ## _vector_field(flatcc_json_printer_t *ctx,\
525 : : flatcc_json_printer_table_descriptor_t *td, \
526 : : int id, const char *name, int len) \
527 : : { \
528 : : const void *p = get_field_ptr(td, id); \
529 : : uoffset_t count; \
530 : : \
531 : : if (p) { \
532 : : if (td->count++) { \
533 : : print_char(','); \
534 : : } \
535 : : p = read_uoffset_ptr(p); \
536 : : count = __flatbuffers_uoffset_read_from_pe(p); \
537 : : p = (void *)((size_t)p + uoffset_size); \
538 : : print_name(ctx, name, len); \
539 : : print_start('['); \
540 : : if (count) { \
541 : : print_nl(); \
542 : : ctx->p += print_ ## TN ( \
543 : : flatbuffers_ ## TN ## _read_from_pe(p), \
544 : : ctx->p); \
545 : : p = (void *)((size_t)p + sizeof(T)); \
546 : : --count; \
547 : : } \
548 : : while (count--) { \
549 : : print_char(','); \
550 : : print_nl(); \
551 : : ctx->p += print_ ## TN ( \
552 : : flatbuffers_ ## TN ## _read_from_pe(p), \
553 : : ctx->p); \
554 : : p = (void *)((size_t)p + sizeof(T)); \
555 : : } \
556 : : print_end(']'); \
557 : : } \
558 : : }
559 : :
560 : : #define __define_print_enum_vector_field(TN, T) \
561 : : void flatcc_json_printer_ ## TN ## _enum_vector_field(flatcc_json_printer_t *ctx,\
562 : : flatcc_json_printer_table_descriptor_t *td, \
563 : : int id, const char *name, int len, \
564 : : flatcc_json_printer_ ## TN ##_enum_f *pf) \
565 : : { \
566 : : const void *p; \
567 : : uoffset_t count; \
568 : : \
569 : : if (ctx->noenum) { \
570 : : flatcc_json_printer_ ## TN ## _vector_field(ctx, td, id, name, len);\
571 : : return; \
572 : : } \
573 : : p = get_field_ptr(td, id); \
574 : : if (p) { \
575 : : if (td->count++) { \
576 : : print_char(','); \
577 : : } \
578 : : p = read_uoffset_ptr(p); \
579 : : count = __flatbuffers_uoffset_read_from_pe(p); \
580 : : p = (void *)((size_t)p + uoffset_size); \
581 : : print_name(ctx, name, len); \
582 : : print_start('['); \
583 : : if (count) { \
584 : : print_nl(); \
585 : : pf(ctx, flatbuffers_ ## TN ## _read_from_pe(p)); \
586 : : p = (void *)((size_t)p + sizeof(T)); \
587 : : --count; \
588 : : } \
589 : : while (count--) { \
590 : : print_char(','); \
591 : : print_nl(); \
592 : : pf(ctx, flatbuffers_ ## TN ## _read_from_pe(p)); \
593 : : p = (void *)((size_t)p + sizeof(T)); \
594 : : } \
595 : : print_end(']'); \
596 : : } \
597 : : }
598 : :
599 [ # # ][ # # ]: 0 : __define_print_scalar_field(uint8, uint8_t)
[ # # ][ # # ]
[ # # ]
600 [ - + ][ # # ]: 2 : __define_print_scalar_field(uint16, uint16_t)
[ # # ][ - + ]
[ # # ]
601 [ + + ][ - + ]: 202 : __define_print_scalar_field(uint32, uint32_t)
[ # # ][ + + ]
[ + - ]
602 [ + + ][ - + ]: 200 : __define_print_scalar_field(uint64, uint64_t)
[ # # ][ + + ]
[ + - ]
603 [ # # ][ # # ]: 0 : __define_print_scalar_field(int8, int8_t)
[ # # ][ # # ]
[ # # ]
604 [ + + ][ - + ]: 209 : __define_print_scalar_field(int16, int16_t)
[ # # ][ + + ]
[ + + ]
605 [ + + ][ - + ]: 204 : __define_print_scalar_field(int32, int32_t)
[ # # ][ + + ]
[ + - ]
606 [ + + ][ - + ]: 206 : __define_print_scalar_field(int64, int64_t)
[ # # ][ + + ]
[ + - ]
607 [ - + ][ # # ]: 100 : __define_print_scalar_field(bool, flatbuffers_bool_t)
[ # # ][ + + ]
[ + - ]
608 [ # # ][ # # ]: 0 : __define_print_scalar_field(float, float)
[ # # ][ # # ]
[ # # ]
609 [ # # ][ # # ]: 0 : __define_print_scalar_field(double, double)
[ # # ][ # # ]
[ # # ]
610 : :
611 [ # # ][ # # ]: 0 : __define_print_enum_field(uint8, uint8_t)
[ # # ][ # # ]
[ # # ][ # # ]
612 [ # # ][ # # ]: 0 : __define_print_enum_field(uint16, uint16_t)
[ # # ][ # # ]
[ # # ][ # # ]
613 [ # # ][ # # ]: 0 : __define_print_enum_field(uint32, uint32_t)
[ # # ][ # # ]
[ # # ][ # # ]
614 [ # # ][ # # ]: 0 : __define_print_enum_field(uint64, uint64_t)
[ # # ][ # # ]
[ # # ][ # # ]
615 [ + + ][ + + ]: 101 : __define_print_enum_field(int8, int8_t)
[ + + ][ + + ]
[ + - ][ + + ]
616 [ # # ][ # # ]: 0 : __define_print_enum_field(int16, int16_t)
[ # # ][ # # ]
[ # # ][ # # ]
617 [ # # ][ # # ]: 0 : __define_print_enum_field(int32, int32_t)
[ # # ][ # # ]
[ # # ][ # # ]
618 [ # # ][ # # ]: 0 : __define_print_enum_field(int64, int64_t)
[ # # ][ # # ]
[ # # ][ # # ]
619 [ # # ][ # # ]: 0 : __define_print_enum_field(bool, flatbuffers_bool_t)
[ # # ][ # # ]
[ # # ][ # # ]
620 : :
621 [ # # ]: 0 : __define_print_scalar_struct_field(uint8, uint8_t)
622 [ # # ]: 0 : __define_print_scalar_struct_field(uint16, uint16_t)
623 [ # # ]: 0 : __define_print_scalar_struct_field(uint32, uint32_t)
624 [ # # ]: 0 : __define_print_scalar_struct_field(uint64, uint64_t)
625 [ + - ]: 6 : __define_print_scalar_struct_field(int8, int8_t)
626 [ - + ]: 6 : __define_print_scalar_struct_field(int16, int16_t)
627 [ # # ]: 0 : __define_print_scalar_struct_field(int32, int32_t)
628 [ # # ]: 0 : __define_print_scalar_struct_field(int64, int64_t)
629 [ # # ]: 0 : __define_print_scalar_struct_field(bool, flatbuffers_bool_t)
630 [ + + ]: 6 : __define_print_scalar_struct_field(float, float)
631 [ + - ]: 2 : __define_print_scalar_struct_field(double, double)
632 : :
633 [ # # ][ # # ]: 0 : __define_print_enum_struct_field(uint8, uint8_t)
634 [ # # ][ # # ]: 0 : __define_print_enum_struct_field(uint16, uint16_t)
635 [ # # ][ # # ]: 0 : __define_print_enum_struct_field(uint32, uint32_t)
636 [ # # ][ # # ]: 0 : __define_print_enum_struct_field(uint64, uint64_t)
637 [ + - ][ - + ]: 2 : __define_print_enum_struct_field(int8, int8_t)
638 [ # # ][ # # ]: 0 : __define_print_enum_struct_field(int16, int16_t)
639 [ # # ][ # # ]: 0 : __define_print_enum_struct_field(int32, int32_t)
640 [ # # ][ # # ]: 0 : __define_print_enum_struct_field(int64, int64_t)
641 [ # # ][ # # ]: 0 : __define_print_enum_struct_field(bool, flatbuffers_bool_t)
642 : :
643 [ + + ][ + - ]: 104 : __define_print_scalar_vector_field(uint8, uint8_t)
[ + - ][ + - ]
[ + - ][ + + ]
[ + - ]
644 [ # # ][ # # ]: 0 : __define_print_scalar_vector_field(uint16, uint16_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
645 [ # # ][ # # ]: 0 : __define_print_scalar_vector_field(uint32, uint32_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
646 [ # # ][ # # ]: 0 : __define_print_scalar_vector_field(uint64, uint64_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
647 [ # # ][ # # ]: 0 : __define_print_scalar_vector_field(int8, int8_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
648 [ # # ][ # # ]: 0 : __define_print_scalar_vector_field(int16, int16_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
649 [ # # ][ # # ]: 0 : __define_print_scalar_vector_field(int32, int32_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
650 [ # # ][ # # ]: 0 : __define_print_scalar_vector_field(int64, int64_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
651 [ - + ][ # # ]: 100 : __define_print_scalar_vector_field(bool, flatbuffers_bool_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
652 [ # # ][ # # ]: 0 : __define_print_scalar_vector_field(float, float)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
653 [ # # ][ # # ]: 0 : __define_print_scalar_vector_field(double, double)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ]
654 : :
655 [ # # ][ # # ]: 0 : __define_print_enum_vector_field(uint8, uint8_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
656 [ # # ][ # # ]: 0 : __define_print_enum_vector_field(uint16, uint16_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
657 [ # # ][ # # ]: 0 : __define_print_enum_vector_field(uint32, uint32_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
658 [ # # ][ # # ]: 0 : __define_print_enum_vector_field(uint64, uint64_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
659 [ # # ][ # # ]: 0 : __define_print_enum_vector_field(int8, int8_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
660 [ # # ][ # # ]: 0 : __define_print_enum_vector_field(int16, int16_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
661 [ # # ][ # # ]: 0 : __define_print_enum_vector_field(int32, int32_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
662 [ # # ][ # # ]: 0 : __define_print_enum_vector_field(int64, int64_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
663 [ # # ][ # # ]: 0 : __define_print_enum_vector_field(bool, flatbuffers_bool_t)
[ # # ][ # # ]
[ # # ][ # # ]
[ # # ][ # # ]
664 : :
665 : 50 : void flatcc_json_printer_struct_vector_field(flatcc_json_printer_t *ctx,
666 : : flatcc_json_printer_table_descriptor_t *td,
667 : : int id, const char *name, int len,
668 : : size_t size,
669 : : flatcc_json_printer_struct_f pf)
670 : : {
671 : : const uint8_t *p = get_field_ptr(td, id);
672 : : uoffset_t count;
673 : :
674 [ + + ]: 50 : if (p) {
675 [ + - ]: 1 : if (td->count++) {
676 : 1 : print_char(',');
677 : : }
678 : : p = read_uoffset_ptr(p);
679 : : count = __flatbuffers_uoffset_read_from_pe(p);
680 : 1 : p += uoffset_size;
681 : 1 : print_name(ctx, name, len);
682 : 1 : print_start('[');
683 [ + - ]: 1 : if (count) {
684 [ + - ]: 1 : print_nl();
685 : 1 : print_start('{');
686 : 1 : pf(ctx, p);
687 [ + - ]: 1 : print_end('}');
688 : 1 : --count;
689 : : }
690 [ + + ]: 2 : while (count--) {
691 : 1 : p += size;
692 : 1 : print_char(',');
693 [ + - ]: 1 : print_nl();
694 : 1 : print_start('{');
695 : 1 : pf(ctx, p);
696 [ + - ]: 1 : print_end('}');
697 : : }
698 [ + - ]: 1 : print_end(']');
699 : : }
700 : 50 : }
701 : :
702 : 50 : void flatcc_json_printer_string_vector_field(flatcc_json_printer_t *ctx,
703 : : flatcc_json_printer_table_descriptor_t *td,
704 : : int id, const char *name, int len)
705 : : {
706 : : const uoffset_t *p = get_field_ptr(td, id);
707 : : uoffset_t count;
708 : :
709 [ + + ]: 50 : if (p) {
710 [ + - ]: 1 : if (td->count++) {
711 : 1 : print_char(',');
712 : : }
713 : : p = read_uoffset_ptr(p);
714 : : count = __flatbuffers_uoffset_read_from_pe(p);
715 : 1 : ++p;
716 : 1 : print_name(ctx, name, len);
717 : 1 : print_start('[');
718 [ + - ]: 1 : if (count) {
719 [ + - ]: 1 : print_nl();
720 : : print_string_object(ctx, read_uoffset_ptr(p));
721 : 1 : --count;
722 : : }
723 [ + + ]: 2 : while (count--) {
724 : 1 : ++p;
725 : 1 : print_char(',');
726 [ + - ]: 1 : print_nl();
727 : : print_string_object(ctx, read_uoffset_ptr(p));
728 : : }
729 [ + - ]: 1 : print_end(']');
730 : : }
731 : 50 : }
732 : :
733 : 50 : void flatcc_json_printer_table_vector_field(flatcc_json_printer_t *ctx,
734 : : flatcc_json_printer_table_descriptor_t *td,
735 : : int id, const char *name, int len,
736 : : flatcc_json_printer_table_f pf)
737 : : {
738 : : const uoffset_t *p = get_field_ptr(td, id);
739 : : uoffset_t count;
740 : :
741 [ + + ]: 50 : if (p) {
742 [ + - ]: 1 : if (td->count++) {
743 : 1 : print_char(',');
744 : : }
745 : : p = read_uoffset_ptr(p);
746 : : count = __flatbuffers_uoffset_read_from_pe(p);
747 : 1 : ++p;
748 : 1 : print_name(ctx, name, len);
749 : 1 : print_start('[');
750 [ - + ]: 1 : if (count) {
751 : 0 : print_table_object(ctx, read_uoffset_ptr(p), td->ttl, pf);
752 : 1 : --count;
753 : : }
754 [ - + ]: 1 : while (count--) {
755 : 0 : ++p;
756 : 0 : print_char(',');
757 : 0 : print_table_object(ctx, read_uoffset_ptr(p), td->ttl, pf);
758 : : }
759 [ - + ]: 1 : print_end(']');
760 : : }
761 : 50 : }
762 : :
763 : 155 : void flatcc_json_printer_table_field(flatcc_json_printer_t *ctx,
764 : : flatcc_json_printer_table_descriptor_t *td,
765 : : int id, const char *name, int len,
766 : : flatcc_json_printer_table_f pf)
767 : : {
768 : : const void *p = get_field_ptr(td, id);
769 : :
770 [ + + ]: 155 : if (p) {
771 [ + - ]: 7 : if (td->count++) {
772 : 7 : print_char(',');
773 : : }
774 : 7 : print_name(ctx, name, len);
775 : 7 : print_table_object(ctx, read_uoffset_ptr(p), td->ttl, pf);
776 : : }
777 : 155 : }
778 : :
779 : 1 : void flatcc_json_printer_embedded_struct_field(flatcc_json_printer_t *ctx,
780 : : int index, const void *p, size_t offset,
781 : : const char *name, int len,
782 : : flatcc_json_printer_struct_f pf)
783 : : {
784 [ + - ]: 1 : if (index) {
785 : 1 : print_char(',');
786 : : }
787 : 1 : print_name(ctx, name, len);
788 : 1 : print_start('{');
789 : 1 : pf(ctx, (uint8_t *)p + offset);
790 [ + - ]: 1 : print_end('}');
791 : 1 : }
792 : :
793 : 50 : void flatcc_json_printer_struct_field(flatcc_json_printer_t *ctx,
794 : : flatcc_json_printer_table_descriptor_t *td,
795 : : int id, const char *name, int len,
796 : : flatcc_json_printer_struct_f *pf)
797 : : {
798 : : const void *p = get_field_ptr(td, id);
799 : :
800 [ + + ]: 50 : if (p) {
801 [ - + ]: 1 : if (td->count++) {
802 : 0 : print_char(',');
803 : : }
804 : 1 : print_name(ctx, name, len);
805 : 1 : print_start('{');
806 : 1 : pf(ctx, p);
807 [ + - ]: 1 : print_end('}');
808 : : }
809 : 50 : }
810 : :
811 : : /*
812 : : * Make sure the buffer identifier is valid before assuming the rest of
813 : : * the buffer is sane.
814 : : */
815 : 45 : static int accept_header(flatcc_json_printer_t * ctx,
816 : : const void *buf, size_t bufsiz, const char *fid)
817 : : {
818 : 45 : flatbuffers_thash_t id, id2 = 0;
819 : :
820 [ - + ]: 45 : if (buf == 0 || bufsiz < offset_size + FLATBUFFERS_IDENTIFIER_SIZE) {
821 : : RAISE_ERROR(bad_input);
822 : : assert(0 && "buffer header too small");
823 : : return 0;
824 : : }
825 [ + + ]: 45 : if (fid != 0) {
826 : 43 : strncpy((char *)&id2, fid, FLATBUFFERS_IDENTIFIER_SIZE);
827 : 43 : id2 = __flatbuffers_thash_cast_from_le(id2);
828 : : id = __flatbuffers_thash_read_from_pe((uint8_t *)buf + offset_size);
829 [ + - ][ - + ]: 43 : if (!(id2 == 0 || id == id2)) {
830 : : RAISE_ERROR(bad_input);
831 : : assert(0 && "identifier mismatch");
832 : : return 0;
833 : : }
834 : : }
835 : : return 1;
836 : : }
837 : :
838 : 0 : int flatcc_json_printer_struct_as_root(flatcc_json_printer_t *ctx,
839 : : const void *buf, size_t bufsiz, const char *fid,
840 : : flatcc_json_printer_struct_f *pf)
841 : : {
842 [ # # ]: 0 : if (!accept_header(ctx, buf, bufsiz, fid)) {
843 : : return -1;
844 : : }
845 : 0 : print_start('{');
846 : 0 : pf(ctx, read_uoffset_ptr(buf));
847 [ # # ]: 0 : print_end('}');
848 [ # # ][ # # ]: 0 : print_last_nl();
849 [ # # ]: 0 : return flatcc_json_printer_get_error(ctx) ? -1 : (int)ctx->total;
850 : : }
851 : :
852 : 43 : int flatcc_json_printer_table_as_root(flatcc_json_printer_t *ctx,
853 : : const void *buf, size_t bufsiz, const char *fid, flatcc_json_printer_table_f *pf)
854 : : {
855 [ + - ]: 43 : if (!accept_header(ctx, buf, bufsiz, fid)) {
856 : : return -1;
857 : : }
858 : 43 : print_table_object(ctx, read_uoffset_ptr(buf), FLATCC_JSON_PRINT_MAX_LEVELS, pf);
859 [ + + ][ + - ]: 43 : print_last_nl();
860 [ + - ]: 43 : return flatcc_json_printer_get_error(ctx) ? -1 : (int)ctx->total;
861 : : }
862 : :
863 : 0 : void flatcc_json_printer_struct_as_nested_root(flatcc_json_printer_t *ctx,
864 : : flatcc_json_printer_table_descriptor_t *td,
865 : : int id, const char *name, int len,
866 : : const char *fid,
867 : : flatcc_json_printer_struct_f *pf)
868 : : {
869 : : const uoffset_t *buf;
870 : : uoffset_t bufsiz;
871 : :
872 [ # # ]: 0 : if (0 == (buf = get_field_ptr(td, id))) {
873 : : return;
874 : : }
875 : 0 : buf = (const uoffset_t *)((size_t)buf + __flatbuffers_uoffset_read_from_pe(buf));
876 : : bufsiz = __flatbuffers_uoffset_read_from_pe(buf);
877 [ # # ]: 0 : if (!accept_header(ctx, buf, bufsiz, fid)) {
878 : : return;
879 : : }
880 [ # # ]: 0 : if (td->count++) {
881 : 0 : print_char(',');
882 : : }
883 : 0 : print_name(ctx, name, len);
884 : 0 : print_start('{');
885 : 0 : pf(ctx, read_uoffset_ptr(buf));
886 [ # # ]: 0 : print_end('}');
887 : : }
888 : :
889 : 50 : void flatcc_json_printer_table_as_nested_root(flatcc_json_printer_t *ctx,
890 : : flatcc_json_printer_table_descriptor_t *td,
891 : : int id, const char *name, int len,
892 : : const char *fid,
893 : : flatcc_json_printer_table_f pf)
894 : : {
895 : : const uoffset_t *buf;
896 : : uoffset_t bufsiz;
897 : :
898 [ + + ]: 50 : if (0 == (buf = get_field_ptr(td, id))) {
899 : : return;
900 : : }
901 : 2 : buf = (const uoffset_t *)((size_t)buf + __flatbuffers_uoffset_read_from_pe(buf));
902 : : bufsiz = __flatbuffers_uoffset_read_from_pe(buf);
903 : 2 : ++buf;
904 [ + - ]: 2 : if (!accept_header(ctx, buf, bufsiz, fid)) {
905 : : return;
906 : : }
907 [ + - ]: 2 : if (td->count++) {
908 : 2 : print_char(',');
909 : : }
910 : 2 : print_name(ctx, name, len);
911 : 2 : print_table_object(ctx, read_uoffset_ptr(buf), td->ttl, pf);
912 : : }
913 : :
914 : 50 : int flatcc_json_printer_read_union_type(
915 : : flatcc_json_printer_table_descriptor_t *td,
916 : : int id)
917 : : {
918 : : const void *p = get_field_ptr(td, id - 1);
919 : :
920 [ + + ]: 50 : int x = p ? __flatbuffers_utype_read_from_pe(p) : 0;
921 : 50 : return x;
922 : : }
923 : :
924 : 5 : void flatcc_json_printer_union_type(flatcc_json_printer_t *ctx,
925 : : flatcc_json_printer_table_descriptor_t *td,
926 : : const char *name, int len, int type,
927 : : const char *type_name, int type_len)
928 : : {
929 [ + - ]: 5 : if (td->count++) {
930 : 5 : print_char(',');
931 : : }
932 : 5 : print_type(ctx, name, len, type, type_name, type_len);
933 : 5 : }
934 : :
935 : 1 : static void __flatcc_json_printer_flush(flatcc_json_printer_t *ctx, int all)
936 : : {
937 [ - + ][ # # ]: 1 : if (!all && ctx->p >= ctx->pflush) {
938 : 0 : size_t spill = ctx->p - ctx->pflush;
939 : :
940 : 0 : fwrite(ctx->buf, ctx->flush_size, 1, ctx->fp);
941 : 0 : memcpy(ctx->buf, ctx->buf + ctx->flush_size, spill);
942 : 0 : ctx->p = ctx->buf + spill;
943 : 0 : ctx->total += ctx->flush_size;
944 : : } else {
945 : 1 : size_t len = ctx->p - ctx->buf;
946 : :
947 : 1 : fwrite(ctx->buf, len, 1, ctx->fp);
948 : 1 : ctx->p = ctx->buf;
949 : 1 : ctx->total += len;
950 : : }
951 : 1 : }
952 : :
953 : 1 : int flatcc_json_printer_init(flatcc_json_printer_t *ctx, void *fp)
954 : : {
955 : 1 : memset(ctx, 0, sizeof(*ctx));
956 [ - + ]: 1 : ctx->fp = fp ? fp : stdout;
957 : 1 : ctx->flush = __flatcc_json_printer_flush;
958 [ + - ]: 1 : if (!(ctx->buf = malloc(FLATCC_JSON_PRINT_BUFFER_SIZE))) {
959 : : return -1;
960 : : }
961 : 1 : ctx->own_buffer = 1;
962 : 1 : ctx->size = FLATCC_JSON_PRINT_BUFFER_SIZE;
963 : 1 : ctx->flush_size = FLATCC_JSON_PRINT_FLUSH_SIZE;
964 : 1 : ctx->p = ctx->buf;
965 : 1 : ctx->pflush = ctx->buf + ctx->flush_size;
966 : : /*
967 : : * Make sure we have space for primitive operations such as printing numbers
968 : : * without having to flush.
969 : : */
970 : : assert(ctx->flush_size + FLATCC_JSON_PRINT_RESERVE <= ctx->size);
971 : 1 : return 0;
972 : : }
973 : :
974 : 0 : static void __flatcc_json_printer_flush_buffer(flatcc_json_printer_t *ctx, int all)
975 : : {
976 : : (void)all;
977 : :
978 : 0 : ctx->total += ctx->p - ctx->buf;
979 : 0 : ctx->p = ctx->buf;
980 : : RAISE_ERROR(overflow);
981 : 0 : }
982 : :
983 : 0 : int flatcc_json_printer_init_buffer(flatcc_json_printer_t *ctx, char *buffer, size_t buffer_size)
984 : : {
985 : : assert(buffer_size >= FLATCC_JSON_PRINT_RESERVE);
986 [ # # ]: 0 : if (buffer_size < FLATCC_JSON_PRINT_RESERVE) {
987 : : return -1;
988 : : }
989 : 0 : memset(ctx, 0, sizeof(*ctx));
990 : 0 : ctx->buf = buffer;
991 : 0 : ctx->size = buffer_size;
992 : 0 : ctx->flush_size = ctx->size - FLATCC_JSON_PRINT_RESERVE;
993 : 0 : ctx->p = ctx->buf;
994 : 0 : ctx->pflush = ctx->buf + ctx->flush_size;
995 : 0 : ctx->flush = __flatcc_json_printer_flush_buffer;
996 : 0 : return 0;
997 : : }
998 : :
999 : 0 : static void __flatcc_json_printer_flush_dynamic_buffer(flatcc_json_printer_t *ctx, int all)
1000 : : {
1001 : 0 : size_t len = ctx->p - ctx->buf;
1002 : 0 : char *p = realloc(ctx->buf, ctx->size * 2);
1003 : :
1004 : : (void)all;
1005 : 0 : ctx->total += len;
1006 [ # # ]: 0 : if (!p) {
1007 : : RAISE_ERROR(overflow);
1008 : 0 : ctx->p = ctx->buf;
1009 : : } else {
1010 : 0 : ctx->size *= 2;
1011 : 0 : ctx->flush_size = ctx->size - FLATCC_JSON_PRINT_RESERVE;
1012 : 0 : ctx->buf = p;
1013 : 0 : ctx->p = p + len;
1014 : 0 : ctx->pflush = p + ctx->flush_size;
1015 : : }
1016 : 0 : }
1017 : :
1018 : 42 : int flatcc_json_printer_init_dynamic_buffer(flatcc_json_printer_t *ctx, size_t buffer_size)
1019 : : {
1020 [ + - ]: 42 : if (buffer_size == 0) {
1021 : : buffer_size = FLATCC_JSON_PRINT_DYN_BUFFER_SIZE;
1022 : : }
1023 [ - + ]: 42 : if (buffer_size < FLATCC_JSON_PRINT_RESERVE) {
1024 : : buffer_size = FLATCC_JSON_PRINT_RESERVE;
1025 : : }
1026 : 42 : memset(ctx, 0, sizeof(*ctx));
1027 : 42 : ctx->buf = malloc(buffer_size);
1028 : 42 : ctx->own_buffer = 1;
1029 : 42 : ctx->size = buffer_size;
1030 : 42 : ctx->flush_size = ctx->size - FLATCC_JSON_PRINT_RESERVE;
1031 : 42 : ctx->p = ctx->buf;
1032 : 42 : ctx->pflush = ctx->buf + ctx->flush_size;
1033 : 42 : ctx->flush = __flatcc_json_printer_flush_dynamic_buffer;
1034 [ - + ]: 42 : if (!ctx->buf) {
1035 : : RAISE_ERROR(overflow);
1036 : : return -1;
1037 : : }
1038 : : return 0;
1039 : : }
1040 : :
1041 : 42 : void *flatcc_json_printer_get_buffer(flatcc_json_printer_t *ctx, size_t *buffer_size)
1042 : : {
1043 [ # # ][ + - ]: 42 : if (buffer_size) {
1044 : 42 : *buffer_size = ctx->p - ctx->buf;
1045 : : }
1046 : 42 : *ctx->p = '\0';
1047 : 42 : return ctx->buf;
1048 : : }
1049 : :
1050 : 0 : void *flatcc_json_printer_finalize_dynamic_buffer(flatcc_json_printer_t *ctx, size_t *buffer_size)
1051 : : {
1052 : : void *buffer;
1053 : :
1054 : : flatcc_json_printer_nl(ctx);
1055 : : flatcc_json_printer_flush(ctx);
1056 : : buffer = flatcc_json_printer_get_buffer(ctx, buffer_size);
1057 : 0 : memset(ctx, 0, sizeof(*ctx));
1058 : 0 : return buffer;
1059 : : }
1060 : :
1061 : 43 : void flatcc_json_printer_clear(flatcc_json_printer_t *ctx)
1062 : : {
1063 [ + - ][ + - ]: 43 : if (ctx->own_buffer && ctx->buf) {
1064 : 43 : free(ctx->buf);
1065 : : }
1066 : 43 : memset(ctx, 0, sizeof(*ctx));
1067 : 43 : }
|