20 std::vector<char> ret;
21 char const *ptr = in.data();
22 char const *end = ptr + in.size();
23 ret.reserve(end - ptr + 10);
25 int c = (
unsigned char)*ptr;
28 case '\"': ret.push_back(
'\\'); ret.push_back(
'\"');
break;
29 case '\\': ret.push_back(
'\\'); ret.push_back(
'\\');
break;
30 case '\b': ret.push_back(
'\\'); ret.push_back(
'b');
break;
31 case '\f': ret.push_back(
'\\'); ret.push_back(
'f');
break;
32 case '\n': ret.push_back(
'\\'); ret.push_back(
'n');
break;
33 case '\r': ret.push_back(
'\\'); ret.push_back(
'r');
break;
34 case '\t': ret.push_back(
'\\'); ret.push_back(
't');
break;
36 if (c >= 0x20 && c < 0x7f) {
40 if ((c & 0xe0) == 0xc0 && ptr < end) {
41 if ((ptr[0] & 0xc0) == 0x80) {
42 int d = (
unsigned char)ptr[0];
43 u = ((c & 0x1f) << 6) | (d & 0x3f);
45 }
else if ((c & 0xf0) == 0xe0 && ptr + 1 < end) {
46 if ((ptr[0] & 0xc0) == 0x80 && (ptr[1] & 0xc0) == 0x80) {
47 int d = (
unsigned char)ptr[0];
48 int e = (
unsigned char)ptr[1];
49 u = ((c & 0x0f) << 12) | ((d & 0x3f) << 6) | (e & 0x3f);
51 }
else if ((c & 0xf8) == 0xf0 && ptr + 2 < end) {
52 if ((ptr[0] & 0xc0) == 0x80 && (ptr[1] & 0xc0) == 0x80 && (ptr[2] & 0xc0) == 0x80) {
53 int d = (
unsigned char)ptr[0];
54 int e = (
unsigned char)ptr[1];
55 int f = (
unsigned char)ptr[2];
56 u = ((c & 0x0f) << 18) | ((d & 0x3f) << 12) | ((e & 0x3f) << 6) | (f & 0x3f);
61 if (u >= 0x10000 && u < 0x110000) {
62 uint16_t h = (u - 0x10000) / 0x400 + 0xd800;
63 uint16_t l = (u - 0x10000) % 0x400 + 0xdc00;
64 sprintf(tmp,
"\\u%04X\\u%04X", h, l);
65 ret.insert(ret.end(), tmp, tmp + 12);
67 sprintf(tmp,
"\\u%04X", u);
68 ret.insert(ret.end(), tmp, tmp + 6);
92 static const double tbl[] = {
93 1e+00, 1e+01, 1e+02, 1e+03, 1e+04, 1e+05, 1e+06,
94 1e+07, 1e+08, 1e+09, 1e+10, 1e+11, 1e+12, 1e+13,
97 if (exp >= 0 && exp <
static_cast<int>(
sizeof tbl /
sizeof *tbl))
99 if (exp <= 0 && exp > -
static_cast<int>(
sizeof tbl /
sizeof *tbl))
100 return 1.0 / tbl[-exp];
102 return std::pow(10.0, exp);
120 static double my_strtod(
const char *nptr,
char **endptr)
122 const char *s = nptr;
124 bool saw_digit =
false;
127 bool exp_sign =
false;
131 while (std::isspace((
unsigned char)*s)) ++s;
134 if (*s ==
'+' || *s ==
'-') {
135 if (*s ==
'-') sign =
true;
140 while (std::isdigit((
unsigned char)*s)) {
142 value = value * 10.0 + (*s -
'0');
149 while (std::isdigit((
unsigned char)*s)) {
151 value = value * 10.0 + (*s -
'0');
159 if (endptr) *endptr =
const_cast<char *
>(nptr);
164 if (*s ==
'e' || *s ==
'E') {
166 const char *exp_start = s;
167 if (*s ==
'+' || *s ==
'-') {
168 if (*s ==
'-') exp_sign =
true;
171 if (std::isdigit((
unsigned char)*s)) {
172 while (std::isdigit((
unsigned char)*s)) {
173 exp_val = exp_val * 10 + (*s -
'0');
186 int total_exp = exp_val - frac_digits;
187 if (total_exp != 0) {
197 if (!std::isfinite(value)) {
199 value = sign ? -HUGE_VAL : HUGE_VAL;
200 }
else if (value == 0.0 && saw_digit && total_exp != 0) {
205 if (endptr) *endptr =
const_cast<char *
>(s);
212 bool trim_zeros =
true;
215 if (std::isnan(val)) {
221 if (std::isinf(val)) {
223 bool sign = std::signbit(val);
242 double intval = floor(val);
247 ptr = end = (
char *)alloca(precision + 10) + 5;
254 ptr = end = (
char *)alloca(intlen + precision + 10) + intlen + 5;
262 while (v > 0 && v < 1) {
271 for (
int i = 0; i < precision - e; i++) {
280 int r = std::min(e, precision);
288 while (i < precision) {
293 *end++ = (char)m +
'0';
301 intval += floor(val + 0.5);
315 for (
int i = 0; i < intlen; i++) {
318 *--ptr = (char)((t - u) * 10 + 0.49) +
'0';
329 if (trim_zeros && dot) {
343 return std::string(ptr, end - ptr);
371 static std::string
to_stdstr(std::vector<char>
const &vec)
374 char const *begin = &vec[0];
375 char const *end = begin + vec.size();
376 return std::string(begin, end);
378 return std::string();
383 char const *ptr = begin;
385 if (std::isspace((
unsigned char)*ptr)) {
392 while (ptr < end && *ptr !=
'\r' && *ptr !=
'\n') {
399 while (ptr + 1 < end) {
400 if (*ptr ==
'*' && ptr[1] ==
'/') {
416 char const *ptr = begin;
418 std::vector<char> vec;
420 if (!isalnum((
unsigned char)*ptr) && *ptr !=
'_')
break;
424 if (ptr > begin && !vec.empty()) {
435 char const *ptr = begin;
438 std::vector<char> vec;
443 if (p + 1 < end && *p ==
'-') {
447 if (p + 1 < end && *p ==
'0' && (p[1] ==
'x' || p[1] ==
'X')) {
449 while (p < end && isxdigit((
unsigned char)*p)) {
454 long long v = strtoll(vec.data(),
nullptr, 16);
455 *out = sign ? -v : v;
463 if (p < end && *p ==
'-') {
467 while (p < end && isalpha((
unsigned char)*p)) {
472 if (strcmp(vec.data(),
"Infinity") == 0) {
474 *out = sign ? -INFINITY : INFINITY;
475 }
else if (strcmp(vec.data(),
"NaN") == 0) {
486 if (isdigit((
unsigned char)c) || c ==
'.' || c ==
'+' || c ==
'-' || c ==
'e' || c ==
'E') {
506 char const *ptr = begin;
510 std::vector<char> vec;
516 }
else if (*ptr ==
'\\') {
519 auto push = [&](
char c){ vec.push_back(c); ptr++;};
521 case 'b': push(
'\b');
break;
522 case 'n': push(
'\n');
break;
523 case 'r': push(
'\r');
break;
524 case 'f': push(
'\f');
break;
525 case 't': push(
'\t');
break;
526 case 'v': push(
'\v');
break;
541 uint32_t unicode = (uint32_t)strtol(tmp,
nullptr, 16);
542 if (unicode >= 0xd800 && unicode < 0xdc00) {
543 if (ptr + 5 < end && ptr[0] ==
'\\' && ptr[1] ==
'u') {
548 uint32_t surrogate = (uint32_t)strtol(tmp,
nullptr, 16);
549 if (surrogate >= 0xdc00 && surrogate < 0xe000) {
551 unicode = ((unicode - 0xd800) << 10) + (surrogate - 0xdc00) + 0x10000;
555 if (unicode < (1 << 7)) {
556 vec.push_back(unicode & 0x7f);
557 }
else if (unicode < (1 << 11)) {
558 vec.push_back(((unicode >> 6) & 0x1f) | 0xc0);
559 vec.push_back((unicode & 0x3f) | 0x80);
560 }
else if (unicode < (1 << 16)) {
561 vec.push_back(((unicode >> 12) & 0x0f) | 0xe0);
562 vec.push_back(((unicode >> 6) & 0x3f) | 0x80);
563 vec.push_back((unicode & 0x3f) | 0x80);
564 }
else if (unicode < (1 << 21)) {
565 vec.push_back(((unicode >> 18) & 0x07) | 0xf0);
566 vec.push_back(((unicode >> 12) & 0x3f) | 0x80);
567 vec.push_back(((unicode >> 6) & 0x3f) | 0x80);
568 vec.push_back((unicode & 0x3f) | 0x80);
589 char const *
ptr =
nullptr;
599 char const *
end =
nullptr;
600 char const *
ptr =
nullptr;
678 void parse(
char const *begin,
char const *end)
687 void parse(std::string_view
const &sv)
689 parse(sv.data(), sv.data() + sv.size());
692 void parse(
char const *ptr,
int len = -1)
697 parse(ptr, ptr + len);
718 if (
key[n - 1] ==
'{') {
719 key =
key.substr(0, n - 1);
742 if (
key[n - 1] ==
'[') {
743 key =
key.substr(0, n - 1);
776 char const *p =
d.
ptr++;
786 char const *p =
d.
ptr++;
795 if (*
d.
ptr ==
'\"') {
825 if (
d.
ptr[n] ==
':') {
841 if (isalpha((
unsigned char)*
d.
ptr)) {
865 if (
d.
ptr[n] ==
':') {
883 Reader(
char const *begin,
char const *end)
1075 for (std::string
const &s :
d.
depth) {
1093 bool match(
char const *
path, std::vector<std::string> *vals =
nullptr,
bool clear =
true)
const
1095 if (vals && clear) {
1100 for (i = 0; i <
d.
depth.size(); i++) {
1101 std::string
const &s =
d.
depth[i];
1102 if (s.empty())
break;
1103 if (
path[0] ==
'*' &&
path[1] ==
'*' &&
path[2] == 0) {
1106 if (
path[0] ==
'*' && s.c_str()[s.size() - 1] ==
'{') {
1109 if (i + 1 ==
d.
depth.size()) {
1112 while (i <
d.
depth.size()) {
1125 }
else if (
path[1] ==
'{') {
1130 if (strncmp(
path, s.c_str(), s.size()) != 0)
return false;
1133 if (
path[0] ==
'*' &&
path[1] ==
'*' &&
path[2] == 0) {
1136 if (
path[0] ==
'*') {
1151 vals->push_back(
string());
1186 for (
size_t i = 0; i < n; i++) {
1199 print(p, strlen(p));
1204 print(s.c_str(), s.size());
1225 size_t n =
stack.size() - 1;
1226 for (
size_t i = 0; i < n; i++) {
1249 print(buf.data(), buf.size());
1254 bool print_value(std::string
const &name, std::function<
bool ()>
const &fn)
1265 void print_object(std::string
const &name = {}, std::function<void ()>
const &fn = {})
1276 void print_array(std::string
const &name = {}, std::function<void ()>
const &fn = {})
1290 if (!
stack.empty()) {
1297 Writer(std::function<
void (
char const *p,
int n)> fn = {})
1327 if (!
stack.empty()) {
1328 if (
stack.back() > 0) {
1332 if (
stack.size() > 1) {
1336 if (!name.empty()) {
1356 void object(std::string
const &name, std::function<
void ()>
const &fn)
1372 void array(std::string
const &name, std::function<
void ()>
const &fn)
1377 bool number(std::string
const &name,
double v)
1389 void string(std::string
const &name, std::string
const &s)
1431 constexpr std::nullptr_t
null =
nullptr;
1436 typedef std::variant<null_t, bool, double, std::string, _Object, Array>
Variant;
1438 std::vector<Variant>
a;
1455 template <
typename T> T &
get(
size_t i)
1457 assert(i <
a.size());
1458 return std::get<T>(
a[i]);
1460 template <
typename T> T
const &
get(
size_t i)
const
1462 assert(i <
a.size());
1463 return std::get<T>(
a[i]);
1510 if (!std::holds_alternative<_Object>(v)) {
1513 p = &std::get<_Object>(v);
1517 return p ?
p->size() : 0;
1526 for (
auto &kv : *
p) {
1527 if (kv.key == key) {
1536 return const_cast<Object *
>(
this)->
find(key);
1548 template <
typename T> T
const &
get(std::string
const &key)
const
1552 return std::get<T>(*v);
1557 return p->back().value;
1563 return std::holds_alternative<null_t>(v);
1567 return std::holds_alternative<bool>(v);
1571 return std::holds_alternative<double>(v);
1575 return std::holds_alternative<std::string>(v);
1579 return std::holds_alternative<_Object>(v);
1583 return std::holds_alternative<Array>(v);
1587 return std::holds_alternative<double>(v) && std::isnan(std::get<double>(v));
1591 return std::holds_alternative<double>(v) && std::isinf(std::get<double>(v));
1599 if (!std::holds_alternative<Array>(v)) {
1602 return std::get<Array>(v);
1606 if (!std::holds_alternative<_Object>(v)) {
1609 return Object(std::get<_Object>(v));
1616 }
else if (reader.
isfalse()) {
1618 }
else if (reader.
istrue()) {
Definition: jstream.h:364
bool is_end_object() const
Definition: jstream.h:960
int depth() const
Definition: jstream.h:1067
bool isarray() const
Definition: jstream.h:1062
Reader(char const *begin, char const *end)
Definition: jstream.h:883
void allow_ambiguous_comma(bool allow)
Definition: jstream.h:895
void allow_hexadicimal(bool allow)
Definition: jstream.h:903
bool isnull() const
Definition: jstream.h:1032
bool is_end_array() const
Definition: jstream.h:970
ParserData d
Definition: jstream.h:617
bool has_error() const
Definition: jstream.h:945
bool pop_state()
Definition: jstream.h:650
static std::string to_stdstr(std::vector< char > const &vec)
Definition: jstream.h:371
bool isobject() const
Definition: jstream.h:975
bool match_start_object(char const *path) const
Definition: jstream.h:1158
bool match_end_array(char const *path) const
Definition: jstream.h:1173
double number() const
Definition: jstream.h:1057
void parse(char const *ptr, int len=-1)
Definition: jstream.h:692
bool isfalse() const
Definition: jstream.h:1037
void allow_comment(bool allow)
Definition: jstream.h:891
void hold()
Definition: jstream.h:915
bool istrue() const
Definition: jstream.h:1042
std::string path() const
Definition: jstream.h:1072
bool match_start_array(char const *path) const
Definition: jstream.h:1168
void push_error(std::string const &what)
Definition: jstream.h:619
std::vector< Error > const & errors() const
Definition: jstream.h:950
std::string_view raw()
Definition: jstream.h:1084
std::string key() const
Definition: jstream.h:1009
bool is_start_object() const
Definition: jstream.h:955
int scan_space(char const *begin, char const *end)
Definition: jstream.h:381
void reset()
Definition: jstream.h:911
int parse_number(char const *begin, char const *end, double *out)
Definition: jstream.h:432
bool isvalue() const
Definition: jstream.h:996
Reader(char const *ptr, int len=-1)
Definition: jstream.h:887
void parse(std::string_view const &sv)
Definition: jstream.h:687
void allow_unquoted_key(bool allow)
Definition: jstream.h:899
void push_state(StateItem s)
Definition: jstream.h:628
std::string string() const
Definition: jstream.h:1014
bool match_end_object(char const *path) const
Definition: jstream.h:1163
Reader(std::string_view const &sv)
Definition: jstream.h:879
bool _internal_next()
Definition: jstream.h:700
bool is_start_array() const
Definition: jstream.h:965
StateType state() const
Definition: jstream.h:940
int parse_symbol(char const *begin, char const *end, std::string *out)
Definition: jstream.h:414
bool isstring() const
Definition: jstream.h:1052
bool match(char const *path, std::vector< std::string > *vals=nullptr, bool clear=true) const
Definition: jstream.h:1093
bool isnumber() const
Definition: jstream.h:1047
void nest()
Definition: jstream.h:919
StateType symbol() const
Definition: jstream.h:1019
bool next()
Definition: jstream.h:923
void parse(char const *begin, char const *end)
Definition: jstream.h:678
int parse_string(char const *begin, char const *end, std::string *out)
Definition: jstream.h:504
void allow_special_constant(bool allow)
Definition: jstream.h:907
Definition: jstream.h:1179
void end_block()
Definition: jstream.h:1287
bool allow_nan_
Definition: jstream.h:1212
void print_string(std::string const &s)
Definition: jstream.h:1243
void array(std::string const &name, std::function< void()> const &fn)
Definition: jstream.h:1372
void boolean(std::string const &name, bool b)
Definition: jstream.h:1419
void symbol(std::string const &name, StateType v)
Definition: jstream.h:1402
void object(std::string const &name, std::function< void()> const &fn)
Definition: jstream.h:1356
std::vector< int > stack
Definition: jstream.h:1207
void print_indent()
Definition: jstream.h:1221
void string(std::string const &s)
Definition: jstream.h:1397
void start_object(std::string const &name={})
Definition: jstream.h:1345
void allow_nan(bool allow)
Definition: jstream.h:1320
void string(std::string const &name, std::string const &s)
Definition: jstream.h:1389
Writer(std::function< void(char const *p, int n)> fn={})
Definition: jstream.h:1297
bool number(std::string const &name, double v)
Definition: jstream.h:1377
void print(char c)
Definition: jstream.h:1192
bool print_value(std::string const &name, std::function< bool()> const &fn)
Definition: jstream.h:1254
void end_array()
Definition: jstream.h:1366
void number(double v)
Definition: jstream.h:1384
bool print_number(double v)
Definition: jstream.h:1232
void print(std::string const &s)
Definition: jstream.h:1202
void print_name(std::string const &name)
Definition: jstream.h:1325
void enable_newline(bool enabled)
Definition: jstream.h:1315
void print_array(std::string const &name={}, std::function< void()> const &fn={})
Definition: jstream.h:1276
void print(char const *p)
Definition: jstream.h:1197
bool enable_indent_
Definition: jstream.h:1210
~Writer()
Definition: jstream.h:1303
void start_array(std::string const &name={})
Definition: jstream.h:1361
bool enable_newline_
Definition: jstream.h:1211
void end_object()
Definition: jstream.h:1350
void print(char const *p, int n)
Definition: jstream.h:1181
std::function< void(char const *p, int n)> output_fn
Definition: jstream.h:1208
void print_newline()
Definition: jstream.h:1214
void print_object(std::string const &name={}, std::function< void()> const &fn={})
Definition: jstream.h:1265
void enable_indent(bool enabled)
Definition: jstream.h:1310
static std::string format_double(double val, bool allow_nan)
Definition: jstream.h:209
static double pow10_int(int exp)
Return 10 raised to an integer power.
Definition: jstream.h:89
static double my_strtod(const char *nptr, char **endptr)
Locale‑independent strtod clone.
Definition: jstream.h:120
static bool is_infinite(Variant const &v)
Definition: jstream.h:1589
static Variant var(jstream::Reader const &reader)
Definition: jstream.h:1612
static bool is_nan(Variant const &v)
Definition: jstream.h:1585
static bool is_null(Variant const &v)
Definition: jstream.h:1561
std::vector< KeyValue > _Object
Definition: jstream.h:1434
static bool is_boolean(Variant const &v)
Definition: jstream.h:1565
static Object obj(Variant &v)
Definition: jstream.h:1604
std::variant< null_t, bool, double, std::string, _Object, Array > Variant
Definition: jstream.h:1436
static bool is_object(Variant const &v)
Definition: jstream.h:1577
StateType
Definition: jstream.h:347
@ Null
Definition: jstream.h:350
@ String
Definition: jstream.h:360
@ EndObject
Definition: jstream.h:357
@ Comma
Definition: jstream.h:355
@ StartObject
Definition: jstream.h:356
@ EndArray
Definition: jstream.h:359
@ True
Definition: jstream.h:352
@ Number
Definition: jstream.h:361
@ StartArray
Definition: jstream.h:358
@ Key
Definition: jstream.h:354
@ False
Definition: jstream.h:351
@ None
Definition: jstream.h:349
static Array & arr(Array &a)
Definition: jstream.h:1593
static bool is_array(Variant const &v)
Definition: jstream.h:1581
static std::vector< char > encode_json_string(std::string_view const &in)
Definition: jstream.h:18
static bool is_number(Variant const &v)
Definition: jstream.h:1569
std::nullptr_t null_t
Definition: jstream.h:1430
static bool is_string(Variant const &v)
Definition: jstream.h:1573
Definition: jstream.h:1437
Variant const & operator[](size_t i) const
Definition: jstream.h:1451
Array & operator+=(Variant const &v)
Definition: jstream.h:1469
bool empty() const
Definition: jstream.h:1443
T & get(size_t i)
Definition: jstream.h:1455
Variant & operator[](size_t i)
Definition: jstream.h:1447
void push_back(Variant const &v)
Definition: jstream.h:1465
size_t size() const
Definition: jstream.h:1439
T const & get(size_t i) const
Definition: jstream.h:1460
std::vector< Variant > a
Definition: jstream.h:1438
Definition: jstream.h:1475
KeyValue(std::string const &k, Variant const &v)
Definition: jstream.h:1479
Variant value
Definition: jstream.h:1477
std::string key
Definition: jstream.h:1476
Definition: jstream.h:1499
size_t size() const
Definition: jstream.h:1515
Object(Variant &v)
Definition: jstream.h:1508
Variant & value(std::string const &key)
Definition: jstream.h:1538
Variant const * find(std::string const &key) const
Definition: jstream.h:1534
Variant const & value(std::string const &key) const
Definition: jstream.h:1544
_Object * p
Definition: jstream.h:1500
Object(_Object &o)
Definition: jstream.h:1504
Object()
Definition: jstream.h:1501
T const & get(std::string const &key) const
Definition: jstream.h:1548
VariantRef operator[](std::string const &key)
Definition: jstream.h:1554
bool empty() const
Definition: jstream.h:1519
Variant * find(std::string const &key)
Definition: jstream.h:1523
Definition: jstream.h:366
std::string what_
Definition: jstream.h:367
std::string what() const
Definition: jstream.h:368
Definition: jstream.h:597
bool allow_comment
Definition: jstream.h:607
std::vector< Error > errors
Definition: jstream.h:615
std::vector< std::string > depth
Definition: jstream.h:612
bool allow_ambiguous_comma
Definition: jstream.h:608
char const * ptr
Definition: jstream.h:600
bool allow_unquoted_key
Definition: jstream.h:609
bool is_array
Definition: jstream.h:606
bool allow_special_constant
Definition: jstream.h:611
StateItem last_state
Definition: jstream.h:614
std::string string
Definition: jstream.h:604
std::vector< StateItem > states
Definition: jstream.h:601
bool hold
Definition: jstream.h:602
std::vector< int > depth_stack
Definition: jstream.h:613
bool allow_hexadicimal
Definition: jstream.h:610
double number
Definition: jstream.h:605
char const * begin
Definition: jstream.h:598
char const * end
Definition: jstream.h:599
std::string key
Definition: jstream.h:603
Definition: jstream.h:587
StateType type
Definition: jstream.h:588
char const * ptr
Definition: jstream.h:589
StateItem(StateType type, char const *ptr=nullptr)
Definition: jstream.h:591
Definition: jstream.h:1484
Variant * var
Definition: jstream.h:1485
void operator=(Variant const &v)
Definition: jstream.h:1490
VariantRef(Variant &v)
Definition: jstream.h:1486