1
0
mirror of git://jb55.com/damus synced 2024-09-16 02:03:45 +00:00
damus/nostrdb/flatcc/json_printer.c
2023-08-28 08:17:25 -07:00

1487 lines
56 KiB
C

/*
* Runtime support for printing flatbuffers to JSON.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "flatcc_rtconfig.h"
#include "flatcc_assert.h"
/*
* Grisu significantly improves printing speed of floating point values
* and also the overall printing speed when floating point values are
* present in non-trivial amounts. (Also applies to parsing).
*/
#if FLATCC_USE_GRISU3 && !defined(PORTABLE_USE_GRISU3)
#define PORTABLE_USE_GRISU3 1
#endif
#include "flatcc_flatbuffers.h"
#include "flatcc_json_printer.h"
#include "flatcc_identifier.h"
#include "portable/pprintint.h"
#include "portable/pprintfp.h"
#include "portable/pbase64.h"
#define RAISE_ERROR(err) flatcc_json_printer_set_error(ctx, flatcc_json_printer_error_##err)
const char *flatcc_json_printer_error_string(int err)
{
switch (err) {
#define XX(no, str) \
case flatcc_json_printer_error_##no: \
return str;
FLATCC_JSON_PRINT_ERROR_MAP(XX)
#undef XX
default:
return "unknown";
}
}
#define flatcc_json_printer_utype_enum_f flatcc_json_printer_union_type_f
#define flatbuffers_utype_read_from_pe __flatbuffers_utype_read_from_pe
#define uoffset_t flatbuffers_uoffset_t
#define soffset_t flatbuffers_soffset_t
#define voffset_t flatbuffers_voffset_t
#define utype_t flatbuffers_utype_t
#define uoffset_size sizeof(uoffset_t)
#define soffset_size sizeof(soffset_t)
#define voffset_size sizeof(voffset_t)
#define utype_size sizeof(utype_t)
#define offset_size uoffset_size
#if FLATBUFFERS_UTYPE_MAX == UINT8_MAX
#define print_utype print_uint8
#else
#ifdef FLATBUFFERS_UTYPE_MIN
#define print_utype print_int64
#else
#define print_utype print_uint64
#endif
#endif
static inline const void *read_uoffset_ptr(const void *p)
{
return (uint8_t *)p + __flatbuffers_uoffset_read_from_pe(p);
}
static inline voffset_t read_voffset(const void *p, uoffset_t base)
{
return __flatbuffers_voffset_read_from_pe((uint8_t *)p + base);
}
static inline const void *get_field_ptr(flatcc_json_printer_table_descriptor_t *td, int id)
{
uoffset_t vo = (uoffset_t)(id + 2) * (uoffset_t)sizeof(voffset_t);
if (vo >= (uoffset_t)td->vsize) {
return 0;
}
vo = read_voffset(td->vtable, vo);
if (vo == 0) {
return 0;
}
return (uint8_t *)td->table + vo;
}
#define print_char(c) *ctx->p++ = (c)
#define print_null() do { \
print_char('n'); \
print_char('u'); \
print_char('l'); \
print_char('l'); \
} while (0)
#define print_start(c) do { \
++ctx->level; \
*ctx->p++ = c; \
} while (0)
#define print_end(c) do { \
if (ctx->indent) { \
*ctx->p++ = '\n'; \
--ctx->level; \
print_indent(ctx); \
} \
*ctx->p++ = c; \
} while (0)
#define print_space() do { \
*ctx->p = ' '; \
ctx->p += !!ctx->indent; \
} while (0)
#define print_nl() do { \
if (ctx->indent) { \
*ctx->p++ = '\n'; \
print_indent(ctx); \
} else { \
flatcc_json_printer_flush_partial(ctx); \
} \
} while (0)
/* Call at the end so print_end does not have to check for level. */
#define print_last_nl() do { \
if (ctx->indent && ctx->level == 0) { \
*ctx->p++ = '\n'; \
} \
ctx->flush(ctx, 1); \
} while (0)
int flatcc_json_printer_fmt_float(char *buf, float n)
{
#if FLATCC_JSON_PRINT_HEX_FLOAT
return print_hex_float(buf, n);
#else
return print_float(n, buf);
#endif
}
int flatcc_json_printer_fmt_double(char *buf, double n)
{
#if FLATCC_JSON_PRINT_HEX_FLOAT
return print_hex_double(buf, n);
#else
return print_double(n, buf);
#endif
}
int flatcc_json_printer_fmt_bool(char *buf, int n)
{
if (n) {
memcpy(buf, "true", 4);
return 4;
}
memcpy(buf, "false", 5);
return 5;
}
static void print_ex(flatcc_json_printer_t *ctx, const char *s, size_t n)
{
size_t k;
if (ctx->p >= ctx->pflush) {
ctx->flush(ctx, 0);
}
k = (size_t)(ctx->pflush - ctx->p);
while (n > k) {
memcpy(ctx->p, s, k);
ctx->p += k;
s += k;
n -= k;
ctx->flush(ctx, 0);
k = (size_t)(ctx->pflush - ctx->p);
}
memcpy(ctx->p, s, n);
ctx->p += n;
}
static inline void print(flatcc_json_printer_t *ctx, const char *s, size_t n)
{
if (ctx->p + n >= ctx->pflush) {
print_ex(ctx, s, n);
} else {
memcpy(ctx->p, s, n);
ctx->p += n;
}
}
static void print_escape(flatcc_json_printer_t *ctx, unsigned char c)
{
unsigned char x;
print_char('\\');
switch (c) {
case '"': print_char('\"'); break;
case '\\': print_char('\\'); break;
case '\t' : print_char('t'); break;
case '\f' : print_char('f'); break;
case '\r' : print_char('r'); break;
case '\n' : print_char('n'); break;
case '\b' : print_char('b'); break;
default:
print_char('u');
print_char('0');
print_char('0');
x = c >> 4;
x += x < 10 ? '0' : 'a' - 10;
print_char((char)x);
x = c & 15;
x += x < 10 ? '0' : 'a' - 10;
print_char((char)x);
break;
}
}
/*
* Even though we know the the string length, we need to scan for escape
* characters. There may be embedded zeroes. Because FlatBuffer strings
* are always zero terminated, we assume and optimize for this.
*
* We enforce \u00xx for control characters, but not for invalid
* characters like 0xff - this makes it possible to handle some other
* codepages transparently while formally not valid. (Formally JSON
* also supports UTF-16/32 little/big endian but flatbuffers only
* support UTF-8 and we expect this in JSON input/output too).
*/
static void print_string(flatcc_json_printer_t *ctx, const char *s, size_t n)
{
const char *p = s;
/* Unsigned is important. */
unsigned char c;
size_t k;
print_char('\"');
for (;;) {
c = (unsigned char)*p;
while (c >= 0x20 && c != '\"' && c != '\\') {
c = (unsigned char)*++p;
}
k = (size_t)(p - s);
/* Even if k == 0, print ensures buffer flush. */
print(ctx, s, k);
n -= k;
if (n == 0) break;
s += k;
print_escape(ctx, c);
++p;
--n;
++s;
}
print_char('\"');
}
/*
* Similar to print_string, but null termination is not guaranteed, and
* trailing nulls are stripped.
*/
static void print_char_array(flatcc_json_printer_t *ctx, const char *s, size_t n)
{
const char *p = s;
/* Unsigned is important. */
unsigned char c = 0;
size_t k;
while (n > 0 && s[n - 1] == '\0') --n;
print_char('\"');
for (;;) {
while (n) {
c = (unsigned char)*p;
if (c < 0x20 || c == '\"' || c == '\\') break;
++p;
--n;
}
k = (size_t)(p - s);
/* Even if k == 0, print ensures buffer flush. */
print(ctx, s, k);
if (n == 0) break;
s += k;
print_escape(ctx, c);
++p;
--n;
++s;
}
print_char('\"');
}
static void print_uint8_vector_base64_object(flatcc_json_printer_t *ctx, const void *p, int mode)
{
const int unpadded_mode = mode & ~base64_enc_modifier_padding;
size_t k, n, len;
const uint8_t *data;
size_t data_len, src_len;
data_len = (size_t)__flatbuffers_uoffset_read_from_pe(p);
data = (const uint8_t *)p + uoffset_size;
print_char('\"');
len = base64_encoded_size(data_len, mode);
if (ctx->p + len >= ctx->pflush) {
ctx->flush(ctx, 0);
}
while (ctx->p + len > ctx->pflush) {
/* Multiples of 4 output chars consumes exactly 3 bytes before final padding. */
k = (size_t)(ctx->pflush - ctx->p) & ~(size_t)3;
n = k * 3 / 4;
FLATCC_ASSERT(n > 0);
src_len = k * 3 / 4;
base64_encode((uint8_t *)ctx->p, data, 0, &src_len, unpadded_mode);
ctx->p += k;
data += n;
data_len -= n;
ctx->flush(ctx, 0);
len = base64_encoded_size(data_len, mode);
}
base64_encode((uint8_t *)ctx->p, data, 0, &data_len, mode);
ctx->p += len;
print_char('\"');
}
static void print_indent_ex(flatcc_json_printer_t *ctx, size_t n)
{
size_t k;
if (ctx->p >= ctx->pflush) {
ctx->flush(ctx, 0);
}
k = (size_t)(ctx->pflush - ctx->p);
while (n > k) {
memset(ctx->p, ' ', k);
ctx->p += k;
n -= k;
ctx->flush(ctx, 0);
k = (size_t)(ctx->pflush - ctx->p);
}
memset(ctx->p, ' ', n);
ctx->p += n;
}
static inline void print_indent(flatcc_json_printer_t *ctx)
{
size_t n = (size_t)(ctx->level * ctx->indent);
if (ctx->p + n > ctx->pflush) {
print_indent_ex(ctx, n);
} else {
memset(ctx->p, ' ', n);
ctx->p += n;
}
}
/*
* Helpers for external use - does not do autmatic pretty printing, but
* does escape strings.
*/
void flatcc_json_printer_string(flatcc_json_printer_t *ctx, const char *s, size_t n)
{
print_string(ctx, s, n);
}
void flatcc_json_printer_write(flatcc_json_printer_t *ctx, const char *s, size_t n)
{
print(ctx, s, n);
}
void flatcc_json_printer_nl(flatcc_json_printer_t *ctx)
{
print_char('\n');
flatcc_json_printer_flush_partial(ctx);
}
void flatcc_json_printer_char(flatcc_json_printer_t *ctx, char c)
{
print_char(c);
}
void flatcc_json_printer_indent(flatcc_json_printer_t *ctx)
{
/*
* This is only needed when indent is 0 but helps external users
* to avoid flushing when indenting.
*/
print_indent(ctx);
}
void flatcc_json_printer_add_level(flatcc_json_printer_t *ctx, int n)
{
ctx->level += n;
}
int flatcc_json_printer_get_level(flatcc_json_printer_t *ctx)
{
return ctx->level;
}
static inline void print_symbol(flatcc_json_printer_t *ctx, const char *name, size_t len)
{
*ctx->p = '\"';
ctx->p += !ctx->unquote;
if (ctx->p + len < ctx->pflush) {
memcpy(ctx->p, name, len);
ctx->p += len;
} else {
print(ctx, name, len);
}
*ctx->p = '\"';
ctx->p += !ctx->unquote;
}
static inline void print_name(flatcc_json_printer_t *ctx, const char *name, size_t len)
{
print_nl();
print_symbol(ctx, name, len);
print_char(':');
print_space();
}
#define __flatcc_define_json_printer_scalar(TN, T) \
void flatcc_json_printer_ ## TN( \
flatcc_json_printer_t *ctx, T v) \
{ \
ctx->p += print_ ## TN(v, ctx->p); \
}
__flatcc_define_json_printer_scalar(uint8, uint8_t)
__flatcc_define_json_printer_scalar(uint16, uint16_t)
__flatcc_define_json_printer_scalar(uint32, uint32_t)
__flatcc_define_json_printer_scalar(uint64, uint64_t)
__flatcc_define_json_printer_scalar(int8, int8_t)
__flatcc_define_json_printer_scalar(int16, int16_t)
__flatcc_define_json_printer_scalar(int32, int32_t)
__flatcc_define_json_printer_scalar(int64, int64_t)
__flatcc_define_json_printer_scalar(float, float)
__flatcc_define_json_printer_scalar(double, double)
void flatcc_json_printer_enum(flatcc_json_printer_t *ctx, const char *symbol, size_t len)
{
print_symbol(ctx, symbol, len);
}
void flatcc_json_printer_delimit_enum_flags(flatcc_json_printer_t *ctx, int multiple)
{
#if FLATCC_JSON_PRINT_ALWAYS_QUOTE_MULTIPLE_FLAGS
int quote = !ctx->unquote || multiple;
#else
int quote = !ctx->unquote;
#endif
*ctx->p = '"';
ctx->p += quote;
}
void flatcc_json_printer_enum_flag(flatcc_json_printer_t *ctx, int count, const char *symbol, size_t len)
{
*ctx->p = ' ';
ctx->p += count > 0;
print(ctx, symbol, len);
}
static inline void print_string_object(flatcc_json_printer_t *ctx, const void *p)
{
size_t len;
const char *s;
len = (size_t)__flatbuffers_uoffset_read_from_pe(p);
s = (const char *)p + uoffset_size;
print_string(ctx, s, len);
}
#define __define_print_scalar_struct_field(TN, T) \
void flatcc_json_printer_ ## TN ## _struct_field(flatcc_json_printer_t *ctx,\
int index, const void *p, size_t offset, \
const char *name, size_t len) \
{ \
T x = flatbuffers_ ## TN ## _read_from_pe((uint8_t *)p + offset); \
\
if (index) { \
print_char(','); \
} \
print_name(ctx, name, len); \
ctx->p += print_ ## TN (x, ctx->p); \
}
void flatcc_json_printer_char_array_struct_field(
flatcc_json_printer_t *ctx,
int index, const void *p, size_t offset,
const char *name, size_t len, size_t count)
{
p = (void *)((size_t)p + offset);
if (index) {
print_char(',');
}
print_name(ctx, name, len);
print_char_array(ctx, p, count);
}
#define __define_print_scalar_array_struct_field(TN, T) \
void flatcc_json_printer_ ## TN ## _array_struct_field( \
flatcc_json_printer_t *ctx, \
int index, const void *p, size_t offset, \
const char *name, size_t len, size_t count) \
{ \
p = (void *)((size_t)p + offset); \
if (index) { \
print_char(','); \
} \
print_name(ctx, name, len); \
print_start('['); \
if (count) { \
print_nl(); \
ctx->p += print_ ## TN ( \
flatbuffers_ ## TN ## _read_from_pe(p), \
ctx->p); \
p = (void *)((size_t)p + sizeof(T)); \
--count; \
} \
while (count--) { \
print_char(','); \
print_nl(); \
ctx->p += print_ ## TN ( \
flatbuffers_ ## TN ## _read_from_pe(p), \
ctx->p); \
p = (void *)((size_t)p + sizeof(T)); \
} \
print_end(']'); \
}
#define __define_print_enum_array_struct_field(TN, T) \
void flatcc_json_printer_ ## TN ## _enum_array_struct_field( \
flatcc_json_printer_t *ctx, \
int index, const void *p, size_t offset, \
const char *name, size_t len, size_t count, \
flatcc_json_printer_ ## TN ##_enum_f *pf) \
{ \
T x; \
\
p = (void *)((size_t)p + offset); \
if (index) { \
print_char(','); \
} \
print_name(ctx, name, len); \
print_start('['); \
if (count) { \
print_nl(); \
x = flatbuffers_ ## TN ## _read_from_pe(p); \
if (ctx->noenum) { \
ctx->p += print_ ## TN (x, ctx->p); \
} else { \
pf(ctx, x); \
} \
p = (void *)((size_t)p + sizeof(T)); \
--count; \
} \
while (count--) { \
print_char(','); \
print_nl(); \
x = flatbuffers_ ## TN ## _read_from_pe(p); \
if (ctx->noenum) { \
ctx->p += print_ ## TN (x, ctx->p); \
} else { \
pf(ctx, x); \
} \
p = (void *)((size_t)p + sizeof(T)); \
} \
print_end(']'); \
}
#define __define_print_enum_struct_field(TN, T) \
void flatcc_json_printer_ ## TN ## _enum_struct_field( \
flatcc_json_printer_t *ctx, \
int index, const void *p, size_t offset, \
const char *name, size_t len, \
flatcc_json_printer_ ## TN ##_enum_f *pf) \
{ \
T x = flatbuffers_ ## TN ## _read_from_pe((uint8_t *)p + offset); \
\
if (index) { \
print_char(','); \
} \
print_name(ctx, name, len); \
if (ctx->noenum) { \
ctx->p += print_ ## TN (x, ctx->p); \
} else { \
pf(ctx, x); \
} \
}
#define __define_print_scalar_field(TN, T) \
void flatcc_json_printer_ ## TN ## _field(flatcc_json_printer_t *ctx, \
flatcc_json_printer_table_descriptor_t *td, \
int id, const char *name, size_t len, T v) \
{ \
T x; \
const void *p = get_field_ptr(td, id); \
\
if (p) { \
x = flatbuffers_ ## TN ## _read_from_pe(p); \
if (x == v && ctx->skip_default) { \
return; \
} \
} else { \
if (!ctx->force_default) { \
return; \
} \
x = v; \
} \
if (td->count++) { \
print_char(','); \
} \
print_name(ctx, name, len); \
ctx->p += print_ ## TN (x, ctx->p); \
}
#define __define_print_scalar_optional_field(TN, T) \
void flatcc_json_printer_ ## TN ## _optional_field( \
flatcc_json_printer_t *ctx, \
flatcc_json_printer_table_descriptor_t *td, \
int id, const char *name, size_t len) \
{ \
T x; \
const void *p = get_field_ptr(td, id); \
\
if (!p) return; \
x = flatbuffers_ ## TN ## _read_from_pe(p); \
if (td->count++) { \
print_char(','); \
} \
print_name(ctx, name, len); \
ctx->p += print_ ## TN (x, ctx->p); \
}
#define __define_print_enum_field(TN, T) \
void flatcc_json_printer_ ## TN ## _enum_field(flatcc_json_printer_t *ctx, \
flatcc_json_printer_table_descriptor_t *td, \
int id, const char *name, size_t len, T v, \
flatcc_json_printer_ ## TN ##_enum_f *pf) \
{ \
T x; \
const void *p = get_field_ptr(td, id); \
\
if (p) { \
x = flatbuffers_ ## TN ## _read_from_pe(p); \
if (x == v && ctx->skip_default) { \
return; \
} \
} else { \
if (!ctx->force_default) { \
return; \
} \
x = v; \
} \
if (td->count++) { \
print_char(','); \
} \
print_name(ctx, name, len); \
if (ctx->noenum) { \
ctx->p += print_ ## TN (x, ctx->p); \
} else { \
pf(ctx, x); \
} \
}
#define __define_print_enum_optional_field(TN, T) \
void flatcc_json_printer_ ## TN ## _enum_optional_field( \
flatcc_json_printer_t *ctx, \
flatcc_json_printer_table_descriptor_t *td, \
int id, const char *name, size_t len, \
flatcc_json_printer_ ## TN ##_enum_f *pf) \
{ \
T x; \
const void *p = get_field_ptr(td, id); \
\
if (!p) return; \
x = flatbuffers_ ## TN ## _read_from_pe(p); \
if (td->count++) { \
print_char(','); \
} \
print_name(ctx, name, len); \
if (ctx->noenum) { \
ctx->p += print_ ## TN (x, ctx->p); \
} else { \
pf(ctx, x); \
} \
}
static inline void print_table_object(flatcc_json_printer_t *ctx,
const void *p, int ttl, flatcc_json_printer_table_f pf)
{
flatcc_json_printer_table_descriptor_t td;
if (!--ttl) {
flatcc_json_printer_set_error(ctx, flatcc_json_printer_error_deep_recursion);
return;
}
print_start('{');
td.count = 0;
td.ttl = ttl;
td.table = p;
td.vtable = (uint8_t *)p - __flatbuffers_soffset_read_from_pe(p);
td.vsize = __flatbuffers_voffset_read_from_pe(td.vtable);
pf(ctx, &td);
print_end('}');
}
void flatcc_json_printer_string_field(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len)
{
const void *p = get_field_ptr(td, id);
if (p) {
if (td->count++) {
print_char(',');
}
print_name(ctx, name, len);
print_string_object(ctx, read_uoffset_ptr(p));
}
}
void flatcc_json_printer_uint8_vector_base64_field(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len, int urlsafe)
{
const void *p = get_field_ptr(td, id);
int mode;
mode = urlsafe ? base64_mode_url : base64_mode_rfc4648;
mode |= base64_enc_modifier_padding;
if (p) {
if (td->count++) {
print_char(',');
}
print_name(ctx, name, len);
print_uint8_vector_base64_object(ctx, read_uoffset_ptr(p), mode);
}
}
#define __define_print_scalar_vector_field(TN, T) \
void flatcc_json_printer_ ## TN ## _vector_field( \
flatcc_json_printer_t *ctx, \
flatcc_json_printer_table_descriptor_t *td, \
int id, const char *name, size_t len) \
{ \
const void *p = get_field_ptr(td, id); \
uoffset_t count; \
\
if (p) { \
if (td->count++) { \
print_char(','); \
} \
p = read_uoffset_ptr(p); \
count = __flatbuffers_uoffset_read_from_pe(p); \
p = (void *)((size_t)p + uoffset_size); \
print_name(ctx, name, len); \
print_start('['); \
if (count) { \
print_nl(); \
ctx->p += print_ ## TN ( \
flatbuffers_ ## TN ## _read_from_pe(p), \
ctx->p); \
p = (void *)((size_t)p + sizeof(T)); \
--count; \
} \
while (count--) { \
print_char(','); \
print_nl(); \
ctx->p += print_ ## TN ( \
flatbuffers_ ## TN ## _read_from_pe(p), \
ctx->p); \
p = (void *)((size_t)p + sizeof(T)); \
} \
print_end(']'); \
} \
}
#define __define_print_enum_vector_field(TN, T) \
void flatcc_json_printer_ ## TN ## _enum_vector_field( \
flatcc_json_printer_t *ctx, \
flatcc_json_printer_table_descriptor_t *td, \
int id, const char *name, size_t len, \
flatcc_json_printer_ ## TN ##_enum_f *pf) \
{ \
const void *p; \
uoffset_t count; \
\
if (ctx->noenum) { \
flatcc_json_printer_ ## TN ## _vector_field(ctx, td, id, name, len);\
return; \
} \
p = get_field_ptr(td, id); \
if (p) { \
if (td->count++) { \
print_char(','); \
} \
p = read_uoffset_ptr(p); \
count = __flatbuffers_uoffset_read_from_pe(p); \
p = (void *)((size_t)p + uoffset_size); \
print_name(ctx, name, len); \
print_start('['); \
if (count) { \
print_nl(); \
pf(ctx, flatbuffers_ ## TN ## _read_from_pe(p)); \
p = (void *)((size_t)p + sizeof(T)); \
--count; \
} \
while (count--) { \
print_char(','); \
print_nl(); \
pf(ctx, flatbuffers_ ## TN ## _read_from_pe(p)); \
p = (void *)((size_t)p + sizeof(T)); \
} \
print_end(']'); \
} \
}
__define_print_scalar_field(uint8, uint8_t)
__define_print_scalar_field(uint16, uint16_t)
__define_print_scalar_field(uint32, uint32_t)
__define_print_scalar_field(uint64, uint64_t)
__define_print_scalar_field(int8, int8_t)
__define_print_scalar_field(int16, int16_t)
__define_print_scalar_field(int32, int32_t)
__define_print_scalar_field(int64, int64_t)
__define_print_scalar_field(bool, flatbuffers_bool_t)
__define_print_scalar_field(float, float)
__define_print_scalar_field(double, double)
__define_print_enum_field(uint8, uint8_t)
__define_print_enum_field(uint16, uint16_t)
__define_print_enum_field(uint32, uint32_t)
__define_print_enum_field(uint64, uint64_t)
__define_print_enum_field(int8, int8_t)
__define_print_enum_field(int16, int16_t)
__define_print_enum_field(int32, int32_t)
__define_print_enum_field(int64, int64_t)
__define_print_enum_field(bool, flatbuffers_bool_t)
__define_print_scalar_optional_field(uint8, uint8_t)
__define_print_scalar_optional_field(uint16, uint16_t)
__define_print_scalar_optional_field(uint32, uint32_t)
__define_print_scalar_optional_field(uint64, uint64_t)
__define_print_scalar_optional_field(int8, int8_t)
__define_print_scalar_optional_field(int16, int16_t)
__define_print_scalar_optional_field(int32, int32_t)
__define_print_scalar_optional_field(int64, int64_t)
__define_print_scalar_optional_field(bool, flatbuffers_bool_t)
__define_print_scalar_optional_field(float, float)
__define_print_scalar_optional_field(double, double)
__define_print_enum_optional_field(uint8, uint8_t)
__define_print_enum_optional_field(uint16, uint16_t)
__define_print_enum_optional_field(uint32, uint32_t)
__define_print_enum_optional_field(uint64, uint64_t)
__define_print_enum_optional_field(int8, int8_t)
__define_print_enum_optional_field(int16, int16_t)
__define_print_enum_optional_field(int32, int32_t)
__define_print_enum_optional_field(int64, int64_t)
__define_print_enum_optional_field(bool, flatbuffers_bool_t)
__define_print_scalar_struct_field(uint8, uint8_t)
__define_print_scalar_struct_field(uint16, uint16_t)
__define_print_scalar_struct_field(uint32, uint32_t)
__define_print_scalar_struct_field(uint64, uint64_t)
__define_print_scalar_struct_field(int8, int8_t)
__define_print_scalar_struct_field(int16, int16_t)
__define_print_scalar_struct_field(int32, int32_t)
__define_print_scalar_struct_field(int64, int64_t)
__define_print_scalar_struct_field(bool, flatbuffers_bool_t)
__define_print_scalar_struct_field(float, float)
__define_print_scalar_struct_field(double, double)
__define_print_scalar_array_struct_field(uint8, uint8_t)
__define_print_scalar_array_struct_field(uint16, uint16_t)
__define_print_scalar_array_struct_field(uint32, uint32_t)
__define_print_scalar_array_struct_field(uint64, uint64_t)
__define_print_scalar_array_struct_field(int8, int8_t)
__define_print_scalar_array_struct_field(int16, int16_t)
__define_print_scalar_array_struct_field(int32, int32_t)
__define_print_scalar_array_struct_field(int64, int64_t)
__define_print_scalar_array_struct_field(bool, flatbuffers_bool_t)
__define_print_scalar_array_struct_field(float, float)
__define_print_scalar_array_struct_field(double, double)
__define_print_enum_array_struct_field(uint8, uint8_t)
__define_print_enum_array_struct_field(uint16, uint16_t)
__define_print_enum_array_struct_field(uint32, uint32_t)
__define_print_enum_array_struct_field(uint64, uint64_t)
__define_print_enum_array_struct_field(int8, int8_t)
__define_print_enum_array_struct_field(int16, int16_t)
__define_print_enum_array_struct_field(int32, int32_t)
__define_print_enum_array_struct_field(int64, int64_t)
__define_print_enum_array_struct_field(bool, flatbuffers_bool_t)
__define_print_enum_struct_field(uint8, uint8_t)
__define_print_enum_struct_field(uint16, uint16_t)
__define_print_enum_struct_field(uint32, uint32_t)
__define_print_enum_struct_field(uint64, uint64_t)
__define_print_enum_struct_field(int8, int8_t)
__define_print_enum_struct_field(int16, int16_t)
__define_print_enum_struct_field(int32, int32_t)
__define_print_enum_struct_field(int64, int64_t)
__define_print_enum_struct_field(bool, flatbuffers_bool_t)
__define_print_scalar_vector_field(utype, flatbuffers_utype_t)
__define_print_scalar_vector_field(uint8, uint8_t)
__define_print_scalar_vector_field(uint16, uint16_t)
__define_print_scalar_vector_field(uint32, uint32_t)
__define_print_scalar_vector_field(uint64, uint64_t)
__define_print_scalar_vector_field(int8, int8_t)
__define_print_scalar_vector_field(int16, int16_t)
__define_print_scalar_vector_field(int32, int32_t)
__define_print_scalar_vector_field(int64, int64_t)
__define_print_scalar_vector_field(bool, flatbuffers_bool_t)
__define_print_scalar_vector_field(float, float)
__define_print_scalar_vector_field(double, double)
__define_print_enum_vector_field(utype, flatbuffers_utype_t)
__define_print_enum_vector_field(uint8, uint8_t)
__define_print_enum_vector_field(uint16, uint16_t)
__define_print_enum_vector_field(uint32, uint32_t)
__define_print_enum_vector_field(uint64, uint64_t)
__define_print_enum_vector_field(int8, int8_t)
__define_print_enum_vector_field(int16, int16_t)
__define_print_enum_vector_field(int32, int32_t)
__define_print_enum_vector_field(int64, int64_t)
__define_print_enum_vector_field(bool, flatbuffers_bool_t)
void flatcc_json_printer_struct_vector_field(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len,
size_t size,
flatcc_json_printer_struct_f pf)
{
const uint8_t *p = get_field_ptr(td, id);
uoffset_t count;
if (p) {
if (td->count++) {
print_char(',');
}
p = read_uoffset_ptr(p);
count = __flatbuffers_uoffset_read_from_pe(p);
p += uoffset_size;
print_name(ctx, name, len);
print_start('[');
if (count) {
print_nl();
print_start('{');
pf(ctx, p);
print_end('}');
--count;
}
while (count--) {
p += size;
print_char(',');
print_nl();
print_start('{');
pf(ctx, p);
print_end('}');
}
print_end(']');
}
}
void flatcc_json_printer_string_vector_field(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len)
{
const uoffset_t *p = get_field_ptr(td, id);
uoffset_t count;
if (p) {
if (td->count++) {
print_char(',');
}
p = read_uoffset_ptr(p);
count = __flatbuffers_uoffset_read_from_pe(p);
++p;
print_name(ctx, name, len);
print_start('[');
if (count) {
print_nl();
print_string_object(ctx, read_uoffset_ptr(p));
--count;
}
while (count--) {
++p;
print_char(',');
print_nl();
print_string_object(ctx, read_uoffset_ptr(p));
}
print_end(']');
}
}
void flatcc_json_printer_table_vector_field(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len,
flatcc_json_printer_table_f pf)
{
const uoffset_t *p = get_field_ptr(td, id);
uoffset_t count;
if (p) {
if (td->count++) {
print_char(',');
}
p = read_uoffset_ptr(p);
count = __flatbuffers_uoffset_read_from_pe(p);
++p;
print_name(ctx, name, len);
print_start('[');
if (count) {
print_table_object(ctx, read_uoffset_ptr(p), td->ttl, pf);
--count;
}
while (count--) {
++p;
print_char(',');
print_table_object(ctx, read_uoffset_ptr(p), td->ttl, pf);
}
print_end(']');
}
}
void flatcc_json_printer_union_vector_field(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len,
flatcc_json_printer_union_type_f ptf,
flatcc_json_printer_union_f pf)
{
const uoffset_t *pt = get_field_ptr(td, id - 1);
const uoffset_t *p = get_field_ptr(td, id);
utype_t *types, type;
uoffset_t count;
char type_name[FLATCC_JSON_PRINT_NAME_LEN_MAX + 5];
flatcc_json_printer_union_descriptor_t ud;
ud.ttl = td->ttl;
if (len > FLATCC_JSON_PRINT_NAME_LEN_MAX) {
RAISE_ERROR(bad_input);
FLATCC_ASSERT(0 && "identifier too long");
return;
}
memcpy(type_name, name, len);
memcpy(type_name + len, "_type", 5);
if (p && pt) {
flatcc_json_printer_utype_enum_vector_field(ctx, td, id - 1,
type_name, len + 5, ptf);
if (td->count++) {
print_char(',');
}
p = read_uoffset_ptr(p);
pt = read_uoffset_ptr(pt);
count = __flatbuffers_uoffset_read_from_pe(p);
++p;
++pt;
types = (utype_t *)pt;
print_name(ctx, name, len);
print_start('[');
if (count) {
type = __flatbuffers_utype_read_from_pe(types);
if (type != 0) {
ud.type = type;
ud.member = p;
pf(ctx, &ud);
} else {
print_null();
}
--count;
}
while (count--) {
++p;
++types;
type = __flatbuffers_utype_read_from_pe(types);
print_char(',');
if (type != 0) {
ud.type = type;
ud.member = p;
pf(ctx, &ud);
} else {
print_null();
}
}
print_end(']');
}
}
void flatcc_json_printer_table_field(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len,
flatcc_json_printer_table_f pf)
{
const void *p = get_field_ptr(td, id);
if (p) {
if (td->count++) {
print_char(',');
}
print_name(ctx, name, len);
print_table_object(ctx, read_uoffset_ptr(p), td->ttl, pf);
}
}
void flatcc_json_printer_union_field(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len,
flatcc_json_printer_union_type_f ptf,
flatcc_json_printer_union_f pf)
{
const void *pt = get_field_ptr(td, id - 1);
const void *p = get_field_ptr(td, id);
utype_t type;
flatcc_json_printer_union_descriptor_t ud;
if (!p || !pt) {
return;
}
type = __flatbuffers_utype_read_from_pe(pt);
if (td->count++) {
print_char(',');
}
print_nl();
*ctx->p = '\"';
ctx->p += !ctx->unquote;
if (ctx->p + len < ctx->pflush) {
memcpy(ctx->p, name, len);
ctx->p += len;
} else {
print(ctx, name, len);
}
print(ctx, "_type", 5);
*ctx->p = '\"';
ctx->p += !ctx->unquote;
print_char(':');
print_space();
if (ctx->noenum) {
ctx->p += print_utype(type, ctx->p);
} else {
ptf(ctx, type);
}
if (type != 0) {
print_char(',');
print_name(ctx, name, len);
ud.ttl = td->ttl;
ud.type = type;
ud.member = p;
pf(ctx, &ud);
}
}
void flatcc_json_printer_union_table(flatcc_json_printer_t *ctx,
flatcc_json_printer_union_descriptor_t *ud,
flatcc_json_printer_table_f pf)
{
print_table_object(ctx, read_uoffset_ptr(ud->member), ud->ttl, pf);
}
void flatcc_json_printer_union_struct(flatcc_json_printer_t *ctx,
flatcc_json_printer_union_descriptor_t *ud,
flatcc_json_printer_struct_f pf)
{
print_start('{');
pf(ctx, read_uoffset_ptr(ud->member));
print_end('}');
}
void flatcc_json_printer_union_string(flatcc_json_printer_t *ctx,
flatcc_json_printer_union_descriptor_t *ud)
{
print_string_object(ctx, read_uoffset_ptr(ud->member));
}
void flatcc_json_printer_embedded_struct_field(flatcc_json_printer_t *ctx,
int index, const void *p, size_t offset,
const char *name, size_t len,
flatcc_json_printer_struct_f pf)
{
if (index) {
print_char(',');
}
print_name(ctx, name, len);
print_start('{');
pf(ctx, (uint8_t *)p + offset);
print_end('}');
}
void flatcc_json_printer_embedded_struct_array_field(flatcc_json_printer_t *ctx,
int index, const void *p, size_t offset,
const char *name, size_t len,
size_t size, size_t count,
flatcc_json_printer_struct_f pf)
{
size_t i;
if (index) {
print_char(',');
}
print_name(ctx, name, len);
print_start('[');
for (i = 0; i < count; ++i) {
if (i > 0) {
print_char(',');
}
print_start('{'); \
pf(ctx, (uint8_t *)p + offset + i * size);
print_end('}');
}
print_end(']');
}
void flatcc_json_printer_struct_field(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len,
flatcc_json_printer_struct_f *pf)
{
const void *p = get_field_ptr(td, id);
if (p) {
if (td->count++) {
print_char(',');
}
print_name(ctx, name, len);
print_start('{');
pf(ctx, p);
print_end('}');
}
}
/*
* Make sure the buffer identifier is valid before assuming the rest of
* the buffer is sane.
* NOTE: this won't work with type hashes because these can contain
* nulls in the fid string. In this case use null as fid to disable
* check.
*/
static int accept_header(flatcc_json_printer_t * ctx,
const void *buf, size_t bufsiz, const char *fid)
{
flatbuffers_thash_t id, id2 = 0;
if (buf == 0 || bufsiz < offset_size + FLATBUFFERS_IDENTIFIER_SIZE) {
RAISE_ERROR(bad_input);
FLATCC_ASSERT(0 && "buffer header too small");
return 0;
}
if (fid != 0) {
id2 = flatbuffers_type_hash_from_string(fid);
id = __flatbuffers_thash_read_from_pe((uint8_t *)buf + offset_size);
if (!(id2 == 0 || id == id2)) {
RAISE_ERROR(bad_input);
FLATCC_ASSERT(0 && "identifier mismatch");
return 0;
}
}
return 1;
}
int flatcc_json_printer_struct_as_root(flatcc_json_printer_t *ctx,
const void *buf, size_t bufsiz, const char *fid,
flatcc_json_printer_struct_f *pf)
{
if (!accept_header(ctx, buf, bufsiz, fid)) {
return -1;
}
print_start('{');
pf(ctx, read_uoffset_ptr(buf));
print_end('}');
print_last_nl();
return flatcc_json_printer_get_error(ctx) ? -1 : (int)ctx->total + (int)(ctx->p - ctx->buf);
}
int flatcc_json_printer_table_as_root(flatcc_json_printer_t *ctx,
const void *buf, size_t bufsiz, const char *fid, flatcc_json_printer_table_f *pf)
{
if (!accept_header(ctx, buf, bufsiz, fid)) {
return -1;
}
print_table_object(ctx, read_uoffset_ptr(buf), FLATCC_JSON_PRINT_MAX_LEVELS, pf);
print_last_nl();
return flatcc_json_printer_get_error(ctx) ? -1 : (int)ctx->total + (int)(ctx->p - ctx->buf);
}
void flatcc_json_printer_struct_as_nested_root(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len,
const char *fid,
flatcc_json_printer_struct_f *pf)
{
const uoffset_t *buf;
uoffset_t bufsiz;
if (0 == (buf = get_field_ptr(td, id))) {
return;
}
buf = (const uoffset_t *)((size_t)buf + __flatbuffers_uoffset_read_from_pe(buf));
bufsiz = __flatbuffers_uoffset_read_from_pe(buf);
if (!accept_header(ctx, buf, bufsiz, fid)) {
return;
}
if (td->count++) {
print_char(',');
}
print_name(ctx, name, len);
print_start('{');
pf(ctx, read_uoffset_ptr(buf));
print_end('}');
}
void flatcc_json_printer_table_as_nested_root(flatcc_json_printer_t *ctx,
flatcc_json_printer_table_descriptor_t *td,
int id, const char *name, size_t len,
const char *fid,
flatcc_json_printer_table_f pf)
{
const uoffset_t *buf;
uoffset_t bufsiz;
if (0 == (buf = get_field_ptr(td, id))) {
return;
}
buf = (const uoffset_t *)((size_t)buf + __flatbuffers_uoffset_read_from_pe(buf));
bufsiz = __flatbuffers_uoffset_read_from_pe(buf);
++buf;
if (!accept_header(ctx, buf, bufsiz, fid)) {
return;
}
if (td->count++) {
print_char(',');
}
print_name(ctx, name, len);
print_table_object(ctx, read_uoffset_ptr(buf), td->ttl, pf);
}
static void __flatcc_json_printer_flush(flatcc_json_printer_t *ctx, int all)
{
if (!all && ctx->p >= ctx->pflush) {
size_t spill = (size_t)(ctx->p - ctx->pflush);
fwrite(ctx->buf, ctx->flush_size, 1, ctx->fp);
memcpy(ctx->buf, ctx->buf + ctx->flush_size, spill);
ctx->p = ctx->buf + spill;
ctx->total += ctx->flush_size;
} else {
size_t len = (size_t)(ctx->p - ctx->buf);
fwrite(ctx->buf, len, 1, ctx->fp);
ctx->p = ctx->buf;
ctx->total += len;
}
*ctx->p = '\0';
}
int flatcc_json_printer_init(flatcc_json_printer_t *ctx, void *fp)
{
memset(ctx, 0, sizeof(*ctx));
ctx->fp = fp ? fp : stdout;
ctx->flush = __flatcc_json_printer_flush;
if (!(ctx->buf = FLATCC_JSON_PRINTER_ALLOC(FLATCC_JSON_PRINT_BUFFER_SIZE))) {
return -1;
}
ctx->own_buffer = 1;
ctx->size = FLATCC_JSON_PRINT_BUFFER_SIZE;
ctx->flush_size = FLATCC_JSON_PRINT_FLUSH_SIZE;
ctx->p = ctx->buf;
ctx->pflush = ctx->buf + ctx->flush_size;
/*
* Make sure we have space for primitive operations such as printing numbers
* without having to flush.
*/
FLATCC_ASSERT(ctx->flush_size + FLATCC_JSON_PRINT_RESERVE <= ctx->size);
return 0;
}
static void __flatcc_json_printer_flush_buffer(flatcc_json_printer_t *ctx, int all)
{
(void)all;
if (ctx->p >= ctx->pflush) {
RAISE_ERROR(overflow);
ctx->total += (size_t)(ctx->p - ctx->buf);
ctx->p = ctx->buf;
}
*ctx->p = '\0';
}
int flatcc_json_printer_init_buffer(flatcc_json_printer_t *ctx, char *buffer, size_t buffer_size)
{
FLATCC_ASSERT(buffer_size >= FLATCC_JSON_PRINT_RESERVE);
if (buffer_size < FLATCC_JSON_PRINT_RESERVE) {
return -1;
}
memset(ctx, 0, sizeof(*ctx));
ctx->buf = buffer;
ctx->size = buffer_size;
ctx->flush_size = ctx->size - FLATCC_JSON_PRINT_RESERVE;
ctx->p = ctx->buf;
ctx->pflush = ctx->buf + ctx->flush_size;
ctx->flush = __flatcc_json_printer_flush_buffer;
return 0;
}
static void __flatcc_json_printer_flush_dynamic_buffer(flatcc_json_printer_t *ctx, int all)
{
size_t len = (size_t)(ctx->p - ctx->buf);
char *p;
(void)all;
*ctx->p = '\0';
if (ctx->p < ctx->pflush) {
return;
}
p = FLATCC_JSON_PRINTER_REALLOC(ctx->buf, ctx->size * 2);
if (!p) {
RAISE_ERROR(overflow);
ctx->total += len;
ctx->p = ctx->buf;
} else {
ctx->size *= 2;
ctx->flush_size = ctx->size - FLATCC_JSON_PRINT_RESERVE;
ctx->buf = p;
ctx->p = p + len;
ctx->pflush = p + ctx->flush_size;
}
*ctx->p = '\0';
}
int flatcc_json_printer_init_dynamic_buffer(flatcc_json_printer_t *ctx, size_t buffer_size)
{
if (buffer_size == 0) {
buffer_size = FLATCC_JSON_PRINT_DYN_BUFFER_SIZE;
}
if (buffer_size < FLATCC_JSON_PRINT_RESERVE) {
buffer_size = FLATCC_JSON_PRINT_RESERVE;
}
memset(ctx, 0, sizeof(*ctx));
ctx->buf = FLATCC_JSON_PRINTER_ALLOC(buffer_size);
ctx->own_buffer = 1;
ctx->size = buffer_size;
ctx->flush_size = ctx->size - FLATCC_JSON_PRINT_RESERVE;
ctx->p = ctx->buf;
ctx->pflush = ctx->buf + ctx->flush_size;
ctx->flush = __flatcc_json_printer_flush_dynamic_buffer;
if (!ctx->buf) {
RAISE_ERROR(overflow);
return -1;
}
return 0;
}
void *flatcc_json_printer_get_buffer(flatcc_json_printer_t *ctx, size_t *buffer_size)
{
ctx->flush(ctx, 0);
if (buffer_size) {
*buffer_size = (size_t)(ctx->p - ctx->buf);
}
return ctx->buf;
}
void *flatcc_json_printer_finalize_dynamic_buffer(flatcc_json_printer_t *ctx, size_t *buffer_size)
{
void *buffer;
buffer = flatcc_json_printer_get_buffer(ctx, buffer_size);
memset(ctx, 0, sizeof(*ctx));
return buffer;
}
void flatcc_json_printer_clear(flatcc_json_printer_t *ctx)
{
if (ctx->own_buffer && ctx->buf) {
FLATCC_JSON_PRINTER_FREE(ctx->buf);
}
memset(ctx, 0, sizeof(*ctx));
}