279 static const int cached_bit = 2;
280 static const int error_bit = 4;
288 lsize_{}, lremain_{}, t_{
t}
291 rvalue(type
t,
char*
s,
char* e)
noexcept:
292 start_{
s}, end_{e}, t_{
t}
294 determine_num_type();
298 start_(r.start_), end_(r.end_), key_(r.key_), t_(r.t_), nt_(r.nt_), option_(r.option_)
305 *
this = std::move(r);
323 key_ = std::move(r.key_);
324 l_ = std::move(r.l_);
326 lremain_ = r.lremain_;
333 explicit operator bool()
const noexcept
335 return (option_ & error_bit) == 0;
338 explicit operator int64_t()
const
343 explicit operator uint64_t()
const
348 explicit operator int()
const
350 return static_cast<int>(
i());
354 explicit operator std::string()
const
356#ifndef CROW_JSON_NO_ERROR_CHECK
357 if (
t() == type::Object ||
t() == type::List)
358 throw std::runtime_error(
"json type container");
363 return std::string(
s());
365 return std::string(
"null");
367 return std::string(
"true");
369 return std::string(
"false");
371 return std::string(start_, end_ - start_);
378#ifndef CROW_JSON_NO_ERROR_CHECK
379 if (option_ & error_bit)
381 throw std::runtime_error(
"invalid json object");
390#ifndef CROW_JSON_NO_ERROR_CHECK
391 if (option_ & error_bit)
393 throw std::runtime_error(
"invalid json object");
402#ifndef CROW_JSON_NO_ERROR_CHECK
407 return utility::lexical_cast<int64_t>(start_, end_ - start_);
409 const std::string msg =
"expected number, got: " + std::string(get_type_str(
t()));
410 throw std::runtime_error(msg);
413 return utility::lexical_cast<int64_t>(start_, end_ - start_);
419#ifndef CROW_JSON_NO_ERROR_CHECK
424 return utility::lexical_cast<uint64_t>(start_, end_ - start_);
426 throw std::runtime_error(std::string(
"expected number, got: ") + get_type_str(
t()));
429 return utility::lexical_cast<uint64_t>(start_, end_ - start_);
435#ifndef CROW_JSON_NO_ERROR_CHECK
436 if (
t() != type::Number)
437 throw std::runtime_error(
"value is not number");
439 return utility::lexical_cast<double>(start_, end_ - start_);
445#ifndef CROW_JSON_NO_ERROR_CHECK
446 if (
t() != type::True &&
t() != type::False)
447 throw std::runtime_error(
"value is not boolean");
449 return t() == type::True;
455#ifndef CROW_JSON_NO_ERROR_CHECK
456 if (
t() != type::String)
457 throw std::runtime_error(
"value is not string");
464 std::vector<rvalue>
lo()
const
466#ifndef CROW_JSON_NO_ERROR_CHECK
467 if (
t() != type::Object &&
t() != type::List)
468 throw std::runtime_error(
"value is not a container");
470 std::vector<rvalue> ret;
472 for (uint32_t
i = 0;
i < lsize_;
i++)
474 ret.emplace_back(l_[
i]);
492 case '"': *tail++ =
'"';
break;
493 case '\\': *tail++ =
'\\';
break;
494 case '/': *tail++ =
'/';
break;
495 case 'b': *tail++ =
'\b';
break;
496 case 'f': *tail++ =
'\f';
break;
497 case 'n': *tail++ =
'\n';
break;
498 case 'r': *tail++ =
'\r';
break;
499 case 't': *tail++ =
'\t';
break;
502 auto from_hex = [](
char c) {
510 (from_hex(head[1]) << 12) +
511 (from_hex(head[2]) << 8) +
512 (from_hex(head[3]) << 4) +
516 *tail++ = 0xE0 | (code >> 12);
517 *tail++ = 0x80 | ((code >> 6) & 0x3F);
518 *tail++ = 0x80 | (code & 0x3F);
520 else if (code >= 0x80)
522 *tail++ = 0xC0 | (code >> 6);
523 *tail++ = 0x80 | (code & 0x3F);
545 bool has(
const char* str)
const
547 return has(std::string(str));
550 bool has(
const std::string& str)
const
556 return l.key_ < r.key_;
558 bool operator()(
const rvalue& l,
const std::string& r)
const
562 bool operator()(
const std::string& l,
const rvalue& r)
const
569 std::sort(begin(), end(), Pred());
572 auto it = lower_bound(begin(), end(), str, Pred());
573 return it != end() && it->key_ == str;
576 int count(
const std::string& str)
const
578 return has(str) ? 1 : 0;
581 rvalue* begin()
const
583#ifndef CROW_JSON_NO_ERROR_CHECK
584 if (
t() != type::Object &&
t() != type::List)
585 throw std::runtime_error(
"value is not a container");
591#ifndef CROW_JSON_NO_ERROR_CHECK
592 if (
t() != type::Object &&
t() != type::List)
593 throw std::runtime_error(
"value is not a container");
595 return l_.get() + lsize_;
598 const detail::r_string& key()
const
605 if (
t() == type::String)
607#ifndef CROW_JSON_NO_ERROR_CHECK
608 if (
t() != type::Object &&
t() != type::List)
609 throw std::runtime_error(
"value is not a container");
614 const rvalue& operator[](
int index)
const
616#ifndef CROW_JSON_NO_ERROR_CHECK
617 if (
t() != type::List)
618 throw std::runtime_error(
"value is not a list");
619 if (index >=
static_cast<int>(lsize_) || index < 0)
620 throw std::runtime_error(
"list out of bound");
625 const rvalue& operator[](
size_t index)
const
627#ifndef CROW_JSON_NO_ERROR_CHECK
628 if (
t() != type::List)
629 throw std::runtime_error(
"value is not a list");
631 throw std::runtime_error(
"list out of bound");
636 const rvalue& operator[](
const char* str)
const
638 return this->operator[](std::string(str));
641 const rvalue& operator[](
const std::string& str)
const
643#ifndef CROW_JSON_NO_ERROR_CHECK
644 if (
t() != type::Object)
645 throw std::runtime_error(
"value is not an object");
649 bool operator()(
const rvalue& l,
const rvalue& r)
const
651 return l.key_ < r.key_;
653 bool operator()(
const rvalue& l,
const std::string& r)
const
657 bool operator()(
const std::string& l,
const rvalue& r)
const
664 std::sort(begin(), end(), Pred());
667 auto it = lower_bound(begin(), end(), str, Pred());
668 if (it != end() && it->key_ == str)
670#ifndef CROW_JSON_NO_ERROR_CHECK
671 throw std::runtime_error(
"cannot find key: " + str);
673 static rvalue nullValue;
680 option_ |= error_bit;
685 return (option_ & error_bit) != 0;
688 std::vector<std::string> keys()
const
690#ifndef CROW_JSON_NO_ERROR_CHECK
691 if (
t() != type::Object)
692 throw std::runtime_error(
"value is not an object");
694 std::vector<std::string> ret;
696 for (uint32_t
i = 0;
i < lsize_;
i++)
698 ret.emplace_back(std::string(l_[
i].key()));
704 bool is_cached()
const
706 return (option_ & cached_bit) != 0;
708 void set_cached()
const
710 option_ |= cached_bit;
712 void copy_l(
const rvalue& r)
714 if (r.t() != type::Object && r.t() != type::List)
718 l_.reset(
new rvalue[lsize_]);
719 std::copy(r.begin(), r.end(), begin());
722 void emplace_back(rvalue&& v)
726 int new_size = lsize_ + lsize_;
727 if (new_size - lsize_ > 60000)
728 new_size = lsize_ + 60000;
731 rvalue* p =
new rvalue[new_size];
733 for (
auto& x : *this)
734 *p2++ = std::move(x);
736 lremain_ = new_size - lsize_;
738 l_[lsize_++] = std::move(v);
743 void determine_num_type()
745 if (t_ != type::Number)
747 nt_ = num_type::Null;
751 const std::size_t len = end_ - start_;
752 const bool has_minus = std::memchr(start_,
'-', len) !=
nullptr;
753 const bool has_e = std::memchr(start_,
'e', len) !=
nullptr || std::memchr(start_,
'E', len) !=
nullptr;
754 const bool has_dec_sep = std::memchr(start_,
'.', len) !=
nullptr;
755 if (has_dec_sep || has_e)
756 nt_ = num_type::Floating_point;
758 nt_ = num_type::Signed_integer;
760 nt_ = num_type::Unsigned_integer;
763 mutable char* start_;
765 detail::r_string key_;
766 std::unique_ptr<rvalue[]> l_;
770 num_type nt_{num_type::Null};
771 mutable uint8_t option_{0};
773 friend rvalue load_nocopy_internal(
char* data,
size_t size);
774 friend rvalue load(
const char* data,
size_t size);
775 friend std::ostream& operator<<(std::ostream& os,
const rvalue& r)
780 case type::Null: os <<
"null";
break;
781 case type::False: os <<
"false";
break;
782 case type::True: os <<
"true";
break;
787 case num_type::Floating_point: os << r.d();
break;
788 case num_type::Double_precision_floating_point: os << r.d();
break;
789 case num_type::Signed_integer: os << r.i();
break;
790 case num_type::Unsigned_integer: os << r.u();
break;
791 case num_type::Null:
throw std::runtime_error(
"Number with num_type Null");
795 case type::String: os <<
'"' << r.s() <<
'"';
break;
818 os <<
'"' << escape(x.key_) <<
"\":";
825 case type::Function: os <<
"custom function";
break;
1297#ifdef CROW_JSON_USE_MAP
1298 std::map<std::string, wvalue>;
1300 std::unordered_map<std::string, wvalue>;
1303 using list = std::vector<wvalue>;
1305 type t()
const {
return t_; }
1311 type t_{type::Null};
1312 num_type nt{num_type::Null};
1320 constexpr number() noexcept:
1322 constexpr number(std::uint64_t value)
noexcept:
1324 constexpr number(std::int64_t value)
noexcept:
1326 explicit constexpr number(
double value)
noexcept:
1328 explicit constexpr number(
float value)
noexcept:
1332 std::unique_ptr<list> l;
1333 std::unique_ptr<object> o;
1334 std::function<std::string(std::string&)> f;
1338 returnable(
"application/json") {}
1340 wvalue(std::nullptr_t):
1341 returnable(
"application/json"), t_(type::Null) {}
1344 returnable(
"application/json"), t_(value ? type::True : type::False) {}
1346 wvalue(std::uint8_t value):
1347 returnable(
"application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1348 wvalue(std::uint16_t value):
1349 returnable(
"application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1350 wvalue(std::uint32_t value):
1351 returnable(
"application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1352 wvalue(std::uint64_t value):
1353 returnable(
"application/json"), t_(type::Number), nt(num_type::Unsigned_integer), num(static_cast<std::uint64_t>(value)) {}
1355 wvalue(std::int8_t value):
1356 returnable(
"application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1357 wvalue(std::int16_t value):
1358 returnable(
"application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1359 wvalue(std::int32_t value):
1360 returnable(
"application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1361 wvalue(std::int64_t value):
1362 returnable(
"application/json"), t_(type::Number), nt(num_type::Signed_integer), num(static_cast<std::int64_t>(value)) {}
1364 wvalue(
float value):
1365 returnable(
"application/json"), t_(type::Number), nt(num_type::Floating_point), num(static_cast<double>(value)) {}
1366 wvalue(
double value):
1367 returnable(
"application/json"), t_(type::Number), nt(num_type::Double_precision_floating_point), num(static_cast<double>(value)) {}
1369 wvalue(
char const* value):
1370 returnable(
"application/json"), t_(type::String), s(value) {}
1372 wvalue(std::string
const& value):
1373 returnable(
"application/json"), t_(type::String), s(value) {}
1374 wvalue(std::string&& value):
1375 returnable(
"application/json"), t_(type::String), s(std::move(value)) {}
1377 wvalue(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list):
1378 returnable(
"application/json"), t_(type::Object), o(new object(initializer_list)) {}
1380 wvalue(
object const& value):
1381 returnable(
"application/json"), t_(type::Object), o(new object(value)) {}
1382 wvalue(
object&& value):
1383 returnable(
"application/json"), t_(type::Object), o(new object(std::move(value))) {}
1385 wvalue(
const list& r):
1386 returnable(
"application/json")
1389 l = std::unique_ptr<list>(
new list{});
1390 l->reserve(r.size());
1391 for (
auto it = r.begin(); it != r.end(); ++it)
1392 l->emplace_back(*it);
1395 returnable(
"application/json")
1398 l = std::unique_ptr<list>(
new list{});
1399 l->reserve(r.size());
1400 for (
auto it = r.begin(); it != r.end(); ++it)
1401 l->emplace_back(*it);
1414 case type::Function:
1418 if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
1420 else if (nt == num_type::Signed_integer)
1429 l = std::unique_ptr<list>(
new list{});
1430 l->reserve(r.size());
1431 for (
auto it = r.begin(); it != r.end(); ++it)
1432 l->emplace_back(*it);
1435 o = std::unique_ptr<object>(
new object{});
1436 for (
auto it = r.begin(); it != r.end(); ++it)
1437 o->emplace(it->key(), *it);
1454 if (nt == num_type::Floating_point || nt == num_type::Double_precision_floating_point)
1456 else if (nt == num_type::Signed_integer)
1465 l = std::unique_ptr<list>(
new list{});
1466 l->reserve(r.
size());
1467 for (
auto it = r.l->begin(); it != r.l->end(); ++it)
1468 l->emplace_back(*it);
1471 o = std::unique_ptr<object>(
new object{});
1472 o->insert(r.o->begin(), r.o->end());
1474 case type::Function:
1480 returnable(
"application/json")
1482 *
this = std::move(r);
1485 wvalue& operator=(wvalue&& r)
1509 wvalue& operator=(std::nullptr_t)
1514 wvalue& operator=(
bool value)
1524 wvalue& operator=(
float value)
1529 nt = num_type::Floating_point;
1533 wvalue& operator=(
double value)
1538 nt = num_type::Double_precision_floating_point;
1542 wvalue& operator=(
unsigned short value)
1547 nt = num_type::Unsigned_integer;
1551 wvalue& operator=(
short value)
1556 nt = num_type::Signed_integer;
1560 wvalue& operator=(
long long value)
1565 nt = num_type::Signed_integer;
1569 wvalue& operator=(
long value)
1574 nt = num_type::Signed_integer;
1578 wvalue& operator=(
int value)
1583 nt = num_type::Signed_integer;
1587 wvalue& operator=(
unsigned long long value)
1592 nt = num_type::Unsigned_integer;
1596 wvalue& operator=(
unsigned long value)
1601 nt = num_type::Unsigned_integer;
1605 wvalue& operator=(
unsigned int value)
1610 nt = num_type::Unsigned_integer;
1614 wvalue& operator=(
const char* str)
1622 wvalue& operator=(
const std::string& str)
1630 wvalue& operator=(list&& v)
1632 if (t_ != type::List)
1636 l = std::unique_ptr<list>(
new list{});
1638 l->resize(v.size());
1642 (*l)[idx++] = std::move(x);
1647 template<
typename T>
1648 wvalue& operator=(
const std::vector<T>& v)
1650 if (t_ != type::List)
1654 l = std::unique_ptr<list>(
new list{});
1656 l->resize(v.size());
1665 wvalue& operator=(std::initializer_list<std::pair<std::string const, wvalue>> initializer_list)
1667 if (t_ != type::Object)
1671 o = std::unique_ptr<object>(
new object(initializer_list));
1675#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(_LIBCPP_VERSION)
1676 o = std::unique_ptr<object>(
new object(initializer_list));
1678 (*o) = initializer_list;
1684 wvalue& operator=(
object const& value)
1686 if (t_ != type::Object)
1690 o = std::unique_ptr<object>(
new object(value));
1694#if defined(__APPLE__) || defined(__MACH__) || defined(__FreeBSD__) || defined(__ANDROID__) || defined(_LIBCPP_VERSION)
1695 o = std::unique_ptr<object>(
new object(value));
1703 wvalue& operator=(
object&& value)
1705 if (t_ != type::Object)
1709 o = std::unique_ptr<object>(
new object(std::move(value)));
1713 (*o) = std::move(value);
1718 wvalue& operator=(std::function<std::string(std::string&)>&& func)
1721 t_ = type::Function;
1722 f = std::move(func);
1726 wvalue& operator[](
unsigned index)
1728 if (t_ != type::List)
1732 l = std::unique_ptr<list>(
new list{});
1733 if (l->size() < index + 1)
1734 l->resize(index + 1);
1738 const wvalue& operator[](
unsigned index)
const
1740 return const_cast<wvalue*
>(
this)->
operator[](index);
1743 int count(
const std::string& str)
const
1745 if (t_ != type::Object)
1749 return o->count(str);
1752 wvalue& operator[](
const std::string& str)
1754 if (t_ != type::Object)
1758 o = std::unique_ptr<object>(
new object{});
1762 const wvalue& operator[](
const std::string& str)
const
1764 return const_cast<wvalue*
>(
this)->
operator[](str);
1767 std::vector<std::string> keys()
const
1769 if (t_ != type::Object)
1771 std::vector<std::string> result;
1774 result.push_back(kv.first);
1779 std::string execute(std::string txt =
"") const
1781 if (t_ != type::Function)
1789 if (t_ != type::List)
1799 case type::Null:
return 4;
1800 case type::False:
return 5;
1801 case type::True:
return 4;
1802 case type::Number:
return 30;
1803 case type::String:
return 2 + s.size() + s.size() / 2;
1812 sum += x.estimate_length();
1825 sum += 2 + kv.first.size() + kv.first.size() / 2;
1826 sum += kv.second.estimate_length();
1831 case type::Function:
1838 inline void dump_string(
const std::string& str, std::string& out)
const
1845 inline void dump_indentation_part(std::string& out,
const int indent,
const char separator,
const int indent_level)
const
1847 out.push_back(
'\n');
1848 out.append(indent_level * indent, separator);
1852 inline void dump_internal(
const wvalue& v, std::string& out,
const int indent,
const char separator,
const int indent_level = 0)
const
1856 case type::Null: out +=
"null";
break;
1857 case type::False: out +=
"false";
break;
1858 case type::True: out +=
"true";
break;
1861 if (v.nt == num_type::Floating_point || v.nt == num_type::Double_precision_floating_point)
1863 if (isnan(v.num.d) || isinf(v.num.d))
1866 CROW_LOG_WARNING <<
"Invalid JSON value detected (" << v.num.d <<
"), value set to null";
1876 if (v.nt == num_type::Double_precision_floating_point)
1879 sprintf_s(outbuf,
sizeof(outbuf),
"%.*g", DECIMAL_DIG, v.num.d);
1881 snprintf(outbuf,
sizeof(outbuf),
"%.*g", DECIMAL_DIG, v.num.d);
1887 sprintf_s(outbuf,
sizeof(outbuf),
"%f", v.num.d);
1889 snprintf(outbuf,
sizeof(outbuf),
"%f", v.num.d);
1892 char* p = &outbuf[0];
1893 char* pos_first_trailing_0 =
nullptr;
1904 char fch = *(p + 1);
1906 if (fch !=
'\0' && fch ==
'0') p++;
1915 pos_first_trailing_0 = p;
1922 pos_first_trailing_0 =
nullptr;
1929 if (pos_first_trailing_0 !=
nullptr)
1930 *pos_first_trailing_0 =
'\0';
1933 else if (v.nt == num_type::Signed_integer)
1935 out += std::to_string(v.num.si);
1939 out += std::to_string(v.num.ui);
1943 case type::String: dump_string(v.s, out);
break;
1950 dump_indentation_part(out, indent, separator, indent_level + 1);
1956 for (
auto& x : *v.l)
1964 dump_indentation_part(out, indent, separator, indent_level + 1);
1968 dump_internal(x, out, indent, separator, indent_level + 1);
1974 dump_indentation_part(out, indent, separator, indent_level);
1986 dump_indentation_part(out, indent, separator, indent_level + 1);
1992 for (
auto& kv : *v.o)
1999 dump_indentation_part(out, indent, separator, indent_level + 1);
2003 dump_string(kv.first, out);
2011 dump_internal(kv.second, out, indent, separator, indent_level + 1);
2017 dump_indentation_part(out, indent, separator, indent_level);
2024 case type::Function:
2025 out +=
"custom function";
2031 std::string dump(
const int indent,
const char separator =
' ')
const
2035 dump_internal(*
this, ret, indent, separator);
2039 std::string dump()
const override
2041 static constexpr int DontIndent = -1;
2043 return dump(DontIndent);