damus

nostr ios client
git clone git://jb55.com/damus
Log | Files | Refs | README | LICENSE

flatcc_json_printer.h (32394B)


      1 #ifndef FLATCC_JSON_PRINTER_H
      2 #define FLATCC_JSON_PRINTER_H
      3 
      4 #ifdef __cplusplus
      5 extern "C" {
      6 #endif
      7 
      8 /*
      9  * Definitions for default implementation, do not assume these are
     10  * always valid.
     11  */
     12 #define FLATCC_JSON_PRINT_FLUSH_SIZE (1024 * 16)
     13 #define FLATCC_JSON_PRINT_RESERVE 64
     14 #define FLATCC_JSON_PRINT_BUFFER_SIZE (FLATCC_JSON_PRINT_FLUSH_SIZE + FLATCC_JSON_PRINT_RESERVE)
     15 
     16 #ifndef FLATCC_JSON_PRINTER_ALLOC
     17 #define FLATCC_JSON_PRINTER_ALLOC(n) FLATCC_ALLOC(n)
     18 #endif
     19 
     20 #ifndef FLATCC_JSON_PRINTER_FREE
     21 #define FLATCC_JSON_PRINTER_FREE(p) FLATCC_FREE(p)
     22 #endif
     23 
     24 #ifndef FLATCC_JSON_PRINTER_REALLOC
     25 #define FLATCC_JSON_PRINTER_REALLOC(p, n) FLATCC_REALLOC(p, n)
     26 #endif
     27 
     28 /* Initial size that grows exponentially. */
     29 #define FLATCC_JSON_PRINT_DYN_BUFFER_SIZE 4096
     30 
     31 
     32 #include <stdlib.h>
     33 #include <string.h>
     34 
     35 #include "flatcc_rtconfig.h"
     36 #include "flatcc_flatbuffers.h"
     37 
     38 /* -DFLATCC_PORTABLE may help if inttypes.h is missing. */
     39 #ifndef PRId64
     40 #include <inttypes.h>
     41 #endif
     42 
     43 #define FLATCC_JSON_PRINT_ERROR_MAP(XX)                                     \
     44     XX(ok,                      "ok")                                       \
     45     /*                                                                      \
     46      * When the flatbuffer is null, has too small a header, or has          \
     47      * mismatching identifier when a match was requested.                   \
     48      */                                                                     \
     49     XX(bad_input,               "bad input")                                \
     50     XX(deep_recursion,          "deep recursion")                           \
     51     /*                                                                      \
     52      * When the output was larger than the available fixed length buffer,     \
     53      * or dynamic allocation could not grow the buffer sufficiently.        \
     54      */                                                                     \
     55     XX(overflow,                "overflow")
     56 
     57 enum flatcc_json_printer_error_no {
     58 #define XX(no, str) flatcc_json_printer_error_##no,
     59     FLATCC_JSON_PRINT_ERROR_MAP(XX)
     60 #undef XX
     61 };
     62 
     63 #define flatcc_json_printer_ok flatcc_json_printer_error_ok
     64 
     65 typedef struct flatcc_json_printer_ctx flatcc_json_printer_t;
     66 
     67 typedef void flatcc_json_printer_flush_f(flatcc_json_printer_t *ctx, int all);
     68 
     69 struct flatcc_json_printer_ctx {
     70     char *buf;
     71     size_t size;
     72     size_t flush_size;
     73     size_t total;
     74     const char *pflush;
     75     char *p;
     76     uint8_t own_buffer;
     77     uint8_t indent;
     78     uint8_t unquote;
     79     uint8_t noenum;
     80     uint8_t skip_default;
     81     uint8_t force_default;
     82     int level;
     83     int error;
     84 
     85     void *fp;
     86     flatcc_json_printer_flush_f *flush;
     87 };
     88 
     89 static inline void flatcc_json_printer_set_error(flatcc_json_printer_t *ctx, int err)
     90 {
     91     if (!ctx->error) {
     92         ctx->error = err;
     93     }
     94 }
     95 
     96 const char *flatcc_json_printer_error_string(int err);
     97 
     98 static inline int flatcc_json_printer_get_error(flatcc_json_printer_t *ctx)
     99 {
    100     return ctx->error;
    101 }
    102 
    103 /*
    104  * Call to reuse context between parses without without
    105  * returning buffer. If a file pointer is being used,
    106  * it will remain open.
    107  *
    108  * Reset does not affect the formatting settings indentation, and
    109  * operational flags, but does zero the indentation level.
    110  */
    111 static inline void flatcc_json_printer_reset(flatcc_json_printer_t *ctx)
    112 {
    113     ctx->p = ctx->buf;
    114     ctx->level = 0;
    115     ctx->total = 0;
    116     ctx->error = 0;
    117 }
    118 
    119 /*
    120  * A custom init function can be implemented with a custom flush
    121  * function can be custom implemented. A few have been provided:
    122  * init with external fixed length buffer, and init with dynamically
    123  * growing buffer.
    124  *
    125  * Because there are a lot of small print functions, it is essentially
    126  * always faster to print to local buffer than moving to io directly
    127  * such as using fprintf or fwrite. The flush callback is used to
    128  * move data when enough has been collected.
    129  *
    130  * `fp` should be of type `FILE *` but we do not enforce it here
    131  * because it allows the header to be independent of <stdio.h>
    132  * when not required. If `fp` is null, it defaults to stdout.
    133  *
    134  * Returns -1 on alloc error (no cleanup needed), or 0 on success.
    135  * Eventually the clear method must be called to return memory.
    136  *
    137  * The file pointer may be stdout or a custom file. The file pointer
    138  * is not affected by reset or clear and should be closed manually.
    139  *
    140  * `set_flags` and related may be called subsequently to modify
    141  * behavior.
    142  */
    143 int flatcc_json_printer_init(flatcc_json_printer_t *ctx, void *fp);
    144 
    145 /*
    146  * Prints to external buffer and sets overflow error if buffer is too
    147  * small. Earlier content is then overwritten. A custom version of this
    148  * function could flush the content to elsewhere before allowing the
    149  * buffer content to be overwritten. The `buffers_size` must be large
    150  * enough to hold `FLATCC_JSON_PRINT_RESERVED_SIZE` which is small but
    151  * large enough value to hold entire numbers and the like.
    152  *
    153  * It is not strictly necessary to call clear because the buffer is
    154  * external, but still good form and case the context type is changed
    155  * later.
    156  *
    157  * Returns -1 on buffer size error (no cleanup needed), or 0 on success.
    158  *
    159  * `set_flags` and related may be called subsequently to modify
    160  * behavior.
    161  */
    162 int flatcc_json_printer_init_buffer(flatcc_json_printer_t *ctx, char *buffer, size_t buffer_size);
    163 
    164 /*
    165  * Returns the current buffer pointer and also the content size in
    166  * `buffer_size` if it is null. The operation is not very useful for
    167  * file oriented printers (created with `init`) and will then only
    168  * return the unflushed buffer content. For fixed length buffers
    169  * (`init_buffer`), only the last content is available if the buffer
    170  * overflowed. Works well with (`init_buffer`) when the dynamic buffer
    171  * is be reused, otherwise `finalize_dynamic_buffer` could be more
    172  * appropriate.
    173  *
    174  * The returned buffer is zero terminated.
    175  *
    176  * The returned pointer is only valid until next operation and should
    177  * not deallocated manually.
    178  */
    179 void *flatcc_json_printer_get_buffer(flatcc_json_printer_t *ctx, size_t *buffer_size);
    180 
    181 /*
    182  * Set to non-zero if names and enum symbols can be unquoted thus
    183  * diverging from standard JSON while remaining compatible with `flatc`
    184  * JSON flavor.
    185  */
    186 static inline void flatcc_json_printer_set_unquoted(flatcc_json_printer_t *ctx, int x)
    187 {
    188     ctx->unquote = !!x;
    189 }
    190 
    191 /*
    192  * Set to non-zero if enums should always be printed as numbers.
    193  * Otherwise enums are printed as a symbol for member values, and as
    194  * numbers for other values.
    195  *
    196  * NOTE: this setting will not affect code generated with enum mapping
    197  * disabled - statically disabling enum mapping is signficantly faster
    198  * for enums, less so for for union types.
    199  */
    200 static inline void flatcc_json_printer_set_noenum(flatcc_json_printer_t *ctx, int x)
    201 {
    202     ctx->noenum = !!x;
    203 }
    204 
    205 /*
    206  * Override priting an existing scalar field if it equals the default value.
    207  * Note that this setting is not mutually exclusive to `set_force_default`.
    208  */
    209 static inline void flatcc_json_printer_set_skip_default(flatcc_json_printer_t *ctx, int x)
    210 {
    211     ctx->skip_default = !!x;
    212 }
    213 
    214 /*
    215  * Override skipping absent scalar fields and print the default value.
    216  * Note that this setting is not mutually exclusive to `set_skip_default`.
    217  */
    218 static inline void flatcc_json_printer_set_force_default(flatcc_json_printer_t *ctx, int x)
    219 {
    220     ctx->force_default = !!x;
    221 }
    222 
    223 
    224 /*
    225  * Set pretty-print indentation in number of spaces. 0 (default) is
    226  * compact with no spaces or linebreaks (default), anything above
    227  * triggers pretty print.
    228  */
    229 static inline void flatcc_json_printer_set_indent(flatcc_json_printer_t *ctx, uint8_t x)
    230 {
    231     ctx->indent = x;
    232 }
    233 
    234 /*
    235  * Override the default compact valid JSON format with a
    236  * pretty printed non-strict version. Enums are translated
    237  * to names, which is also the default.
    238  */
    239 static inline void flatcc_json_printer_set_nonstrict(flatcc_json_printer_t *ctx)
    240 {
    241     flatcc_json_printer_set_indent(ctx, 2);
    242     flatcc_json_printer_set_unquoted(ctx, 1);
    243     flatcc_json_printer_set_noenum(ctx, 0);
    244 }
    245 
    246 typedef uint32_t flatcc_json_printer_flags_t;
    247 static const flatcc_json_printer_flags_t flatcc_json_printer_f_unquote = 1;
    248 static const flatcc_json_printer_flags_t flatcc_json_printer_f_noenum = 2;
    249 static const flatcc_json_printer_flags_t flatcc_json_printer_f_skip_default = 4;
    250 static const flatcc_json_printer_flags_t flatcc_json_printer_f_force_default = 8;
    251 static const flatcc_json_printer_flags_t flatcc_json_printer_f_pretty = 16;
    252 static const flatcc_json_printer_flags_t flatcc_json_printer_f_nonstrict = 32;
    253 
    254 /*
    255  * May be called instead of setting operational modes individually.
    256  * Formatting is strict quoted json witout pretty printing by default.
    257  *
    258  * flags are:
    259  *
    260  *   `unquote`,
    261  *   `noenum`,
    262  *   `skip_default`,
    263  *   `force_default`,
    264  *   `pretty`,
    265  *   `nonstrict`
    266  *
    267  * `pretty` flag sets indentation to 2.
    268  * `nonstrict` implies: `noenum`, `unquote`, `pretty`.
    269  */
    270 static inline void flatcc_json_printer_set_flags(flatcc_json_printer_t *ctx, flatcc_json_printer_flags_t flags)
    271 {
    272     ctx->unquote = !!(flags & flatcc_json_printer_f_unquote);
    273     ctx->noenum = !!(flags & flatcc_json_printer_f_noenum);
    274     ctx->skip_default = !!(flags & flatcc_json_printer_f_skip_default);
    275     ctx->force_default = !!(flags & flatcc_json_printer_f_force_default);
    276     if (flags & flatcc_json_printer_f_pretty) {
    277         flatcc_json_printer_set_indent(ctx, 2);
    278     }
    279     if (flags & flatcc_json_printer_f_nonstrict) {
    280         flatcc_json_printer_set_nonstrict(ctx);
    281     }
    282 }
    283 
    284 
    285 /*
    286  * Detects if the conctext type uses dynamically allocated memory
    287  * using malloc and realloc and frees any such memory.
    288  *
    289  * Not all context types needs to be cleared.
    290  */
    291 void flatcc_json_printer_clear(flatcc_json_printer_t *ctx);
    292 
    293 /*
    294  * Ensures that there ia always buffer capacity for priting the next
    295  * primitive with delimiters.
    296  *
    297  * Only flushes complete flush units and is inexpensive to call.
    298  * The content buffer has an extra reserve which ensures basic
    299  * data types and delimiters can always be printed after a partial
    300  * flush. At the end, a `flush` is required to flush the
    301  * remaining incomplete buffer data.
    302  *
    303  * Numbers do not call partial flush but will always fit into the reserve
    304  * capacity after a partial flush, also surrounded by delimiters.
    305  *
    306  * Variable length operations generally submit a partial flush so it is
    307  * safe to print a number after a name without flushing, but vectors of
    308  * numbers must (and do) issue a partial flush between elements. This is
    309  * handled automatically but must be considered if using the primitives
    310  * for special purposes. Because repeated partial flushes are very cheap
    311  * this is only a concern for high performance applications.
    312  *
    313  * When identiation is enabled, partial flush is also automatically
    314  * issued .
    315  */
    316 static inline void flatcc_json_printer_flush_partial(flatcc_json_printer_t *ctx)
    317 {
    318     if (ctx->p >= ctx->pflush) {
    319         ctx->flush(ctx, 0);
    320     }
    321 }
    322 
    323 /* Returns the total printed size but flushed and in buffer. */
    324 static inline size_t flatcc_json_printer_total(flatcc_json_printer_t *ctx)
    325 {
    326     return ctx->total + (size_t)(ctx->p - ctx->buf);
    327 }
    328 
    329 /*
    330  * Flush the remaining data not flushed by partial flush. It is valid to
    331  * call at any point if it is acceptable to have unaligned flush units,
    332  * but this is not desireable if, for example, compression or encryption
    333  * is added to the flush pipeline.
    334  *
    335  * Not called automatically at the end of printing a flatbuffer object
    336  * in case more data needs to be appended without submitting incomplete
    337  * flush units prematurely - for example adding a newline at the end.
    338  *
    339  * The flush behavior depeends on the underlying `ctx` object, for
    340  * example dynamic buffers have no distinction between partial and full
    341  * flushes - here it is merely ensured that the buffer always has a
    342  * reserve capacity left.
    343  *
    344  * Returns the total printed size.
    345  */
    346 static inline size_t flatcc_json_printer_flush(flatcc_json_printer_t *ctx)
    347 {
    348     ctx->flush(ctx, 1);
    349     return flatcc_json_printer_total(ctx);
    350 }
    351 
    352 /*
    353  * Helper functions to print anything into the json buffer.
    354  * Strings are escaped.
    355  *
    356  * When pretty printing (indent > 0), level 0 has special significance -
    357  * so if wrapping printed json in a manually printed container json
    358  * object, these functions can help manage this.
    359  */
    360 
    361 /* Escaped and quoted string. */
    362 void flatcc_json_printer_string(flatcc_json_printer_t *ctx, const char *s, size_t n);
    363 /* Unescaped and unquoted string. */
    364 void flatcc_json_printer_write(flatcc_json_printer_t *ctx, const char *s, size_t n);
    365 /* Print a newline and issues a partial flush. */
    366 void flatcc_json_printer_nl(flatcc_json_printer_t *ctx);
    367 /* Like numbers, a partial flush is not issued. */
    368 void flatcc_json_printer_char(flatcc_json_printer_t *ctx, char c);
    369 /* Indents and issues a partial flush. */
    370 void flatcc_json_printer_indent(flatcc_json_printer_t *ctx);
    371 /* Adjust identation level, usually +/-1. */
    372 void flatcc_json_printer_add_level(flatcc_json_printer_t *ctx, int n);
    373 /* Returns current identation level (0 is top level). */
    374 int flatcc_json_printer_get_level(flatcc_json_printer_t *ctx);
    375 
    376 /*
    377  * If called explicitly be aware that repeated calls to numeric
    378  * printers may cause buffer overflow without flush in-between.
    379  */
    380 void flatcc_json_printer_uint8(flatcc_json_printer_t *ctx, uint8_t v);
    381 void flatcc_json_printer_uint16(flatcc_json_printer_t *ctx, uint16_t v);
    382 void flatcc_json_printer_uint32(flatcc_json_printer_t *ctx, uint32_t v);
    383 void flatcc_json_printer_uint64(flatcc_json_printer_t *ctx, uint64_t v);
    384 void flatcc_json_printer_int8(flatcc_json_printer_t *ctx, int8_t v);
    385 void flatcc_json_printer_int16(flatcc_json_printer_t *ctx, int16_t v);
    386 void flatcc_json_printer_int32(flatcc_json_printer_t *ctx, int32_t v);
    387 void flatcc_json_printer_int64(flatcc_json_printer_t *ctx, int64_t v);
    388 void flatcc_json_printer_bool(flatcc_json_printer_t *ctx, int v);
    389 void flatcc_json_printer_float(flatcc_json_printer_t *ctx, float v);
    390 void flatcc_json_printer_double(flatcc_json_printer_t *ctx, double v);
    391 
    392 void flatcc_json_printer_enum(flatcc_json_printer_t *ctx,
    393         const char *symbol, size_t len);
    394 
    395 /*
    396  * Convenience function to add a trailing newline, flush the buffer,
    397  * test for error and reset the context for reuse.
    398  *
    399  * Returns total size printed or < 0 on error.
    400  *
    401  * This function makes most sense for file oriented output.
    402  * See also `finalize_dynamic_buffer`.
    403  */
    404 static inline int flatcc_json_printer_finalize(flatcc_json_printer_t *ctx)
    405 {
    406     int ret;
    407     flatcc_json_printer_nl(ctx);
    408     ret = (int)flatcc_json_printer_flush(ctx);
    409     if (ctx->error) {
    410         ret = -1;
    411     }
    412     flatcc_json_printer_reset(ctx);
    413     return ret;
    414 }
    415 
    416 /*
    417  * Allocates a small buffer and grows it dynamically.
    418  * Buffer survives past reset. To reduce size between uses, call clear
    419  * followed by init call. To reuse buffer just call reset between uses.
    420  * If `buffer_size` is 0 a sensible default is being used. The size is
    421  * automatically rounded up to reserved size if too small.
    422  *
    423  * Returns -1 on alloc error (no cleanup needed), or 0 on success.
    424  * Eventually the clear method must be called to return memory.
    425  *
    426  * `set_flags` and related may be called subsequently to modify
    427  * behavior.
    428  */
    429 int flatcc_json_printer_init_dynamic_buffer(flatcc_json_printer_t *ctx, size_t buffer_size);
    430 
    431 /*
    432  * Similar to calling `finalize` but returns the buffer and does NOT
    433  * reset, but rather clears printer object and the returned buffer must
    434  * be deallocated with `free`.
    435  *
    436  * The returned buffer is zero terminated.
    437  *
    438  * NOTE: it is entirely optional to use this method. For repeated used
    439  * of dynamic buffers, `newline` (or not) followed by `get_buffer`
    440  * and `reset` will be an alternative.
    441  *
    442  * Stores the printed buffer size in `buffer_size` if it is not null.
    443  *
    444  * See also `get_dynamic_buffer`.
    445  */
    446 void *flatcc_json_printer_finalize_dynamic_buffer(flatcc_json_printer_t *ctx, size_t *buffer_size);
    447 
    448 
    449 /*************************************************************
    450  * The following is normally only used by generated code.
    451  *************************************************************/
    452 
    453 typedef struct flatcc_json_printer_table_descriptor flatcc_json_printer_table_descriptor_t;
    454 
    455 struct flatcc_json_printer_table_descriptor {
    456     const void *table;
    457     const void *vtable;
    458     int vsize;
    459     int ttl;
    460     int count;
    461 };
    462 
    463 typedef struct flatcc_json_printer_union_descriptor flatcc_json_printer_union_descriptor_t;
    464 
    465 struct flatcc_json_printer_union_descriptor {
    466     const void *member;
    467     int ttl;
    468     uint8_t type;
    469 };
    470 
    471 typedef void flatcc_json_printer_table_f(flatcc_json_printer_t *ctx,
    472         flatcc_json_printer_table_descriptor_t *td);
    473 
    474 typedef void flatcc_json_printer_struct_f(flatcc_json_printer_t *ctx,
    475         const void *p);
    476 
    477 typedef void flatcc_json_printer_union_f(flatcc_json_printer_t *ctx,
    478         flatcc_json_printer_union_descriptor_t *ud);
    479 
    480 /* Generated value to name map callbacks. */
    481 typedef void flatcc_json_printer_union_type_f(flatcc_json_printer_t *ctx, flatbuffers_utype_t type);
    482 typedef void flatcc_json_printer_uint8_enum_f(flatcc_json_printer_t *ctx, uint8_t v);
    483 typedef void flatcc_json_printer_uint16_enum_f(flatcc_json_printer_t *ctx, uint16_t v);
    484 typedef void flatcc_json_printer_uint32_enum_f(flatcc_json_printer_t *ctx, uint32_t v);
    485 typedef void flatcc_json_printer_uint64_enum_f(flatcc_json_printer_t *ctx, uint64_t v);
    486 typedef void flatcc_json_printer_int8_enum_f(flatcc_json_printer_t *ctx, int8_t v);
    487 typedef void flatcc_json_printer_int16_enum_f(flatcc_json_printer_t *ctx, int16_t v);
    488 typedef void flatcc_json_printer_int32_enum_f(flatcc_json_printer_t *ctx, int32_t v);
    489 typedef void flatcc_json_printer_int64_enum_f(flatcc_json_printer_t *ctx, int64_t v);
    490 typedef void flatcc_json_printer_bool_enum_f(flatcc_json_printer_t *ctx, flatbuffers_bool_t v);
    491 
    492 #define __define_print_scalar_field_proto(TN, T)                            \
    493 void flatcc_json_printer_ ## TN ## _field(flatcc_json_printer_t *ctx,       \
    494         flatcc_json_printer_table_descriptor_t *td,                         \
    495         int id, const char *name, size_t len, T v);
    496 
    497 #define __define_print_scalar_optional_field_proto(TN, T)                   \
    498 void flatcc_json_printer_ ## TN ## _optional_field(                         \
    499         flatcc_json_printer_t *ctx,                                         \
    500         flatcc_json_printer_table_descriptor_t *td,                         \
    501         int id, const char *name, size_t len);
    502 
    503 #define __define_print_scalar_struct_field_proto(TN, T)                     \
    504 void flatcc_json_printer_ ## TN ## _struct_field(flatcc_json_printer_t *ctx,\
    505         int index, const void *p, size_t offset,                            \
    506         const char *name, size_t len);
    507 
    508 #define __define_print_scalar_array_struct_field_proto(TN, T)               \
    509 void flatcc_json_printer_ ## TN ## _array_struct_field(                     \
    510         flatcc_json_printer_t *ctx,                                         \
    511         int index, const void *p, size_t offset,                            \
    512         const char *name, size_t len, size_t count);
    513 
    514 #define __define_print_enum_array_struct_field_proto(TN, T)                 \
    515 void flatcc_json_printer_ ## TN ## _enum_array_struct_field(                \
    516         flatcc_json_printer_t *ctx,                                         \
    517         int index, const void *p, size_t offset,                            \
    518         const char *name, size_t len, size_t count,                         \
    519         flatcc_json_printer_ ## TN ##_enum_f *pf);
    520 
    521 #define __define_print_enum_struct_field_proto(TN, T)                       \
    522 void flatcc_json_printer_ ## TN ## _enum_struct_field(                      \
    523         flatcc_json_printer_t *ctx,                                         \
    524         int index, const void *p, size_t offset,                            \
    525         const char *name, size_t len,                                       \
    526         flatcc_json_printer_ ## TN ##_enum_f *pf);
    527 
    528 #define __define_print_enum_field_proto(TN, T)                              \
    529 void flatcc_json_printer_ ## TN ## _enum_field(flatcc_json_printer_t *ctx,  \
    530         flatcc_json_printer_table_descriptor_t *td,                         \
    531         int id, const char *name, size_t len, T v,                          \
    532         flatcc_json_printer_ ## TN ##_enum_f *pf);
    533 
    534 #define __define_print_enum_optional_field_proto(TN, T)                     \
    535 void flatcc_json_printer_ ## TN ## _enum_optional_field(                    \
    536         flatcc_json_printer_t *ctx,                                         \
    537         flatcc_json_printer_table_descriptor_t *td,                         \
    538         int id, const char *name, size_t len,                               \
    539         flatcc_json_printer_ ## TN ##_enum_f *pf);
    540 
    541 #define __define_print_scalar_vector_field_proto(TN, T)                     \
    542 void flatcc_json_printer_ ## TN ## _vector_field(flatcc_json_printer_t *ctx,\
    543         flatcc_json_printer_table_descriptor_t *td,                         \
    544         int id, const char *name, size_t len);
    545 
    546 #define __define_print_enum_vector_field_proto(TN, T)                       \
    547 void flatcc_json_printer_ ## TN ## _enum_vector_field(                      \
    548         flatcc_json_printer_t *ctx,                                         \
    549         flatcc_json_printer_table_descriptor_t *td,                         \
    550         int id, const char *name, size_t len,                               \
    551         flatcc_json_printer_ ## TN ##_enum_f *pf);
    552 
    553 __define_print_scalar_field_proto(uint8, uint8_t)
    554 __define_print_scalar_field_proto(uint16, uint16_t)
    555 __define_print_scalar_field_proto(uint32, uint32_t)
    556 __define_print_scalar_field_proto(uint64, uint64_t)
    557 __define_print_scalar_field_proto(int8, int8_t)
    558 __define_print_scalar_field_proto(int16, int16_t)
    559 __define_print_scalar_field_proto(int32, int32_t)
    560 __define_print_scalar_field_proto(int64, int64_t)
    561 __define_print_scalar_field_proto(bool, flatbuffers_bool_t)
    562 __define_print_scalar_field_proto(float, float)
    563 __define_print_scalar_field_proto(double, double)
    564 
    565 __define_print_enum_field_proto(uint8, uint8_t)
    566 __define_print_enum_field_proto(uint16, uint16_t)
    567 __define_print_enum_field_proto(uint32, uint32_t)
    568 __define_print_enum_field_proto(uint64, uint64_t)
    569 __define_print_enum_field_proto(int8, int8_t)
    570 __define_print_enum_field_proto(int16, int16_t)
    571 __define_print_enum_field_proto(int32, int32_t)
    572 __define_print_enum_field_proto(int64, int64_t)
    573 __define_print_enum_field_proto(bool, flatbuffers_bool_t)
    574 
    575 __define_print_scalar_optional_field_proto(uint8, uint8_t)
    576 __define_print_scalar_optional_field_proto(uint16, uint16_t)
    577 __define_print_scalar_optional_field_proto(uint32, uint32_t)
    578 __define_print_scalar_optional_field_proto(uint64, uint64_t)
    579 __define_print_scalar_optional_field_proto(int8, int8_t)
    580 __define_print_scalar_optional_field_proto(int16, int16_t)
    581 __define_print_scalar_optional_field_proto(int32, int32_t)
    582 __define_print_scalar_optional_field_proto(int64, int64_t)
    583 __define_print_scalar_optional_field_proto(bool, flatbuffers_bool_t)
    584 __define_print_scalar_optional_field_proto(float, float)
    585 __define_print_scalar_optional_field_proto(double, double)
    586 
    587 __define_print_enum_optional_field_proto(uint8, uint8_t)
    588 __define_print_enum_optional_field_proto(uint16, uint16_t)
    589 __define_print_enum_optional_field_proto(uint32, uint32_t)
    590 __define_print_enum_optional_field_proto(uint64, uint64_t)
    591 __define_print_enum_optional_field_proto(int8, int8_t)
    592 __define_print_enum_optional_field_proto(int16, int16_t)
    593 __define_print_enum_optional_field_proto(int32, int32_t)
    594 __define_print_enum_optional_field_proto(int64, int64_t)
    595 __define_print_enum_optional_field_proto(bool, flatbuffers_bool_t)
    596 
    597 __define_print_scalar_struct_field_proto(uint8, uint8_t)
    598 __define_print_scalar_struct_field_proto(uint16, uint16_t)
    599 __define_print_scalar_struct_field_proto(uint32, uint32_t)
    600 __define_print_scalar_struct_field_proto(uint64, uint64_t)
    601 __define_print_scalar_struct_field_proto(int8, int8_t)
    602 __define_print_scalar_struct_field_proto(int16, int16_t)
    603 __define_print_scalar_struct_field_proto(int32, int32_t)
    604 __define_print_scalar_struct_field_proto(int64, int64_t)
    605 __define_print_scalar_struct_field_proto(bool, flatbuffers_bool_t)
    606 __define_print_scalar_struct_field_proto(float, float)
    607 __define_print_scalar_struct_field_proto(double, double)
    608 
    609 /*
    610  * char arrays are special as there are no char fields
    611  * without arrays and because they are printed as strings.
    612  */
    613 __define_print_scalar_array_struct_field_proto(char, char)
    614 
    615 __define_print_scalar_array_struct_field_proto(uint8, uint8_t)
    616 __define_print_scalar_array_struct_field_proto(uint16, uint16_t)
    617 __define_print_scalar_array_struct_field_proto(uint32, uint32_t)
    618 __define_print_scalar_array_struct_field_proto(uint64, uint64_t)
    619 __define_print_scalar_array_struct_field_proto(int8, int8_t)
    620 __define_print_scalar_array_struct_field_proto(int16, int16_t)
    621 __define_print_scalar_array_struct_field_proto(int32, int32_t)
    622 __define_print_scalar_array_struct_field_proto(int64, int64_t)
    623 __define_print_scalar_array_struct_field_proto(bool, flatbuffers_bool_t)
    624 __define_print_scalar_array_struct_field_proto(float, float)
    625 __define_print_scalar_array_struct_field_proto(double, double)
    626 
    627 __define_print_enum_array_struct_field_proto(uint8, uint8_t)
    628 __define_print_enum_array_struct_field_proto(uint16, uint16_t)
    629 __define_print_enum_array_struct_field_proto(uint32, uint32_t)
    630 __define_print_enum_array_struct_field_proto(uint64, uint64_t)
    631 __define_print_enum_array_struct_field_proto(int8, int8_t)
    632 __define_print_enum_array_struct_field_proto(int16, int16_t)
    633 __define_print_enum_array_struct_field_proto(int32, int32_t)
    634 __define_print_enum_array_struct_field_proto(int64, int64_t)
    635 __define_print_enum_array_struct_field_proto(bool, flatbuffers_bool_t)
    636 
    637 __define_print_enum_struct_field_proto(uint8, uint8_t)
    638 __define_print_enum_struct_field_proto(uint16, uint16_t)
    639 __define_print_enum_struct_field_proto(uint32, uint32_t)
    640 __define_print_enum_struct_field_proto(uint64, uint64_t)
    641 __define_print_enum_struct_field_proto(int8, int8_t)
    642 __define_print_enum_struct_field_proto(int16, int16_t)
    643 __define_print_enum_struct_field_proto(int32, int32_t)
    644 __define_print_enum_struct_field_proto(int64, int64_t)
    645 __define_print_enum_struct_field_proto(bool, flatbuffers_bool_t)
    646 
    647 __define_print_scalar_vector_field_proto(uint8, uint8_t)
    648 __define_print_scalar_vector_field_proto(uint16, uint16_t)
    649 __define_print_scalar_vector_field_proto(uint32, uint32_t)
    650 __define_print_scalar_vector_field_proto(uint64, uint64_t)
    651 __define_print_scalar_vector_field_proto(int8, int8_t)
    652 __define_print_scalar_vector_field_proto(int16, int16_t)
    653 __define_print_scalar_vector_field_proto(int32, int32_t)
    654 __define_print_scalar_vector_field_proto(int64, int64_t)
    655 __define_print_scalar_vector_field_proto(bool, flatbuffers_bool_t)
    656 __define_print_scalar_vector_field_proto(float, float)
    657 __define_print_scalar_vector_field_proto(double, double)
    658 
    659 __define_print_enum_vector_field_proto(uint8, uint8_t)
    660 __define_print_enum_vector_field_proto(uint16, uint16_t)
    661 __define_print_enum_vector_field_proto(uint32, uint32_t)
    662 __define_print_enum_vector_field_proto(uint64, uint64_t)
    663 __define_print_enum_vector_field_proto(int8, int8_t)
    664 __define_print_enum_vector_field_proto(int16, int16_t)
    665 __define_print_enum_vector_field_proto(int32, int32_t)
    666 __define_print_enum_vector_field_proto(int64, int64_t)
    667 __define_print_enum_vector_field_proto(bool, flatbuffers_bool_t)
    668 
    669 void flatcc_json_printer_uint8_vector_base64_field(flatcc_json_printer_t *ctx,
    670         flatcc_json_printer_table_descriptor_t *td,
    671         int id, const char *name, size_t len, int urlsafe);
    672 
    673 /*
    674  * If `fid` is null, the identifier is not checked and is allowed to be
    675  * entirely absent.
    676  *
    677  * The buffer must at least be aligned to uoffset_t on systems that
    678  * require aligned memory addresses (as always for flatbuffers).
    679  */
    680 int flatcc_json_printer_table_as_root(flatcc_json_printer_t *ctx,
    681         const void *buf, size_t bufsiz, const char *fid,
    682         flatcc_json_printer_table_f *pf);
    683 
    684 int flatcc_json_printer_struct_as_root(flatcc_json_printer_t *ctx,
    685         const void *buf, size_t bufsiz, const char *fid,
    686         flatcc_json_printer_struct_f *pf);
    687 
    688 /*
    689  * Call before and after enum flags to ensure proper quotation. Enum
    690  * quotes may be configured runtime, but regardless of this, multiple
    691  * flags may be forced to be quoted depending on compile time flag since
    692  * not all parsers may be able to handle unquoted space separated values
    693  * even if they handle non-strict unquoted json otherwise.
    694  *
    695  * Flags should only be called when not empty (0) and when there are no
    696  * unknown flags in the value. Otherwise print the numeric value. The
    697  * auto generated code deals with this.
    698  *
    699  * This bit twiddling hack may be useful:
    700  *
    701  *     `multiple = 0 != (v & (v - 1);`
    702  */
    703 void flatcc_json_printer_delimit_enum_flags(flatcc_json_printer_t *ctx, int multiple);
    704 
    705 /* The index increments from 0 to handle space. It is not the flag bit position. */
    706 void flatcc_json_printer_enum_flag(flatcc_json_printer_t *ctx, int index, const char *symbol, size_t len);
    707 
    708 /* A struct inside another struct, as opposed to inside a table or a root. */
    709 void flatcc_json_printer_embedded_struct_field(flatcc_json_printer_t *ctx,
    710         int index, const void *p, size_t offset,
    711         const char *name, size_t len,
    712         flatcc_json_printer_struct_f pf);
    713 
    714 void flatcc_json_printer_embedded_struct_array_field(flatcc_json_printer_t *ctx,
    715         int index, const void *p, size_t offset,
    716         const char *name, size_t len,
    717         size_t size, size_t count,
    718         flatcc_json_printer_struct_f pf);
    719 
    720 void flatcc_json_printer_struct_field(flatcc_json_printer_t *ctx,
    721         flatcc_json_printer_table_descriptor_t *td,
    722         int id, const char *name, size_t len,
    723         flatcc_json_printer_struct_f *pf);
    724 
    725 void flatcc_json_printer_string_field(flatcc_json_printer_t *ctx,
    726         flatcc_json_printer_table_descriptor_t *td,
    727         int id, const char *name, size_t len);
    728 
    729 void flatcc_json_printer_string_vector_field(flatcc_json_printer_t *ctx,
    730         flatcc_json_printer_table_descriptor_t *td,
    731         int id, const char *name, size_t len);
    732 
    733 void flatcc_json_printer_table_field(flatcc_json_printer_t *ctx,
    734         flatcc_json_printer_table_descriptor_t *td,
    735         int id, const char *name, size_t len,
    736         flatcc_json_printer_table_f pf);
    737 
    738 void flatcc_json_printer_struct_vector_field(flatcc_json_printer_t *ctx,
    739         flatcc_json_printer_table_descriptor_t *td,
    740         int id, const char *name, size_t len,
    741         size_t size,
    742         flatcc_json_printer_struct_f pf);
    743 
    744 void flatcc_json_printer_table_vector_field(flatcc_json_printer_t *ctx,
    745         flatcc_json_printer_table_descriptor_t *td,
    746         int id, const char *name, size_t len,
    747         flatcc_json_printer_table_f pf);
    748 
    749 void flatcc_json_printer_union_vector_field(flatcc_json_printer_t *ctx,
    750         flatcc_json_printer_table_descriptor_t *td,
    751         int id, const char *name, size_t len,
    752         flatcc_json_printer_union_type_f ptf,
    753         flatcc_json_printer_union_f pf);
    754 
    755 void flatcc_json_printer_struct_as_nested_root(flatcc_json_printer_t *ctx,
    756         flatcc_json_printer_table_descriptor_t *td,
    757         int id, const char *name, size_t len,
    758         const char *fid,
    759         flatcc_json_printer_struct_f *pf);
    760 
    761 void flatcc_json_printer_table_as_nested_root(flatcc_json_printer_t *ctx,
    762         flatcc_json_printer_table_descriptor_t *td,
    763         int id, const char *name, size_t len,
    764         const char *fid,
    765         flatcc_json_printer_table_f pf);
    766 
    767 void flatcc_json_printer_union_field(flatcc_json_printer_t *ctx,
    768         flatcc_json_printer_table_descriptor_t *td,
    769         int id, const char *name, size_t len,
    770         flatcc_json_printer_union_type_f ptf,
    771         flatcc_json_printer_union_f pf);
    772 
    773 void flatcc_json_printer_union_table(flatcc_json_printer_t *ctx,
    774         flatcc_json_printer_union_descriptor_t *ud,
    775         flatcc_json_printer_table_f pf);
    776 
    777 void flatcc_json_printer_union_struct(flatcc_json_printer_t *ctx,
    778         flatcc_json_printer_union_descriptor_t *ud,
    779         flatcc_json_printer_struct_f pf);
    780 
    781 void flatcc_json_printer_union_string(flatcc_json_printer_t *ctx,
    782         flatcc_json_printer_union_descriptor_t *ud);
    783 
    784 #ifdef __cplusplus
    785 }
    786 #endif
    787 
    788 #endif /* FLATCC_JSON_PRINTER_H */