12#define __STDC_FORMAT_MACROS 1
16const char *
json_cvsid =
"$Id: json.cpp 5469 2023-03-15 20:00:35Z dpgilbert $"
29 snprintf(msg,
sizeof(msg),
"json.cpp(%d): Assertion failed: %s", line, expr);
30 throw std::logic_error(msg);
33#define jassert(expr) (!(expr) ? jassert_failed(__LINE__, #expr) : (void)0)
43 bool prev_underscore =
false;
44 size_t i_sz = strlen(str);
47 std::string res(i_sz,
' ');
48 const char * cp = str;
49 static const int lower_alpha_off =
'a' -
'A';
54 if ((
'0' <= c && c <=
'9') || (
'a' <= c && c <=
'z')) {
56 prev_underscore =
false;
57 }
else if (
'A' <= c && c <=
'Z') {
58 res[o_ind++] = c + lower_alpha_off;
59 prev_underscore =
false;
61 if ((o_ind > 0) && ! prev_underscore) {
63 prev_underscore =
true;
69 else if (res[o_ind - 1] ==
'_')
88: m_js(base.m_js), m_path(base.m_path)
95: m_js(base.m_js), m_path(base.m_path)
97 jassert(0 <= index && index < 10000);
102: m_js(base.m_js), m_path(base.m_path)
104 int n = (int)
m_path.size(), i;
105 for (i = n; --i >= 0; ) {
106 std::string & base_key =
m_path[i].key;
107 if (base_key.empty())
109 base_key += key_suffix;
121 m_js.set_bool(m_path, value);
126 m_js.set_int64(m_path, (int64_t)value);
131 m_js.set_uint64(m_path, (uint64_t)value);
136 operator=((
long long)value);
141 operator=((
unsigned long long)value);
146 operator=((
long long)value);
151 operator=((
unsigned long long)value);
156 m_js.set_cstring(m_path, value);
161 m_js.set_string(m_path, value);
167 operator=((
unsigned long long)value_lo);
169 m_js.set_uint128(m_path, value_hi, value_lo);
176 operator=((
unsigned long long)value);
184 return set_if_safe_uint64(value_lo);
196 operator=((
unsigned long long)value);
201 snprintf(
s,
sizeof(
s),
"%" PRIu64, value);
202 with_suffix(
"_s") =
s;
207 if (!m_js.m_verbose && !value_hi)
208 set_unsafe_uint64(value_lo);
211 m_js.m_uint128_output =
true;
215 ref le = with_suffix(
"_le");
216 for (
int i = 0; i < 8; i++) {
217 uint64_t v = (value_lo >> (i << 3));
222 for (
int i = 0; i < 8; i++) {
223 uint64_t v = value_hi >> (i << 3);
226 le[8 + i] = v & 0xff;
240 jassert(kv.keystr && *kv.keystr);
241 switch (kv.value.type) {
242 default:
operator[](kv.keystr) = kv.value;
break;
271 m_use_map(sorted && node_p->type ==
nt_object)
280 return (m_key_iter == m_node_p->key2index.end());
282 return (m_child_idx >= m_node_p->childs.size());
302 return m_node_p->
childs[m_key_iter->second].get();
304 return m_node_p->childs[m_child_idx].get();
310 for (
unsigned i = 0; i < path.size(); i++) {
312 if (!pi.
key.empty()) {
323 p2 = p->
childs[ni->second].get();
328 p->
childs.push_back(std::unique_ptr<node>(p2 =
new node(pi.
key)));
428 for (i = 0;
s[i]; i++) {
429 unsigned char c =
s[i];
431 if ((c & 0xc0) == 0x80) {
440 else if ((c & 0xe0) == 0xc0 && (c & 0x1f))
442 else if ((c & 0xf0) == 0xe0 && (c & 0x0f))
444 else if ((c & 0xf8) == 0xf0 && (c & 0x07))
459 for (
int i = 0;
s[i]; i++) {
461 if (c ==
'"' || c ==
'\\')
463 else if (c ==
'\t') {
464 putc(
'\\', f); c =
't';
468 if ( (
' ' <= c && c <=
'~')
469 || ((c & 0x80) && (utf8_rc >= -1 ? utf8_rc : (utf8_rc =
check_utf8(
s + i))) == -1))
474 fprintf(f,
"\\\\x%02x", (
unsigned char)c);
483 bool need =
false;
char quotes =
'\'';
484 for (
int i = 0;
s[i]; i++) {
486 if (!(
' ' <= c && c <=
'~'))
488 if ( (
'0' <= c && c <=
'9') || (
'A' <= c && c <=
'Z')
489 || (
'a' <= c && c <=
'z') || c ==
'_' )
495 else if (c ==
' ' && (
s[i-1] ==
':' ||
s[i+1] ==
'#'))
497 else if ((c ==
' ' || c ==
':') && !
s[i+1])
504 "[0-9]+[,0-9]*(\\.[0-9]*)?([eE][-+]?[0-9]+)?|"
506 "[Ff][Aa][Ll][Ss][Ee]|[Tt][Rr][Uu][Ee]|[Nn][Oo]|[Yy][Ee][Ss]|"
520 putc((is_obj ?
'{' :
'['), f);
527 fprintf(f,
"\n%*s", (level + 1) * 2,
"");
528 const node * p2 = *it;
537 fprintf(f,
"\"%s\":%s", p2->
key.c_str(), (pretty ?
" " :
""));
544 fprintf(f,
"\n%*s", level * 2,
"");
546 putc((is_obj ?
'}' :
']'), f);
550 fputs((p->
intval ?
"true" :
"false"), f);
554 fprintf(f,
"%" PRId64, (int64_t)p->
intval);
558 fprintf(f,
"%" PRIu64, p->
intval);
577 int level_a,
bool cont)
587 int spaces = (cont ? 1 : (is_obj ? level_o : level_a) * 2);
589 fprintf(f,
"%*s", spaces,
"");
590 const node * p2 = *it;
599 fprintf(f,
"%s:", p2->
key.c_str());
603 print_yaml(f, pretty, sorted, p2, (is_obj ? level_o : level_a) + 1,
604 (is_obj ? level_o + (pretty ? 1 : 0) : level_a + 1), !is_obj);
610 fputs((is_obj ?
"{}\n" :
"[]\n"), f);
615 fputs((p->
intval ?
" true\n" :
" false\n"), f);
619 fprintf(f,
" %" PRId64
"\n", (int64_t)p->
intval);
623 fprintf(f,
" %" PRIu64
"\n", p->
intval);
637 case '\'': fprintf(f,
"'%s'", p->
strval.c_str());
break;
638 case 0: fputs(p->
strval.c_str(), f);
break;
654 fprintf(f,
"%s%s%s;\n", path.c_str(), assign, (is_obj ?
"{}" :
"[]"));
656 unsigned len = path.size();
658 const node * p2 = *it;
660 char buf[10]; snprintf(buf,
sizeof(buf),
"[%u]", it.array_index());
664 path +=
'.'; path += p2->
key;
669 fprintf(f,
"%s%snull;\n", path.c_str(), assign);
681 fprintf(f,
"%s%s%s;\n", path.c_str(), assign, (p->
intval ?
"true" :
"false"));
685 fprintf(f,
"%s%s%" PRId64
";\n", path.c_str(), assign, (int64_t)p->
intval);
689 fprintf(f,
"%s%s%" PRIu64
";\n", path.c_str(), assign, p->
intval);
695 fprintf(f,
"%s%s%s;\n", path.c_str(), assign,
701 fprintf(f,
"%s%s", path.c_str(), assign);
727 std::string path(
"json");
unsigned array_index() const
const node * operator*() const
const_iterator(const node *node_p, bool sorted)
keymap::const_iterator m_key_iter
Reference to a JSON element.
void set_uint128(uint64_t value_hi, uint64_t value_lo)
void set_unsafe_uint128(uint64_t value_hi, uint64_t value_lo)
void operator+=(std::initializer_list< initlist_key_value_pair > ilist)
Braced-init-list support for nested objects.
void set_unsafe_le128(const void *pvalue)
void operator=(bool value)
bool set_if_safe_le128(const void *pvalue)
void set_unsafe_uint64(uint64_t value)
bool set_if_safe_uint64(uint64_t value)
bool set_if_safe_uint128(uint64_t value_hi, uint64_t value_lo)
Create and print JSON output.
static void print_flat(FILE *f, const char *assign, bool sorted, const node *p, std::string &path)
std::vector< node_info > node_path
void set_uint64(const node_path &path, uint64_t value)
void set_int64(const node_path &path, int64_t value)
void set_string(const node_path &path, const std::string &value)
void set_initlist_value(const node_path &path, const initlist_value &value)
static std::string str2key(const char *str)
Replace space and non-alphanumerics with '_', upper to lower case.
void set_bool(const node_path &path, bool value)
void set_cstring(const node_path &path, const char *value)
static void print_json(FILE *f, bool pretty, bool sorted, const node *p, int level)
static bool is_safe_uint(unsigned long long value)
Return true if value is a safe JSON integer.
static void print_yaml(FILE *f, bool pretty, bool sorted, const node *p, int level_o, int level_a, bool cont)
node * find_or_create_node(const node_path &path, node_type type)
ref operator[](const char *keystr)
Return reference to element of top level object.
void set_uint128(const node_path &path, uint64_t value_hi, uint64_t value_lo)
void print(FILE *f, const print_options &options) const
Print JSON tree to a file.
Wrapper class for POSIX regex(3) or std::regex Supports copy & assignment and is compatible with STL ...
bool full_match(const char *str) const
Return true if full string matches pattern.
static void jassert_failed(int line, const char *expr)
static char yaml_string_needs_quotes(const char *s)
static void print_quoted_string(FILE *f, const char *s)
static int check_utf8(const char *s)
static uint64_t sg_get_unaligned_le64(const void *p)
std::vector< std::unique_ptr< node > > childs
const char * uint128_hilo_to_str(char *str, int strsize, uint64_t value_hi, uint64_t value_lo)