35#ifndef CTL_JSON_TEMPLATE_LIBRARY
36#define CTL_JSON_TEMPLATE_LIBRARY
51#if !defined(NAMESPACE_CTLJSON)
52#define NAMESPACE_CTLJSON ctl
55namespace NAMESPACE_CTLJSON {
56namespace string_internal_ {
64const T casetables<T>::lc[] = {
65 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
67 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
69 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72,
71 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x2e, 0x2b,
72 0x2d, 0x69, 0x6e, 0x66,
73 0x2d, 0x71, 0x6e, 0x61, 0x6e,
74 0x2d, 0x73, 0x6e, 0x61, 0x6e
77const T casetables<T>::uc[] = {
78 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
80 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
82 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52,
84 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x2e, 0x2b,
85 0x2d, 0x49, 0x4e, 0x46,
86 0x2d, 0x51, 0x4e, 0x41, 0x4e,
87 0x2d, 0x53, 0x4e, 0x41, 0x4e
90template <
typename stringT>
91stringT reverse_(stringT& s) {
92 typedef typename stringT::size_type size_type;
93 const size_type mid = s.size() / 2;
95 for (size_type i = 0; i < mid; ++i) std::swap(s[i], s[s.size() - i - 1]);
100template <
typename stringT>
101int mul2_(stringT& s,
const int radix) {
102 typedef typename stringT::value_type char_type;
103 typedef typename stringT::size_type size_type;
104 char_type carried = 0;
106 for (size_type i = 0; i < s.size(); ++i) {
107 char_type& ch = s[i] *= 2;
109 carried = ((ch =
static_cast<char_type
>(ch + carried)) >=
110 static_cast<char_type
>(radix))
111 ? (ch =
static_cast<char_type
>(ch - radix), 1)
114 return carried ? (s.push_back(carried), 1) : 0;
117template <
typename stringT>
118int div2_(stringT& s,
const int radix) {
119 typedef typename stringT::value_type char_type;
120 typedef typename stringT::size_type size_type;
123 for (size_type i = s.size(); i;) {
124 char_type& ch = s[--i];
126 ch =
static_cast<char_type
>(ch + (borrowed ? radix : 0));
131 if (borrowed) s.insert(0, 1,
static_cast<char_type
>(radix / 2));
133 if (s.size() && s[s.size() - 1] == 0) {
134 s.resize(s.size() - 1);
140template <
typename stringT>
141int plus_(stringT& s1,
const stringT& s2,
const int radix) {
142 typedef typename stringT::value_type char_type;
143 typedef typename stringT::size_type size_type;
144 char_type carried = 0;
146 if (s1.size() < s2.size()) s1.resize(s2.size(), 0);
148 for (size_type i = 0; i < s1.size(); ++i) {
149 char_type& ch = s1[i] += (i < s2.size() ? s2[i] : 0) + carried;
150 carried = (ch >=
static_cast<char_type
>(radix))
151 ? (ch =
static_cast<char_type
>(ch - radix), 1)
154 return carried ? (s1.push_back(carried), 1) : 0;
157template <
typename stringT>
158int round_(stringT& s,
typename stringT::size_type pos,
const int radix) {
159 typedef typename stringT::value_type char_type;
161 if (pos <= s.size()) {
163 (s[(pos = s.size() - pos)] >=
static_cast<char_type
>(radix / 2)) ? 1
166 for (s.erase(0, pos + 1), pos = 0; carried && pos < s.size(); ++pos) {
167 char_type& ch = s[pos];
169 ch =
static_cast<char_type
>(ch + carried);
170 carried = (ch >=
static_cast<char_type
>(radix))
171 ? (ch =
static_cast<char_type
>(ch - radix), 1)
174 if (carried)
return s.push_back(carried), 1;
180static bool is_same_(
const T l,
const T r) {
181 return std::memcmp(&l, &r,
sizeof(T)) == 0;
186template <
typename stringT,
typename T>
187inline stringT to_string(T value,
int base = 10,
const int precision = 1) {
188 typedef typename stringT::value_type char_type;
189 typedef typename stringT::size_type size_type;
190 const char_type*
const table =
192 ? string_internal_::casetables<char_type>::lc
193 : (base = 0 - base, string_internal_::casetables<char_type>::uc));
196 if (base >= 2 && base <= 36) {
197 const bool minus = value < 0 ? (value = 0 - value,
true) : false;
199 for (; value; value /= base) {
200 num.push_back(table[value % base]);
203 if (precision > 0 && num.size() <
static_cast<size_type
>(precision))
204 num.append(
static_cast<size_type
>(precision) - num.size(), table[0]);
206 if (minus) num.push_back(table[38]);
208 return string_internal_::reverse_(num);
211template <
typename stringT,
typename T>
212stringT to_string_fp(T value,
int fmt,
int precision) {
213 typedef stringT string_type;
214 typedef typename stringT::value_type char_type;
215 typedef typename stringT::size_type size_type;
217 const bool uc = fmt >=
'A' && fmt <=
'Z';
219 const char_type*
const table =
220 uc ? (fmt +=
'a' -
'A', string_internal_::casetables<char_type>::uc)
221 : string_internal_::casetables<char_type>::lc;
226 string_internal_::is_same_(value, std::numeric_limits<T>::infinity())) ||
228 string_internal_::is_same_(value, -std::numeric_limits<T>::infinity())))
230 return stringT(&table[dppos], ((dppos & 1) ? 3 : 4));
232 if ((dppos = 42 + 1, string_internal_::is_same_(
233 value, std::numeric_limits<T>::quiet_NaN())) ||
235 string_internal_::is_same_(value, -std::numeric_limits<T>::quiet_NaN())))
237 return stringT(&table[dppos], ((dppos & 1) ? 4 : 5));
239 if ((dppos = 47 + 1, string_internal_::is_same_(
240 value, std::numeric_limits<T>::signaling_NaN())) ||
241 (--dppos, string_internal_::is_same_(
242 value, -std::numeric_limits<T>::signaling_NaN())))
244 return stringT(&table[dppos], ((dppos & 1) ? 5 : 4));
246 const int base = fmt ==
'a' ? (fmt =
'e', 16) : 10;
247 const bool remove0s =
248 (precision < 0) ? (precision = 0 - precision,
true) : (fmt ==
'g');
250 (value < 0 || string_internal_::is_same_(value, static_cast<T>(-0.0)))
251 ? (value = 0 - value,
true)
264 for (; (value - mask) >= mask; mask *= 2.0)
265 dppos += string_internal_::mul2_(mstr, base);
268 ((dppos -= (string_internal_::div2_(mstr, base) & 2) ? 1 : 0),
271 for (
int count = 11; value > 0.0 && mask > 0.0 && count < 64; mask /= 2.0) {
272 if (borrowed) resstr.insert(0, 1, 0);
276 dppos += string_internal_::plus_(resstr, mstr, base);
278 borrowed = string_internal_::div2_(mstr, base) & 1;
281 if (base == 16 && resstr.size()) {
282 const char_type& lb = resstr[resstr.size() - 1];
283 const int shift = (lb & 8) ? 3 : ((lb & 4) ? 2 : ((lb & 2) ? 1 : 0));
285 dppos = dppos * 4 + shift;
287 char_type borrowed2 = 0;
288 for (size_type i = resstr.size(); i;) {
289 char_type& ch = resstr[--i] |= borrowed2;
291 ch =
static_cast<char_type
>((ch >> shift) & 15);
295 static_cast<char_type
>((borrowed2 >> shift) & 15));
302 dppos += string_internal_::round_(resstr, precision + 1, base);
304 if (dppos >= -4 && dppos < precision) {
305 precision = precision - 1 - dppos;
306 dppos < 0 ? (resstr.append(
static_cast<size_type
>(-dppos),
307 static_cast<char_type
>(0)),
317 dppos += string_internal_::round_(resstr, precision + 1, base);
322 for (size_type i = 0;
323 precision > 1 && i < resstr.size() && resstr[i] == 0;
326 if (resstr.size() >
static_cast<size_type
>(precision))
327 resstr.erase(0, resstr.size() - precision);
329 resstr.insert(0,
static_cast<size_type
>(precision) - resstr.size(), 0);
331 for (size_type i = 0; i < resstr.size(); ++i)
332 resstr[i] = table[
static_cast<unsigned int>(resstr[i])];
334 if (resstr.size() > 1) resstr.insert(resstr.size() - 1, 1, table[36]);
336 resstr.insert(0, 1, table[base == 10 ? 14 : 25]);
337 resstr.insert(0, 1, ((dppos >= 0) ? table[37] : table[38]));
339 if (dppos < 0) dppos = 0 - dppos;
341 const size_type minwidth = base == 10 ? 2 : 1;
342 for (size_type inspos = 0; dppos || inspos < minwidth;
343 ++inspos, dppos /= 10)
344 resstr.insert(inspos, 1, table[dppos % 10]);
347 resstr.push_back(table[33]);
348 resstr.push_back(table[0]);
351 dppos < 0 ? (resstr.append(
static_cast<size_type
>(-dppos),
352 static_cast<char_type
>(0)),
356 dppos += string_internal_::round_(resstr, precision + dppos + 1, base);
361 for (size_type i = 0;
362 precision > 1 && i < resstr.size() && resstr[i] == 0;
367 if (resstr.size() >
static_cast<size_type
>(precision))
368 resstr.erase(0, resstr.size() - precision);
370 const size_type wantedsize =
371 static_cast<size_type
>(remove0s ? dppos : precision);
372 if (resstr.size() < wantedsize)
373 resstr.insert(0, wantedsize - resstr.size(), 0);
376 for (size_type i = 0; i < resstr.size(); ++i)
377 resstr[i] = table[
static_cast<unsigned int>(resstr[i])];
379 if (resstr.size() >
static_cast<size_type
>(dppos))
380 resstr.insert(resstr.size() - dppos, 1, table[36]);
383 if (minus) resstr.push_back(table[38]);
385 return string_internal_::reverse_(resstr);
388template <
typename stringT>
389inline stringT to_string(
double val,
const int fmt =
'f',
390 const int precision = 6) {
391 return to_string_fp<stringT>(val, fmt, precision);
393template <
typename stringT>
394inline stringT to_string(
float val,
const int fmt =
'f',
395 const int precision = 6) {
396 return to_string_fp<stringT>(val, fmt, precision);
398template <
typename stringT>
399inline stringT to_string(
long double val,
const int fmt =
'f',
400 const int precision = 6) {
401 return to_string_fp<stringT>(val, fmt, precision);
418 int code()
const {
return code_; }
420 std::size_t position()
const {
return pos_; }
434namespace json_internal_ {
439 typedef std::size_t size_type;
440 typedef const char_type* const_iterator;
442 view(
const char_type*
const p)
443 : data_(p), size_(std::char_traits<T>::length(p)) {}
445 view(
const char_type*
const p,
const size_type l) : data_(p), size_(l) {}
447 template <
typename StringLike>
448 view(
const StringLike& s) : data_(s.data()), size_(s.size()) {}
450 char_type* data() {
return data_; }
451 const char_type* data()
const {
return data_; }
453 size_type size()
const {
return size_; }
455 template <
typename StringLike>
456 StringLike str()
const {
457 return StringLike(data_, size_);
460 template <
typename StringLike>
461 int compare(
const StringLike& right)
const {
462 if (data_ == right.data())
return 0;
464 const size_type count = size_ <= right.size() ? size_ : right.size();
465 const int cmp = std::memcmp(data_, right.data(), count *
sizeof(T));
467 if (cmp != 0)
return cmp;
469 return size_ == right.size() ? 0 : (size_ < right.size() ? -1 : 1);
472 template <
typename StringLike>
473 bool operator==(
const StringLike& right)
const {
474 return compare(right) == 0;
477 template <
typename StringLike>
478 bool operator!=(
const StringLike& right)
const {
479 return !operator==(right);
482 const T operator[](
const size_type n)
const {
return data_[n]; }
484 const_iterator begin()
const {
return data_; }
485 const_iterator end()
const {
return data_ + size_; }
492template <
typename ElemT>
495 typedef ElemT value_type;
496 typedef std::size_t size_type;
497 typedef ElemT& reference;
498 typedef const ElemT& const_reference;
499 typedef ElemT* pointer;
500 typedef const ElemT* const_pointer;
501 typedef const_pointer const_iterator;
502 typedef view<ElemT> view_type;
504 static const size_type npos =
static_cast<size_type
>(-1);
507 nestring() : size_(0), capacity_p1_(lbsize_p1_) {}
509 nestring(
const const_pointer p,
const size_type len)
510 : size_(0), capacity_p1_(lbsize_p1_) {
512 if (len) std::memcpy(buf_(), p, len *
sizeof(ElemT));
515 nestring(
const nestring& right,
const size_type pos, size_type len = npos)
516 : size_(0), capacity_p1_(lbsize_p1_) {
518 const size_type len2 = right.size_ - pos;
519 if (len > len2) len = len2;
523 if (len) std::memcpy(buf_(), right.buf_() + pos, len *
sizeof(ElemT));
526 nestring(
const const_pointer p) : size_(0), capacity_p1_(lbsize_p1_) {
530 nestring(
const nestring& right) : size_(0), capacity_p1_(lbsize_p1_) {
534 nestring(
const view_type v) : size_(0), capacity_p1_(lbsize_p1_) {
535 assign(v.data(), v.size());
538 nestring& operator=(
const nestring& right) {
539 if (
this != &right) {
541 std::memcpy(buf_(), right.buf_(), right.size_ *
sizeof(ElemT));
546 nestring& operator=(
const const_pointer p) {
548 const std::size_t size = std::char_traits<ElemT>::length(p);
551 std::memcpy(buf_(), p, size *
sizeof(ElemT));
556#if defined(__cpp_rvalue_references)
557 nestring(nestring&& right)
558 : size_(right.size_), capacity_p1_(right.capacity_p1_) {
559 if (!right.is_localbuf_()) {
560 buffer_ = right.buffer_;
561 right.buffer_ = NULL;
563 std::memcpy(localbuf_, right.localbuf_, size_ *
sizeof(ElemT));
566 right.capacity_p1_ = lbsize_p1_;
569 nestring& operator=(nestring&& right) {
570 if (
this != &right) {
572 capacity_p1_ = right.capacity_p1_;
574 if (!is_localbuf_() && buffer_ != NULL) std::free(buffer_);
576 if (!right.is_localbuf_()) {
577 buffer_ = right.buffer_;
578 right.buffer_ = NULL;
580 std::memcpy(localbuf_, right.localbuf_, size_ *
sizeof(ElemT));
583 right.capacity_p1_ = lbsize_p1_;
590 if (!is_localbuf_() && buffer_ != NULL) std::free(buffer_);
593 size_type size()
const {
return size_; }
595 template <
typename Traits,
typename Alloc>
596 operator std::basic_string<ElemT, Traits, Alloc>()
const {
597 return std::basic_string<ElemT, Traits, Alloc>(buf_(), buf_() + size_);
600 nestring substr(size_type pos, size_type len)
const {
601 return nestring(buf_() + pos, len);
604 view_type make_view(size_type pos, size_type len)
const {
605 return view_type(buf_() + pos, len);
608 bool operator==(
const nestring& right)
const {
609 if (size_ != right.size_)
return false;
611 if (
this == &right)
return true;
613 return std::memcmp(buf_(), right.buf_(), size_ *
sizeof(ElemT)) == 0;
616 bool operator!=(
const nestring& right)
const {
return !operator==(right); }
617 bool operator<(
const nestring& right)
const {
return compare(right) < 0; }
619 void clear() { size_ = 0; }
621 void resize(
const size_type newsize) {
622 if (newsize >= capacity_p1_)
624 else if (!is_localbuf_() && newsize <= localbuf_size_)
625 heap_to_local_(newsize);
630 void resize(
const size_type newsize,
const ElemT type) {
631 size_type oldsize = size_;
635 const pointer base = buf_();
636 for (; oldsize < size_; ++oldsize) base[oldsize] = type;
639 reference operator[](
const size_type pos) {
return buf_()[pos]; }
641 const_reference operator[](
const size_type pos)
const {
return buf_()[pos]; }
643 void push_back(
const ElemT n) {
644 const size_type oldsize = size_;
646 if (++size_ >= capacity_p1_) reserve(size_);
651 void assign(
const nestring& right) { operator=(right); }
653 void assign(
const const_pointer p,
const size_type len) {
656 std::memcpy(buf_(), p, len *
sizeof(ElemT));
660 template <
typename Iterator>
661 void assign(Iterator begin,
const Iterator end) {
664 for (size_type i = 0; begin != end; ++i, ++begin)
665 buf_()[i] =
static_cast<value_type
>(*begin);
668 nestring& append(
const size_type len,
const ElemT type) {
669 resize(size_ + len, type);
673 nestring& append(
const const_pointer p,
const size_type len) {
674 const size_type oldsize = size_;
677 std::memcpy(buf_() + oldsize, p, len *
sizeof(ElemT));
681 nestring& append(
const const_pointer p) {
682 return append(p, std::char_traits<ElemT>::length(p));
685 template <
typename Iterator>
686 nestring& append(Iterator begin,
const Iterator end) {
687 const size_type len = end - begin;
688 size_type oldsize = size_;
691 pointer base = buf_() + oldsize;
692 for (size_type i = 0; begin != end; ++i, ++begin)
693 base[i] =
static_cast<value_type
>(*begin);
697 nestring& append(
const view_type right) {
698 const size_type oldsize = size_;
699 const size_type rightsize = right.size();
701 resize(size_ + right.size());
702 std::memcpy(buf_() + oldsize, right.data(), rightsize *
sizeof(ElemT));
706 void erase(
const size_type pos,
const size_type len) {
708 size_type rmndr = size_ - pos;
712 std::memmove(buf_() + pos, buf_() + pos + len, rmndr *
sizeof(ElemT));
717 if (!is_localbuf_() && size_ <= localbuf_size_) heap_to_local_(size_);
721 void insert(
const size_type pos,
const view_type right) {
722 const size_type rightsize = right.size();
724 move_forwards_(pos, rightsize);
725 std::memcpy(buf_() + pos, right.data(), rightsize *
sizeof(ElemT));
728 void insert(
const size_type pos,
const size_type count,
const ElemT ch) {
729 move_forwards_(pos, count);
730 pointer base = buf_() + pos;
732 for (size_type i = 0; i < count; ++i) base[i] = ch;
735 const_pointer data()
const {
return buf_(); }
737 const_iterator begin()
const {
return buf_(); }
738 const_iterator end()
const {
return buf_() + size_; }
740 int compare(size_type pos1,
const size_type count1,
const view_type right,
741 const size_type pos2,
const size_type count2)
const {
742 const size_type count = count1 <= count2 ? count1 : count2;
743 const_pointer lbase = buf_() + pos1;
744 const_pointer rbase = right.data() + pos2;
745 const int cmp = std::memcmp(lbase, rbase, count *
sizeof(ElemT));
747 if (cmp != 0)
return cmp;
749 return count1 == count2 ? 0 : (count1 < count2 ? -1 : 1);
752 bool no_alloc_failure()
const {
return capacity_p1_ > 0; }
754 void reserve(size_type newsize) {
755 if (newsize <= maxsize_) {
756 const size_type capa2 = capacity_p1_ * 2;
758 if (newsize < capa2) {
760 if (newsize > maxsize_) newsize = maxsize_;
763 if (is_localbuf_()) {
764 const pointer newbuf =
765 static_cast<pointer
>(std::malloc(newsize *
sizeof(ElemT)));
767 if (newbuf != NULL) {
768 std::memcpy(newbuf, localbuf_, size_ *
sizeof(ElemT));
770 capacity_p1_ = newsize + 1;
774 const pointer oldbuffer = buffer_;
776 buffer_ =
static_cast<pointer
>(
777 std::realloc(
static_cast<void*
>(buffer_), newsize *
sizeof(ElemT)));
778 if (buffer_ != NULL) {
779 capacity_p1_ = newsize + 1;
782 std::free(oldbuffer);
789 throw std::bad_alloc();
793 void move_forwards_(
const size_type pos,
const size_type count) {
794 const size_type oldsize = size_;
796 resize(size_ + count);
799 const pointer base = buf_() + pos;
801 std::memmove(base + count, base, (oldsize - pos) *
sizeof(ElemT));
805 void heap_to_local_(
const size_type newsize) {
806 const pointer buf = buffer_;
808 std::memcpy(localbuf_, buf, newsize *
sizeof(ElemT));
810 capacity_p1_ = lbsize_p1_;
813 enum { localbuf_size_ = 16, lbsize_p1_ = localbuf_size_ + 1 };
815 bool is_localbuf_()
const {
return capacity_p1_ <= lbsize_p1_; }
817 pointer buf_() {
return !is_localbuf_() ? buffer_ : localbuf_; }
818 const_pointer buf_()
const {
return !is_localbuf_() ? buffer_ : localbuf_; }
822 ElemT localbuf_[localbuf_size_];
825 size_type capacity_p1_;
827 static const size_type maxsize_ = npos /
sizeof(ElemT) / 2;
829template <
typename ElemT>
830const typename nestring<ElemT>::size_type nestring<ElemT>::npos;
833template <
typename ElemT>
836 typedef ElemT value_type;
837 typedef std::size_t size_type;
838 typedef ElemT& reference;
839 typedef const ElemT& const_reference;
840 typedef ElemT* pointer;
841 typedef const ElemT* const_pointer;
844 nevector() : buffer_(NULL), size_(0), capacity_p1_(1) {}
846 nevector(
const size_type initsize)
847 : buffer_(NULL), size_(0), capacity_p1_(1) {
850 for (size_type i = 0; i < initsize; ++i)
new (&buffer_[i]) ElemT();
855 nevector(
const nevector& right) : buffer_(NULL), size_(0), capacity_p1_(1) {
856 reserve(right.size_);
858 for (size_type i = 0; i < right.size_; ++i)
859 new (&buffer_[i]) ElemT(right.buffer_[i]);
864#if defined(__cpp_rvalue_references)
865 nevector(nevector&& right)
866 : buffer_(right.buffer_),
868 capacity_p1_(right.capacity_p1_) {
870 right.capacity_p1_ = 1;
871 right.buffer_ = NULL;
874 nevector& operator=(nevector&& right) {
875 if (
this != &right) {
876 if (this->buffer_ != NULL) destroy_all_(this->buffer_);
878 this->size_ = right.size_;
879 this->capacity_p1_ = right.capacity_p1_;
880 this->buffer_ = right.buffer_;
883 right.capacity_p1_ = 1;
884 right.buffer_ = NULL;
890 nevector& operator=(
const nevector& right) {
891 if (
this != &right) {
893 for (size_type i = 0; i < right.size_; ++i) buffer_[i] = right.buffer_[i];
899 if (buffer_ != NULL) destroy_all_(buffer_);
902 size_type size()
const {
return size_; }
905 for (size_type i = 0; i < size_; ++i) buffer_[i].~ElemT();
909 void resize(
const size_type newsize) {
910 if (newsize > size_) {
911 if (newsize >= capacity_p1_) reserve(newsize);
913 for (size_type i = size_; i < newsize; ++i)
new (&buffer_[i]) ElemT();
915 for (size_type i = newsize; i < size_; ++i) buffer_[i].~ElemT();
920 void resize(
const size_type newsize,
const ElemT& type) {
921 if (newsize > size_) {
922 if (newsize >= capacity_p1_) reserve(newsize);
924 for (size_type i = size_; i < newsize; ++i)
new (&buffer_[i]) ElemT(type);
926 for (size_type i = newsize; i < size_; ++i) buffer_[i].~ElemT();
931 reference operator[](
const size_type pos) {
return buffer_[pos]; }
933 const_reference operator[](
const size_type pos)
const {
return buffer_[pos]; }
935 void push_back(const_reference n) {
936 const size_type oldsize = size_;
938 if (++size_ >= capacity_p1_) reserve(size_);
940 new (&buffer_[oldsize]) ElemT(n);
942 reference push_back() {
943 const size_type oldsize = size_;
945 if (++size_ >= capacity_p1_) reserve(size_);
947 new (&buffer_[oldsize]) ElemT;
948 return buffer_[oldsize];
951 const_reference back()
const {
return buffer_[size_ - 1]; }
953 reference back() {
return buffer_[size_ - 1]; }
955 void erase(
const size_type pos) {
957 buffer_[pos].~ElemT();
958 std::memmove(
static_cast<void*
>(buffer_ + pos), buffer_ + pos + 1,
959 (size_ - pos - 1) *
sizeof(ElemT));
964 void insert(
const size_type pos,
const ElemT& type) {
965 move_forwards_(pos, 1);
967 new (&buffer_[pos]) ElemT(type);
969 reference insert(
const size_type pos) {
970 move_forwards_(pos, 1);
972 new (&buffer_[pos]) ElemT;
976 bool no_alloc_failure()
const {
return capacity_p1_ > 0; }
978 void reserve(
const size_type newsize) { reserve_<16>(newsize); }
981 void move_forwards_(
const size_type pos,
const size_type count) {
982 const size_type oldsize = size_;
984 resize(size_ + count);
987 const pointer base = buffer_ + pos;
989 std::memmove(
static_cast<void*
>(base + count), base,
990 (oldsize - pos) *
sizeof(ElemT));
994 template <const
size_type minsize>
995 void reserve_(size_type newsize) {
996 if (newsize <= maxsize_) {
997 const pointer oldbuffer = buffer_;
998 const size_type capa2 = newsize >= minsize ? capacity_p1_ << 1 : minsize;
1000 if (newsize < capa2) {
1002 if (newsize > maxsize_) newsize = maxsize_;
1005 buffer_ =
static_cast<pointer
>(
1006 std::realloc(
static_cast<void*
>(buffer_), newsize *
sizeof(ElemT)));
1007 capacity_p1_ = newsize + 1;
1009 if (buffer_ != NULL)
return;
1011 destroy_all_(oldbuffer);
1016 throw std::bad_alloc();
1019 void destroy_all_(
const pointer p) {
1020 for (size_type i = 0; i < size_; ++i) p[i].~ElemT();
1026 size_type capacity_p1_;
1028 static const size_type maxsize_ =
1029 static_cast<size_type
>(-1) /
sizeof(ElemT) / 2;
1033enum rbtree_colour { rb_red, rb_black };
1035struct rbtree_node_base {
1036 typedef rbtree_node_base* pointer;
1037 typedef const rbtree_node_base* const_pointer;
1042 rbtree_colour colour;
1044 rbtree_node_base() : parent(NULL), left(NULL), right(NULL), colour(rb_red) {}
1047struct rbtree_header :
public rbtree_node_base {
1048 std::size_t node_count;
1050 rbtree_header() { reset(); }
1053 this->parent = NULL;
1060template <
typename T>
1061struct rbtree_node :
public rbtree_node_base {
1062 typedef rbtree_node<T>* pointer;
1063 typedef const rbtree_node<T>* const_pointer;
1067 rbtree_node& operator=(
const rbtree_node&) {
return *
this; }
1070template <
typename T>
1071struct const_iterator_base {
1072 typedef typename rbtree_node<T>::pointer pointer;
1073 typedef T value_type;
1074 typedef std::ptrdiff_t difference_type;
1076 const_iterator_base() : it_(NULL) {}
1078 const_iterator_base(
const pointer p) : it_(p) {}
1080 bool operator==(
const const_iterator_base& right)
const {
1081 return it_ == right.it_;
1084 bool operator!=(
const const_iterator_base& right)
const {
1085 return it_ != right.it_;
1088 const_iterator_base& operator++() {
1090 if (it_->right != NULL) {
1091 for (it_ =
static_cast<pointer
>(it_->right); it_->left != NULL;
1092 it_ =
static_cast<pointer
>(it_->left));
1093 }
else if (it_->parent != NULL) {
1094 pointer p =
static_cast<pointer
>(it_->parent);
1096 for (; p && p->right == it_;) {
1098 p =
static_cast<pointer
>(p->parent);
1107 const_iterator_base operator++(
int) {
1108 const const_iterator_base r(*
this);
1113 const T& operator*()
const {
return it_->value; }
1115 const T* operator->()
const {
return &it_->value; }
1117 operator pointer()
const {
return it_; }
1123template <
typename T>
1124struct iterator_base :
public const_iterator_base<T> {
1125 typedef const_iterator_base<T> base_type;
1126 typedef typename base_type::pointer pointer;
1127 typedef typename base_type::value_type value_type;
1128 typedef typename base_type::difference_type difference_type;
1130 iterator_base() : base_type(NULL) {}
1132 iterator_base(
const pointer p) : base_type(p) {}
1134 T& operator*()
const {
return this->it_->value; }
1136 T* operator->()
const {
return &this->it_->value; }
1139template <
typename Key,
typename T>
1142 typedef Key key_type;
1143 typedef T mapped_type;
1144 typedef std::pair<const Key, T> value_type;
1145 typedef std::size_t size_type;
1146 typedef value_type& reference;
1147 typedef const value_type& const_reference;
1148 typedef value_type* pointer;
1149 typedef const value_type* const_pointer;
1151 typedef iterator_base<value_type> iterator;
1152 typedef const_iterator_base<value_type> const_iterator;
1154 nemap() { entire_.reset(); }
1156 nemap(
const nemap& right) { operator=(right); }
1158 ~nemap() { erase_all_(entire_.parent); }
1160 std::size_t size()
const {
return entire_.node_count; }
1163 erase_all_(entire_.parent);
1167 nemap& operator=(
const nemap& right) {
1170 if (
this != &right && right.entire_.parent != NULL)
1171 entire_.parent = copy_nodes_(entire_.parent, right.entire_.parent, right);
1176 mapped_type& operator[](
const typename key_type::view_type key) {
1177 node_pointer p = find_(key);
1179 return p->value.second;
1182 iterator begin()
const {
1183 return iterator(
static_cast<node_pointer
>(entire_.left));
1186 iterator end()
const {
return iterator(NULL); }
1188 void erase(
const typename key_type::view_type key) {
1189 rbtree_node_base* node = entire_.parent;
1193 key.compare(
static_cast<node_pointer
>(node)->value.first);
1205 void erase(iterator it) { erase_(it); }
1207 iterator find(
const typename key_type::view_type key) {
1208 rbtree_node_base* node = entire_.parent;
1212 key.compare(
static_cast<node_pointer
>(node)->value.first);
1221 return iterator(
static_cast<node_pointer
>(node));
1225 typedef typename key_type::value_type char_type;
1226 typedef rbtree_node<value_type> node_type;
1227 typedef typename node_type::pointer node_pointer;
1228 typedef typename node_type::const_pointer const_node_pointer;
1230 node_pointer find_(
const json_internal_::view<char_type> key) {
1231 rbtree_node_base* node = entire_.parent;
1232 rbtree_node_base* parentnode = entire_.parent;
1236 comp = key.compare(
static_cast<node_pointer
>(node)->value.first);
1244 return static_cast<node_pointer
>(node);
1247 const node_pointer nn =
1248 static_cast<node_pointer
>(std::malloc(
sizeof(node_type)));
1250 if (nn == NULL)
throw std::bad_alloc();
1252 ++entire_.node_count;
1255 new (&nn->value) value_type(key, mapped_type());
1257 if (entire_.parent == NULL) {
1259 nn->colour = rb_black;
1261 entire_.parent = nn;
1267 nn->parent = parentnode;
1268 nn->colour = rb_red;
1271 parentnode->left = nn;
1272 if (entire_.left == parentnode) entire_.left = nn;
1274 parentnode->right = nn;
1275 if (entire_.right == parentnode) entire_.right = nn;
1278 rbtree_node_base* nn2 = nn;
1280 while (nn2 != entire_.parent && nn2->parent->colour == rb_red) {
1281 rbtree_node_base*
const pp = nn2->parent->parent;
1283 if (nn2->parent == pp->left) {
1284 rbtree_node_base*
const oo = pp->right;
1286 if (oo && oo->colour == rb_red) {
1287 nn2->parent->colour = rb_black;
1288 oo->colour = rb_black;
1289 pp->colour = rb_red;
1292 if (nn2 == nn2->parent->right) {
1296 nn2->parent->colour = rb_black;
1297 pp->colour = rb_red;
1301 rbtree_node_base*
const oo = pp->left;
1303 if (oo && oo->colour == rb_red) {
1304 nn2->parent->colour = rb_black;
1305 oo->colour = rb_black;
1306 pp->colour = rb_red;
1309 if (nn2 == nn2->parent->left) {
1313 nn2->parent->colour = rb_black;
1314 pp->colour = rb_red;
1319 entire_.parent->colour = rb_black;
1324 void rotate_left_(rbtree_node_base* nc) {
1325 rbtree_node_base*
const np = nc->right;
1327 nc->right = np->left;
1329 if (np->left != NULL) np->left->parent = nc;
1331 np->parent = nc->parent;
1333 if (nc == entire_.parent)
1334 entire_.parent = np;
1335 else if (nc == nc->parent->left)
1336 nc->parent->left = np;
1338 nc->parent->right = np;
1344 void rotate_right_(rbtree_node_base* nc) {
1345 rbtree_node_base*
const np = nc->left;
1347 nc->left = np->right;
1349 if (np->right != NULL) np->right->parent = nc;
1351 np->parent = nc->parent;
1353 if (nc == entire_.parent)
1354 entire_.parent = np;
1355 else if (nc == nc->parent->right)
1356 nc->parent->right = np;
1358 nc->parent->left = np;
1364 rbtree_node_base* copy_nodes_(rbtree_node_base* pnode,
1365 const rbtree_node_base*
const srcnode,
1366 const nemap& srctree) {
1367 const node_pointer nn =
1368 static_cast<node_pointer
>(std::malloc(
sizeof(node_type)));
1370 if (nn == NULL)
throw std::bad_alloc();
1373 value_type(
static_cast<const_node_pointer
>(srcnode)->value);
1376 nn->colour = srcnode->colour;
1378 ++entire_.node_count;
1381 nn->left = copy_nodes_(nn, srcnode->left, srctree);
1386 nn->right = copy_nodes_(nn, srcnode->right, srctree);
1390 if (srcnode == srctree.entire_.left) entire_.left = nn;
1392 if (srcnode == srctree.entire_.right) entire_.right = nn;
1397 void erase_all_(rbtree_node_base*
const node) {
1399 node_pointer enode =
static_cast<node_pointer
>(node);
1401 erase_all_(enode->left);
1402 erase_all_(enode->right);
1404 (&enode->value)->~value_type();
1409 void erase_(rbtree_node_base*
const enode) {
1411 rbtree_node_base*& root = entire_.parent;
1412 rbtree_node_base*& leftmost = entire_.left;
1413 rbtree_node_base*& rightmost = entire_.right;
1414 rbtree_node_base* s = enode;
1415 rbtree_node_base* sc = NULL;
1416 rbtree_node_base* scp = NULL;
1417 rbtree_colour s_orgclr = s->colour;
1419 if (enode->left == NULL)
1421 else if (enode->right == NULL)
1426 while (s->left) s = s->left;
1428 s_orgclr = s->colour;
1435 if (sc) sc->parent = scp;
1439 else if (enode == enode->parent->left)
1440 enode->parent->left = sc;
1442 enode->parent->right = sc;
1444 if (enode == leftmost) {
1445 if (enode->right == NULL)
1446 leftmost = enode->parent;
1448 for (leftmost = sc; leftmost->left != NULL;
1449 leftmost = leftmost->left);
1452 if (enode == rightmost) {
1453 if (enode->left == NULL)
1454 rightmost = enode->parent;
1456 for (rightmost = sc; rightmost->right != NULL;
1457 rightmost = rightmost->right);
1460 enode->left->parent = s;
1461 s->left = enode->left;
1463 if (enode->right == s)
1468 if (sc) sc->parent = scp;
1470 s->parent->left = sc;
1471 s->right = enode->right;
1472 enode->right->parent = s;
1477 else if (enode == enode->parent->left)
1478 enode->parent->left = s;
1480 enode->parent->right = s;
1482 s->parent = enode->parent;
1483 s->colour = enode->colour;
1486 if (s_orgclr == rb_black) {
1487 while (sc != root && (sc == NULL || sc->colour == rb_black)) {
1488 if (sc == scp->left) {
1489 rbtree_node_base* sib = scp->right;
1491 if (sib->colour == rb_red) {
1492 sib->colour = rb_black;
1493 scp->colour = rb_red;
1498 if ((sib->left == NULL || sib->left->colour == rb_black) &&
1499 (sib->right == NULL || sib->right->colour == rb_black)) {
1500 sib->colour = rb_red;
1504 if (sib->right == NULL || sib->right->colour == rb_black) {
1505 sib->left->colour = rb_black;
1506 sib->colour = rb_red;
1511 sib->colour = scp->colour;
1512 scp->colour = rb_black;
1514 if (sib->right) sib->right->colour = rb_black;
1520 rbtree_node_base* sib = scp->left;
1522 if (sib->colour == rb_red) {
1523 sib->colour = rb_black;
1524 scp->colour = rb_red;
1529 if ((sib->right == NULL || sib->right->colour == rb_black) &&
1530 (sib->left == NULL || sib->left->colour == rb_black)) {
1531 sib->colour = rb_red;
1535 if (sib->left == NULL || sib->left->colour == rb_black) {
1536 sib->right->colour = rb_black;
1537 sib->colour = rb_red;
1542 sib->colour = scp->colour;
1543 scp->colour = rb_black;
1545 if (sib->left) sib->left->colour = rb_black;
1552 if (sc) sc->colour = rb_black;
1555 node_pointer enode2 =
static_cast<node_pointer
>(enode);
1557 (&enode2->value)->~value_type();
1560 --entire_.node_count;
1564 rbtree_header entire_;
1571template <
bool,
typename T>
1573template <
typename T>
1574struct enable_if<true, T> {
1577template <
typename IntType,
typename RetType>
1578struct enable_if_integer
1579 : enable_if<std::numeric_limits<IntType>::is_integer, RetType> {};
1581template <
typename charT,
typename utftype>
1595 typedef std::basic_string<charT>
1597 typedef charT char_type;
1599 typedef nestring<charT> nstring_type;
1600 typedef json_internal_::view<charT> sview_type;
1606 psnum(
const double n,
const int p = -6) : value(n), precision(p) {}
1610 explicit jsonnode(
const value_type v)
1615 jsonnode() : type_(unassigned) {}
1617 jsonnode(
const jsonnode& right) : type_(right.type_) {
1618 if (
this != &right && !is_fallback() && !right.is_fallback()) {
1619 if (type_ == array) {
1620 array_ = new array_type(*right.array_);
1621 }
else if (type_ ==
object) {
1622 object_ =
new object_type(*right.object_);
1623 }
else if (type_ == number || type_ ==
string) {
1624 string_ =
new strnum_type(*right.string_);
1625 }
else if (type_ ==
boolean)
1626 boolvalue_ = right.boolvalue_;
1630 template <
typename StringT>
1631 explicit jsonnode(
const StringT& s) : type_(unassigned) {
1632 if (!parse(s)) clear();
1635 template <
typename StringT>
1636 jsonnode(
const StringT& s, json_error& e) : type_(unassigned) {
1640 template <
typename Iterator>
1641 jsonnode(Iterator begin,
const Iterator end) : type_(unassigned) {
1642 if (!parse(begin, end)) clear();
1645 template <
typename Iterator>
1646 jsonnode(Iterator begin,
const Iterator end, json_error& e)
1647 : type_(unassigned) {
1648 parse(begin, end, e);
1652 if (type_ <
boolean) destroy_node_();
1656 if (!is_fallback()) {
1664 value_type type()
const {
return static_cast<value_type
>(type_); }
1666 bool is_num()
const {
return type_ == number; }
1667 bool is_str()
const {
return type_ == string; }
1668 bool is_bool()
const {
return type_ == boolean; }
1669 bool is_true()
const {
return type_ ==
boolean && boolvalue_; }
1670 bool is_false()
const {
return type_ ==
boolean && !boolvalue_; }
1671 bool is_null()
const {
return type_ == null; }
1672 bool is_array()
const {
return type_ == array; }
1673 bool is_object()
const {
return type_ == object; }
1674 bool is_unassigned()
const {
return type_ == unassigned; }
1675 bool is_fallback()
const {
return type_ == fallback; }
1676 bool is_assigned()
const {
return type_ < unassigned; }
1677 bool has_value()
const {
return type_ < unassigned; }
1679 bool exists()
const {
return type_ != fallback; }
1681 jsonnode& operator=(
const jsonnode& right) {
1682 if (
this != &right && !is_fallback() && !right.is_fallback()) {
1683 const int newtype = right.type_;
1685 if (newtype == array) {
1686 array_type*
const newarray =
new array_type(*right.array_);
1689 }
else if (newtype ==
object) {
1690 object_type*
const newobject =
new object_type(*right.object_);
1692 object_ = newobject;
1693 }
else if (newtype == number || newtype ==
string) {
1694 strnum_type*
const newstring =
new strnum_type(*right.string_);
1696 string_ = newstring;
1697 }
else if (newtype ==
boolean) {
1698 const bool bv = right.boolvalue_;
1707 jsonnode& operator=(
const double d) {
return set_num(d, -6); }
1709 jsonnode& operator=(
const psnum& n) {
return set_num(n.value, n.precision); }
1711 template <
typename IntType>
1712 typename enable_if_integer<IntType, jsonnode>::type& operator=(
1714 return set_num(
static_cast<double>(i), -6);
1717 jsonnode& operator=(
const bool b) {
return set_bool(b); }
1719 jsonnode& operator=(
const sview_type s) {
return set_str(s); }
1721 jsonnode& operator=(
const char_type*
const p) {
return set_str(p); }
1723 jsonnode& operator=(
const value_type v) {
1726 return empty_array();
1728 return empty_object();
1732 return set_str(emptystr_, emptystr_);
1734 return set_bool(
false);
1741 template <
typename StringT>
1742 bool parse(
const StringT& s) {
1747 template <
typename StringT>
1748 bool parse(
const StringT& s, json_error& e) {
1749 if (!is_fallback()) {
1750 return parse(s.data(), s.data() + s.size(), e);
1755 template <
typename charT2>
1756 bool parse(
const charT2*
const p) {
1761 template <
typename charT2>
1762 bool parse(
const charT2*
const p, json_error& e) {
1763 if (!is_fallback()) {
1764 const charT2*
const end = p + std::char_traits<charT2>::length(p);
1765 return parse(p, end, e);
1770 template <
typename Iterator>
1771 bool parse(Iterator begin,
const Iterator end) {
1773 return parse(begin, end, e);
1776 template <
typename Iterator>
1777 bool parse(Iterator begin,
const Iterator end, json_error& e) {
1778 if (is_fallback())
return e.clear_();
1780 const Iterator orgbegin = begin;
1784 begin = skip_spaces_(begin, end);
1786 e.code_ = parse_value_(begin, end);
1787 e.pos_ = e.code_ ? std::distance(orgbegin, begin) : 0;
1789 return e.code_ == 0;
1792 std::basic_string<char_type> to_string()
const {
1793 std::basic_string<char_type> out;
1794 value_to_string_(out);
1797 std::basic_string<char_type>
stringify()
const {
1798 std::basic_string<char_type> out;
1799 value_to_string_(out);
1803 template <
typename StringT>
1804 StringT to_string()
const {
1806 value_to_string_(out);
1809 template <
typename StringT>
1812 value_to_string_(out);
1816 template <
typename StringT>
1817 void to_string(StringT& out)
const {
1819 value_to_string_(out);
1821 template <
typename StringT>
1824 value_to_string_(out);
1829 jsonnode& set_num(
const double d,
const int precision = -6) {
1830 if (is_fallback())
return fallback_node_;
1832 if (type_ != number) {
1835 string_ =
new strnum_type();
1839 string_->str.assign(ctl::to_string<nstring_type>(d,
'f', precision));
1845 jsonnode& set_str(
const sview_type s) {
1846 return set_str(s.data(), s.data() + s.size());
1849 template <
typename Iterator>
1850 jsonnode& set_str(Iterator begin,
const Iterator end) {
1851 if (is_fallback())
return fallback_node_;
1853 if (type_ !=
string) {
1856 string_ =
new strnum_type();
1858 string_->str.assign(begin, end);
1865 bool exists(
const std::size_t no)
const {
1866 return !is_fallback() && n(no) != &fallback_node_;
1869 const jsonnode& operator[](
const std::size_t no)
const {
1870 const jsonnode*
const node = n(no);
1873 jsonnode& operator[](
const std::size_t no) {
1874 jsonnode*
const node = n(no);
1878 const jsonnode* n(
const std::size_t no)
const {
1879 if (type_ == array) {
1880 if (no < array_->size())
return &(*array_)[no];
1882 return &fallback_node_;
1884 jsonnode* n(
const std::size_t no) {
1885 if (type_ == array) {
1886 if (no < array_->size())
return &(*array_)[no];
1888 return &fallback_node_;
1891 jsonnode& operator()(
const std::size_t no) {
1892 if (is_fallback())
return fallback_node_;
1894 if (type_ == array) {
1895 if (no >= array_->size()) array_->resize(no + 1);
1899 array_ =
new array_type();
1900 array_->resize(no + 1);
1902 return (*array_)[no];
1905 bool erase(
const std::size_t no) {
1906 if (type_ == array && no < array_->size()) {
1913 template <
typename ValueType>
1914 bool insert(
const std::size_t no,
const ValueType& right) {
1915 if (type_ == array && no <= array_->size()) {
1918 array_->insert(no).move_(backup);
1924 template <
typename ValueType>
1925 void push_back(
const ValueType& right) {
1926 if (type_ == array) {
1929 array_->push_back().move_(backup);
1933 jsonnode& empty_array() {
1934 if (is_fallback())
return fallback_node_;
1936 if (type_ == array) {
1941 array_ =
new array_type();
1948 std::size_t size()
const {
1950 return array_->size();
1951 else if (type_ ==
object)
1952 return object_->objmap.size();
1959 bool exists(
const sview_type key)
const {
1960 return !is_fallback() && n(key) != &fallback_node_;
1963 const jsonnode& operator[](
const sview_type key)
const {
1964 const jsonnode*
const node = n(key);
1967 jsonnode& operator[](
const sview_type key) {
1968 jsonnode*
const node = n(key);
1972 const jsonnode* n(
const sview_type key)
const {
1973 if (type_ ==
object) {
1974 const typename object_core::const_iterator it = object_->objmap.find(key);
1976 if (it != object_->objmap.end())
return &it->second;
1978 return &fallback_node_;
1980 jsonnode* n(
const sview_type key) {
1981 if (type_ ==
object) {
1982 const typename object_core::iterator it = object_->objmap.find(key);
1984 if (it != object_->objmap.end())
return &it->second;
1986 return &fallback_node_;
1989 jsonnode& operator()(
const sview_type key) {
1990 if (is_fallback())
return fallback_node_;
1992 if (type_ ==
object) {
1993 const typename object_core::iterator it = object_->objmap.find(key);
1995 if (it != object_->objmap.end())
return it->second;
1997 append_keyinfo_(object_->order, key, utftype());
1998 return object_->objmap[key];
2003 object_ =
new object_type();
2004 append_keyinfo_(object_->order, key, utftype());
2005 return object_->objmap[key];
2008 bool erase(
const sview_type key) {
2009 if (type_ ==
object) {
2010 const typename object_core::iterator it = object_->objmap.find(key);
2012 if (it != object_->objmap.end()) {
2013 object_->objmap.erase(it);
2014 remove_orderkey_(key);
2021 template <
typename ValueType>
2022 bool insert(
const sview_type inspos,
const sview_type newkey,
2023 const ValueType& newelem) {
2024 if (type_ ==
object && newkey != inspos) {
2025 strsize_type newkeyindex = object_->order.size();
2026 strsize_type insposindex = newkeyindex;
2028 for (strsize_type i = 0; (i < object_->order.size()) &&
2029 (newkeyindex == object_->order.size() ||
2030 insposindex == object_->order.size());) {
2031 const strsize_type keylen = get_keylen_(&object_->order[i], utftype());
2032 strsize_type base = i + keylen_size;
2034 if (keylen == newkey.size() &&
2035 object_->order.compare(base, keylen, newkey, 0, keylen) == 0)
2037 else if (keylen == inspos.size() &&
2038 object_->order.compare(base, keylen, inspos, 0, keylen) == 0)
2044 if (insposindex < object_->order.size()) {
2045 const strsize_type newkeylen = newkey.size();
2050 if (newkeyindex < object_->order.size()) {
2051 const strsize_type remlen = keylen_size + newkeylen;
2053 if ((newkeyindex + remlen) == insposindex)
2056 object_->order.erase(newkeyindex, remlen);
2057 if (newkeyindex < insposindex) insposindex -= remlen;
2061 nstring_type len_newkey;
2063 append_keyinfo_(len_newkey, newkey, utftype());
2064 object_->order.insert(insposindex, len_newkey);
2068 object_->objmap[newkey].move_(backup);
2075 template <
typename ValueType>
2076 bool push_back(
const sview_type key,
const ValueType& right) {
2077 if (type_ ==
object) {
2082 for (strsize_type pos = 0;
2083 (pos +
sizeof(keylen_type)) < object_->order.size();) {
2084 const strsize_type keylen =
2085 get_keylen_(&object_->order[pos], utftype());
2086 const strsize_type keypos = pos + keylen_size;
2088 if (keylen == key.size()) {
2089 for (strsize_type i = 0;; ++i) {
2091 if (keypos + keylen == object_->order.size())
goto PUSH_VALUE;
2093 object_->order.erase(keypos - keylen_size, keylen_size + keylen);
2096 if (object_->order[keypos + i] != key[i])
break;
2099 pos = keypos + keylen;
2103 append_keyinfo_(object_->order, key, utftype());
2106 object_->objmap[key].move_(backup);
2113 jsonnode& empty_object() {
2114 if (is_fallback())
return fallback_node_;
2116 if (type_ ==
object) {
2117 object_->objmap.clear();
2118 object_->order.clear();
2122 object_ =
new object_type();
2127 double num()
const {
2128 if (type_ == number)
return string_->num;
2129 if (type_ ==
boolean)
return static_cast<double>(boolvalue_);
2133 template <
typename NumType>
2134 NumType num()
const {
2135 return static_cast<NumType
>(
2136 type_ == number ? string_->num : (type_ ==
boolean ? boolvalue_ : 0));
2139 sview_type numstr_view()
const {
2140 static const char_type ltrue[] = {0x74, 0x72, 0x75, 0x65, 0};
2141 static const char_type lfalse[] = {0x66, 0x61, 0x6C,
2143 static const char_type lnull[] = {0x6E, 0x75, 0x6C, 0x6C, 0};
2145 if (type_ == number)
return string_->str;
2146 if (type_ ==
boolean)
return boolvalue_ ? ltrue : lfalse;
2147 if (type_ == null)
return lnull;
2148 return sview_type(lnull, 0);
2151 std::basic_string<char_type> numstr()
const {
2152 const sview_type sv = numstr_view();
2153 return std::basic_string<char_type>(sv.data(), sv.size());
2156 template <
typename StringT>
2157 void numstr(StringT& out)
const {
2158 typedef typename StringT::value_type dchar_type;
2159 static const dchar_type ltrue[] = {0x74, 0x72, 0x75, 0x65, 0};
2160 static const dchar_type lfalse[] = {0x66, 0x61, 0x6C,
2162 static const dchar_type lnull[] = {0x6E, 0x75, 0x6C, 0x6C, 0};
2165 if (type_ == number) {
2166 out.append(string_->str.begin(), string_->str.end());
2167 }
else if (type_ ==
boolean)
2168 out.append(boolvalue_ ? ltrue : lfalse);
2169 else if (type_ == null)
2173 sview_type str_view()
const {
2174 if (type_ ==
string)
return sview_type(string_->str);
2176 return sview_type(emptystr_, 0);
2179 std::basic_string<char_type> str()
const {
2180 if (type_ ==
string)
return string_->str;
2182 return std::basic_string<char_type>();
2185 template <
typename StringT>
2186 void str(StringT& out)
const {
2188 if (type_ ==
string) {
2189 out.append(string_->str.begin(), string_->str.end());
2195 jsonnode& set_bool(
const bool b) {
2196 if (is_fallback())
return fallback_node_;
2198 if (type_ !=
boolean) {
2206 jsonnode& set_null() {
2207 if (is_fallback())
return fallback_node_;
2209 if (type_ != null) {
2216 jsonnode allkeys()
const {
2222 void allkeys(jsonnode& out)
const {
2223 if (is_fallback()) {
2224 }
else if (type_ ==
object) {
2225 const std::size_t objsize = object_->objmap.size();
2227 if (out.type_ != array) {
2228 out.destroy_node_();
2230 out.array_ =
new array_type();
2232 out.array_->resize(objsize);
2234 strsize_type pos = 0;
2236 for (std::size_t i = 0;
2237 i < objsize && (pos + keylen_size) < object_->order.size(); ++i) {
2238 jsonnode& elem = (*out.array_)[i];
2239 const strsize_type keylen =
2240 get_keylen_(&object_->order[pos], utftype());
2242 if (elem.type_ !=
string) {
2243 elem.destroy_node_();
2244 elem.type_ = string;
2245 elem.string_ =
new strnum_type();
2248 elem.string_->str.assign(object_->order.view(pos, keylen));
2257 typedef typename nstring_type::size_type strsize_type;
2258 typedef unsigned int keylen_type;
2260 typedef nevector<jsonnode> array_type;
2261 typedef nemap<nstring_type, jsonnode> object_core;
2263 struct object_type {
2268 struct strnum_type {
2273 static const std::size_t keylen_size_tmp =
2274 sizeof(keylen_type) /
sizeof(char_type) +
2275 ((
sizeof(keylen_type) %
sizeof(char_type)) ? 1 : 0);
2276 static const std::size_t keylen_size =
2277 keylen_size_tmp >= 2 ? keylen_size_tmp : 2;
2279 template <
typename ForwardIterator>
2280 inline ForwardIterator skip_spaces_(ForwardIterator begin,
2281 const ForwardIterator end) {
2282 for (; begin != end && (*begin == 0x20 || *begin == 0x09 ||
2283 *begin == 0x0a || *begin == 0x0d);
2289 template <
typename utftag>
2290 void append_keyinfo_(nstring_type& order,
const sview_type add,
2291 const utftag)
const {
2292 const keylen_type size =
static_cast<keylen_type
>(add.size());
2293 const strsize_type base = order.size();
2295 order.resize(base + keylen_size);
2296 std::memcpy(&order[base], &size,
sizeof(keylen_type));
2299 void append_keyinfo_(nstring_type& order,
const sview_type add,
2300 const utf16tag)
const {
2301 const keylen_type size =
static_cast<keylen_type
>(add.size());
2302 strsize_type i = order.size();
2304 order.resize(i + keylen_size);
2305 order[i++] =
static_cast<charT
>(size & 0xffff);
2306 order[i] =
static_cast<charT
>(((size >> 8) >> 8) & 0xffff);
2310 template <
typename utftag>
2311 strsize_type get_keylen_(
const charT*
const p,
const utftag)
const {
2313 std::memcpy(&size, p,
sizeof(keylen_type));
2316 strsize_type get_keylen_(
const charT*
const p,
const utf16tag)
const {
2317 return static_cast<strsize_type
>(((p[0] & 0xffff)) |
2318 (((p[1] & 0xffff) << 8) << 8));
2323 template <
typename ForwardIterator,
typename UTFtag>
2324 bool parse_string_(nstring_type*
const str, ForwardIterator& begin,
2325 const ForwardIterator end,
const UTFtag) {
2326 ForwardIterator prevbegin = begin;
2327 unsigned long prev = 0ul;
2329 for (; begin != end;) {
2332 if (prevbegin != begin) str->append(prevbegin, begin);
2334 begin = skip_spaces_(++begin, end);
2340 if (++begin == end)
break;
2342 char_type nch = *begin;
2372 ForwardIterator upos = begin;
2373 unsigned long ucp = parse_4hexdigits_(begin, end);
2375 if (ucp < 0x10000ul) {
2378 if (prev && ucp >= 0xDC00ul && ucp <= 0xDFFFul) {
2379 ucp = ((ucp & 0x3FFul) | ((prev & 0x3FFul) << 10)) + 0x10000;
2381 (*str)[str->size() - 3] =
2382 static_cast<char_type
>(((ucp >> 18) & 7) | 0xf0);
2383 (*str)[str->size() - 2] =
2384 static_cast<char_type
>(((ucp >> 12) & 0x3f) | 0x80);
2385 (*str)[str->size() - 1] =
2386 static_cast<char_type
>(((ucp >> 6) & 0x3f) | 0x80);
2387 str->push_back(
static_cast<char_type
>((ucp & 0x3f) | 0x80));
2393 str->append(prevbegin, upos);
2394 (*str)[str->size() - 1] =
static_cast<char_type
>(ucp);
2395 }
else if (ucp < 0x800ul) {
2397 str->append(prevbegin, upos);
2398 (*str)[str->size() - 2] =
2399 static_cast<char_type
>(((ucp >> 6) & 0x1f) | 0xc0);
2400 (*str)[str->size() - 1] =
2401 static_cast<char_type
>((ucp & 0x3f) | 0x80);
2405 str->append(prevbegin, upos);
2406 (*str)[str->size() - 3] =
2407 static_cast<char_type
>(((ucp >> 12) & 0x0f) | 0xe0);
2408 (*str)[str->size() - 2] =
2409 static_cast<char_type
>(((ucp >> 6) & 0x3f) | 0x80);
2410 (*str)[str->size() - 1] =
2411 static_cast<char_type
>((ucp & 0x3f) | 0x80);
2412 if ((ucp & 0xFC00ul) == 0xD800ul) prev = ucp;
2429 str->append(prevbegin, begin);
2430 (*str)[str->size() - 1] = nch;
2433 prevbegin = ++begin;
2444 template <
typename ForwardIterator>
2445 bool parse_string_(nstring_type*
const str, ForwardIterator& begin,
2446 const ForwardIterator end,
const utf16tag) {
2447 ForwardIterator prevbegin = begin;
2449 for (; begin != end;) {
2452 if (prevbegin != begin) str->append(prevbegin, begin);
2454 begin = skip_spaces_(++begin, end);
2460 if (++begin == end)
break;
2462 char_type nch = *begin;
2492 ForwardIterator upos = begin;
2493 unsigned long ucp = parse_4hexdigits_(begin, end);
2495 if (ucp < 0x10000ul) {
2498 str->append(prevbegin, upos);
2499 (*str)[str->size() - 1] =
static_cast<char_type
>(ucp);
2511 str->append(prevbegin, begin);
2512 (*str)[str->size() - 1] = nch;
2514 prevbegin = ++begin;
2516 }
else if (*begin & 0x80) {
2517 unsigned long ch = *begin & 0xff;
2520 if ((ch & 0x20) == 0)
2522 if (++begin != end && (*begin & 0xc0) == 0x80)
2524 ch = ((ch << 6) & 0x7c0) | (*begin & 0x3f);
2526 str->append(prevbegin, begin);
2527 (*str)[str->size() - 1] =
static_cast<char_type
>(ch);
2528 prevbegin = ++begin;
2531 }
else if ((ch & 0x10) == 0)
2533 if (++begin != end && (*begin & 0xc0) == 0x80)
2535 const ForwardIterator tmpend = begin;
2537 ch = (ch << 8) | (*begin & 0xff);
2541 if (++begin != end && (*begin & 0xc0) == 0x80)
2543 ch = ((ch << 4) & 0xf000) | ((ch << 6) & 0xfc0) |
2546 str->append(prevbegin, tmpend);
2547 (*str)[str->size() - 1] =
static_cast<char_type
>(ch);
2548 prevbegin = ++begin;
2553 }
else if (ch >= 0xf0 && ch <= 0xf4)
2555 if (++begin != end && (*begin & 0xc0) == 0x80)
2557 ch = (ch << 8) | (*begin & 0xff);
2559 if (ch >= 0xf090 && ch <= 0xf48f)
2561 if (++begin != end && (*begin & 0xc0) == 0x80)
2563 const ForwardIterator tmpend = begin;
2565 ch = ((ch << 4) & 0x7000) | ((ch << 6) & 0xfc0) |
2568 if (++begin != end && (*begin & 0xc0) == 0x80)
2570 ch = ((ch << 6) | (*begin & 0x3f)) - 0x10000;
2572 str->append(prevbegin, tmpend);
2573 (*str)[str->size() - 2] =
2574 static_cast<char_type
>(0xd800 | (ch >> 10));
2575 (*str)[str->size() - 1] =
2576 static_cast<char_type
>(0xdc00 | (ch & 0x3ff));
2577 prevbegin = ++begin;
2595 template <
typename ForwardIterator>
2596 int parse_value_(ForwardIterator& begin,
const ForwardIterator end) {
2597 int ecode = json_error::ec_no_error;
2602 array_ =
new array_type();
2604 begin = skip_spaces_(++begin, end);
2608 ecode = json_error::ec_array;
2614 begin = skip_spaces_(++begin, end);
2618 array_->push_back(jsonnode());
2619 ecode = array_->back().parse_value_(begin, end);
2622 if (begin != end && *begin == 0x2C)
2623 begin = skip_spaces_(++begin, end);
2626 }
else if (*begin == 0x7B)
2630 object_ =
new object_type();
2632 begin = skip_spaces_(++begin, end);
2636 ecode = json_error::ec_object;
2642 begin = skip_spaces_(++begin, end);
2649 parse_string_(&key, ++begin, end, utftype());
2651 if (key.size() == 0) {
2652 ecode = json_error::ec_object_name;
2656 const typename object_core::iterator it = object_->objmap.find(key);
2659 if (it == object_->objmap.end()) {
2660 append_keyinfo_(object_->order, key, utftype());
2661 newnode = &object_->objmap[key];
2663 it->second.destroy_node_();
2664 it->second.type_ = unassigned;
2665 newnode = &it->second;
2668 if (begin == end || *begin != 0x3A)
2670 ecode = json_error::ec_no_colon;
2673 begin = skip_spaces_(++begin, end);
2675 ecode = newnode->parse_value_(begin, end);
2678 if (begin != end && *begin == 0x2C)
2679 begin = skip_spaces_(++begin, end);
2683 ecode = json_error::ec_object;
2688 }
else if (*begin == 0x22)
2690 string_ =
new strnum_type();
2692 if (parse_string_(&string_->str, ++begin, end, utftype())) {
2696 ecode = json_error::ec_string;
2698 }
else if (*begin == 0x74)
2700 if (++begin != end && *begin == 0x72)
2701 if (++begin != end && *begin == 0x75)
2702 if (++begin != end && *begin == 0x65)
2709 ecode = json_error::ec_literal;
2710 }
else if (*begin == 0x66)
2712 if (++begin != end && *begin == 0x61)
2713 if (++begin != end && *begin == 0x6C)
2714 if (++begin != end && *begin == 0x73)
2715 if (++begin != end && *begin == 0x65)
2722 ecode = json_error::ec_literal;
2723 }
else if (*begin == 0x6E)
2725 if (++begin != end && *begin == 0x75)
2726 if (++begin != end && *begin == 0x6C)
2727 if (++begin != end && *begin == 0x6C)
2733 ecode = json_error::ec_literal;
2735 ForwardIterator orgbegin = begin;
2736 nestring<char> cdigits;
2740 cdigits.push_back(
'-');
2747 cdigits.push_back(
'0');
2749 }
else if (*begin >= 0x31 && *begin <= 0x39)
2752 cdigits.push_back(
static_cast<char>(*begin - 0x30 +
'0'));
2753 }
while (++begin != end && *begin >= 0x30 &&
2757 cdigits.size() ? json_error::ec_number : json_error::ec_literal;
2761 ecode = json_error::ec_number;
2763 if (begin != end && *begin == 0x2E)
2765 cdigits.push_back(
'.');
2766 if (++begin == end || *begin < 0x30 || *begin > 0x39)
goto FAILED;
2769 cdigits.push_back(
static_cast<char>(*begin - 0x30 +
'0'));
2770 }
while (++begin != end && *begin >= 0x30 &&
2774 if (begin != end && (*begin | 0x20) == 0x65)
2776 cdigits.push_back(
'E');
2777 if (++begin == end)
goto FAILED;
2779 if (*begin == 0x2B || *begin == 0x2D)
2781 cdigits.push_back(*begin == 0x2B ?
'+' :
'-');
2785 if (begin == end || *begin < 0x30 || *begin > 0x39)
goto FAILED;
2788 cdigits.push_back(
static_cast<char>(*begin - 0x30 +
'0'));
2789 }
while (++begin != end && *begin >= 0x30 &&
2793 cdigits.push_back(0);
2795 string_ =
new strnum_type();
2796 string_->num = std::strtod(cdigits.data(), NULL);
2797 string_->str.assign(orgbegin, begin);
2798 begin = skip_spaces_(begin, end);
2807 void destroy_node_() {
2808 if (type_ == array) {
2812 if (array_)
delete array_;
2813 }
else if (type_ ==
object) {
2817 if (object_)
delete object_;
2818 }
else if (type_ ==
string || type_ == number) {
2819 if (string_)
delete string_;
2827 jsonnode& move_(jsonnode& right) {
2828 if (
this != &right && !is_fallback() && !right.is_fallback()) {
2829 if (type_ <
boolean) destroy_node_();
2831 type_ = right.type_;
2833 if (type_ == array) {
2834 array_ = right.array_;
2835 }
else if (type_ ==
object) {
2836 object_ = right.object_;
2837 }
else if (type_ == number || type_ ==
string) {
2838 string_ = right.string_;
2839 }
else if (type_ ==
boolean) {
2840 boolvalue_ = right.boolvalue_;
2842 right.type_ = unassigned;
2847 template <
typename StringT>
2848 void value_to_string_(StringT& out)
const {
2849 typedef typename StringT::value_type dchar_type;
2850 static const dchar_type quot = 0x22;
2851 static const dchar_type quotcolon[] = {0x22, 0x3A, 0};
2852 static const dchar_type ltrue[] = {0x74, 0x72, 0x75, 0x65, 0};
2853 static const dchar_type lfalse[] = {0x66, 0x61, 0x6C,
2855 static const dchar_type lnull[] = {0x6E, 0x75, 0x6C, 0x6C, 0};
2857 if (type_ == number) {
2858 const strsize_type base = out.size();
2860 out.resize(out.size() + string_->str.size());
2862 for (strsize_type i = 0; i < string_->str.size(); ++i)
2863 out[base + i] = string_->str[i];
2864 }
else if (type_ ==
string) {
2865 out.push_back(quot);
2866 escape_(out, string_->str, utftype());
2867 out.push_back(quot);
2868 }
else if (type_ ==
boolean)
2869 out.append(boolvalue_ ? ltrue : lfalse);
2870 else if (type_ == array) {
2871 out.push_back(0x5B);
2873 const strsize_type base = out.size();
2876 for (
typename array_type::size_type i = 0; i < array_->size(); ++i) {
2877 (*array_)[i].value_to_string_(out);
2878 out.push_back(0x2C);
2882 if (out.size() != base)
2883 out[out.size() - 1] = 0x5D;
2885 out.push_back(0x5D);
2886 }
else if (type_ ==
object) {
2887 out.push_back(0x7B);
2889 const strsize_type base = out.size();
2893 for (
typename object_core::const_iterator it = object_->objmap.begin(); it != object_->objmap.end(); ++it)
2895 out.push_back(quot);
2896 escape_(out, it->first, utftype());
2897 out.append(quotcolon);
2898 it->second.value_to_string_(out);
2899 out.push_back(0x2C);
2902 for (strsize_type pos = 0;
2903 (pos + keylen_size) < object_->order.size();) {
2904 const strsize_type keylen =
2905 get_keylen_(&object_->order[pos], utftype());
2907 const typename object_core::const_iterator it =
2908 object_->objmap.find(object_->order.view(pos, keylen));
2911 if (it != object_->objmap.end()) {
2912 out.push_back(quot);
2913 escape_(out, it->first, utftype());
2914 out.append(quotcolon);
2915 it->second.value_to_string_(out);
2916 out.push_back(0x2C);
2922 if (out.size() != base)
2923 out[out.size() - 1] = 0x7D;
2925 out.push_back(0x7D);
2930 void remove_orderkey_(
const sview_type key) {
2931 for (strsize_type pos = 0; (pos + keylen_size) < object_->order.size();) {
2932 const strsize_type keylen = get_keylen_(&object_->order[pos], utftype());
2933 const strsize_type keypos = pos + keylen_size;
2935 if (keylen == key.size()) {
2936 for (strsize_type i = 0;; ++i) {
2938 object_->order.erase(pos, keylen_size + keylen);
2941 if (object_->order[keypos + i] != key[i])
break;
2944 pos = keypos + keylen;
2948 template <
typename ForwardIterator>
2949 unsigned long parse_4hexdigits_(ForwardIterator& begin,
2950 const ForwardIterator end)
const {
2951 unsigned long ucp = 0ul;
2953 for (strsize_type i = 0; i < 4; ++i) {
2954 if (++begin != end) {
2957 if (b >= 0x30 && b <= 0x39)
2958 ucp = (ucp << 4) | (b - 0x30);
2961 if (b >= 0x61 && b <= 0x66)
2962 ucp = (ucp << 4) | (b - 0x61 + 10);
2974 template <
typename StringT,
typename UTFtype>
2975 void escape_(StringT& d,
const sview_type s,
const UTFtype)
const {
2976 typedef typename StringT::value_type dchar_type;
2977 typedef typename StringT::size_type dsize_type;
2979 const dsize_type base = d.size();
2981 d.append(s.begin(), s.end());
2983 for (dsize_type i = base; i < d.size(); ++i) {
2984 unsigned long ch = d[i];
2989 d[i++] =
static_cast<dchar_type
>(0x5c);
2990 d[i++] =
static_cast<dchar_type
>(0x75);
2991 d[i++] =
static_cast<dchar_type
>(0x30);
2992 d[i++] =
static_cast<dchar_type
>(0x30);
2993 d[i++] =
static_cast<dchar_type
>((ch >> 4) + 0x30);
2995 d[i] =
static_cast<dchar_type
>(ch + (ch < 10 ? 0x30 : 0x41 - 10));
2996 }
else if (ch == 0x22 || ch == 0x5c) {
2997 d.insert(i++, 1, 0x5c);
3004 template <
typename StringT>
3005 void escape_(StringT& d,
const sview_type s,
const utf16tag)
const {
3006 typedef typename StringT::value_type dchar_type;
3007 typedef typename StringT::size_type dsize_type;
3008 unsigned long prev = 0ul;
3010 d.reserve(d.size() + s.size());
3012 for (strsize_type i = 0; i < s.size(); ++i) {
3013 unsigned long ch = s[i] & 0xffff;
3017 dsize_type j = d.size();
3020 d[j++] =
static_cast<dchar_type
>(0x5c);
3021 d[j++] =
static_cast<dchar_type
>(0x75);
3022 d[j++] =
static_cast<dchar_type
>(0x30);
3023 d[j++] =
static_cast<dchar_type
>(0x30);
3024 d[j++] =
static_cast<dchar_type
>((ch >> 4) + 0x30);
3026 d[j] =
static_cast<dchar_type
>(ch + (ch < 10 ? 0x30 : 0x41 - 10));
3027 }
else if (ch == 0x22 || ch == 0x5c) {
3028 d.resize(d.size() + 2, 0x5c);
3029 d[d.size() - 1] =
static_cast<dchar_type
>(ch);
3030 }
else if (ch >= 0x80) {
3032 if (prev && ((ch - 0xdc00) < 0x400))
3034 dsize_type j = d.size();
3036 ch = (((prev & 0x3ff) << 10) | (ch & 0x3ff)) + 0x10000;
3038 d.resize(j + 1,
static_cast<dchar_type
>(0x80 | (ch & 0x3f)));
3039 d[j - 3] =
static_cast<dchar_type
>(0xf0 | (ch >> 18));
3040 d[j - 2] =
static_cast<dchar_type
>(0x80 | ((ch >> 12) & 0x3f));
3041 d[j - 1] =
static_cast<dchar_type
>(0x80 | ((ch >> 6) & 0x3f));
3043 dsize_type j = d.size();
3045 d.resize(j + 3,
static_cast<dchar_type
>(0x80 | (ch & 0x3f)));
3046 d[j++] =
static_cast<dchar_type
>(0xe0 | (ch >> 12));
3047 d[j++] =
static_cast<dchar_type
>(0x80 | ((ch >> 6) & 0x3f));
3049 prev = ((ch - 0xd800) < 0x400) ? ch : 0ul;
3054 dsize_type j = d.size();
3056 d.resize(j + 2,
static_cast<dchar_type
>(0x80 | (ch & 0x3f)));
3057 d[j] =
static_cast<dchar_type
>(0xc0 | (ch >> 6));
3060 d.push_back(
static_cast<dchar_type
>(ch));
3069 strnum_type* string_;
3071 object_type* object_;
3080 static jsonnode fallback_node_;
3081 static const char_type emptystr_[];
3085template <
typename charT,
typename utftype>
3086jsonnode<charT, utftype> jsonnode<charT, utftype>::fallback_node_(
3087 jsonnode<charT, utftype>::fallback);
3089template <
typename charT,
typename utftype>
3090const typename jsonnode<charT, utftype>::char_type
3091 jsonnode<charT, utftype>::emptystr_[] = {0};
3096typedef json_internal_::jsonnode<char, json_internal_::utf8tag> json;
3097typedef json_internal_::jsonnode<char, json_internal_::utf8tag> u8cjson;
3099#if defined(WCHAR_MAX) && (WCHAR_MAX >= 0xffff)
3100#if (WCHAR_MAX >= 0x10ffff)
3102typedef json_internal_::jsonnode<wchar_t, json_internal_::utf16tag> wjson;
3103typedef json_internal_::jsonnode<wchar_t, json_internal_::utf16tag> u16wjson;
3107#if defined(__cpp_unicode_characters)
3108typedef json_internal_::jsonnode<char16_t, json_internal_::utf16tag> u16json;
3111#if defined(__cpp_char8_t)
3112typedef json_internal_::jsonnode<char8_t, json_internal_::utf8tag> u8json;
std::string stringify(const Object &obj)
Convert a VDF object into a human-readable string.
Definition vdf.hpp:199