@@ -65,11 +65,12 @@ inline bool is_null(const value &v) noexcept;
6565// conversion (you get a copy)
6666inline std::string to_string (const value &v);
6767inline bool to_bool (const value &v);
68- inline double to_number (const value &v);
69- inline int64_t to_integer (const value &v);
7068inline object to_object (const value &v);
7169inline array to_array (const value &v);
7270
71+ template <class T , class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
72+ T to_number (const value &v);
73+
7374// interpretation (you get a reference)
7475inline object &as_object (value &v);
7576inline array &as_array (value &v);
@@ -91,9 +92,9 @@ inline value parse(NS::string_view s);
9192
9293// convert a value to a JSON string
9394enum Options {
94- None = 0x00 ,
95- EscapeUnicode = 0x01 ,
96- PrettyPrint = 0x02 ,
95+ None = 0x00 ,
96+ EscapeUnicode = 0x01 ,
97+ PrettyPrint = 0x02 ,
9798};
9899
99100constexpr inline Options operator &(Options lhs, Options rhs) noexcept {
@@ -205,6 +206,32 @@ void surrogate_pair_to_utf8(uint16_t w1, uint16_t w2, Out &out) {
205206 *out++ = static_cast <uint8_t >(0x80 | (cp & 0x3f ));
206207 }
207208}
209+
210+ template <class T >
211+ struct to_number_helper {};
212+
213+ template <> struct to_number_helper <float > { float convert (const value &v) { return stof (as_string (v), nullptr ); } };
214+ template <> struct to_number_helper <double > { double convert (const value &v) { return stod (as_string (v), nullptr ); } };
215+
216+ template <> struct to_number_helper <uint8_t > { uint8_t convert (const value &v) { return static_cast <uint8_t >(stoul (as_string (v), nullptr )); } };
217+ template <> struct to_number_helper <uint16_t > { uint16_t convert (const value &v) { return static_cast <uint16_t >(stoul (as_string (v), nullptr )); } };
218+ template <> struct to_number_helper <uint32_t > { uint32_t convert (const value &v) { return static_cast <uint32_t >(stoul (as_string (v), nullptr )); } };
219+ template <> struct to_number_helper <uint64_t > { uint64_t convert (const value &v) { return stoull (as_string (v), nullptr ); } };
220+
221+ template <> struct to_number_helper <int8_t > { int8_t convert (const value &v) { return static_cast <int8_t >(stol (as_string (v), nullptr )); } };
222+ template <> struct to_number_helper <int16_t > { int16_t convert (const value &v) { return static_cast <int16_t >(stol (as_string (v), nullptr )); } };
223+ template <> struct to_number_helper <int32_t > { int32_t convert (const value &v) { return static_cast <int32_t >(stol (as_string (v), nullptr )); } };
224+ template <> struct to_number_helper <int64_t > { int64_t convert (const value &v) { return stoll (as_string (v), nullptr ); } };
225+ }
226+
227+ template <class T , class >
228+ T to_number (const value &v) {
229+ if (!is_number (v)) {
230+ throw invalid_type_cast ();
231+ }
232+
233+ detail::to_number_helper<T> helper;
234+ return helper.convert (v);
208235}
209236
210237/* *
@@ -632,8 +659,8 @@ class value {
632659
633660public:
634661 // intialize from basic types
635- value (const array &a);
636- value (const object &o);
662+ explicit value (const array &a);
663+ explicit value (const object &o);
637664
638665 value (array &&a);
639666 value (object &&o);
@@ -723,6 +750,8 @@ class value {
723750 value operator [](const ptr &ptr) const ;
724751 value &operator [](const ptr &ptr);
725752
753+ value &create (const ptr &ptr);
754+
726755public:
727756 // array like interface
728757 template <class T >
@@ -1124,28 +1153,32 @@ inline bool to_bool(const value &v) {
11241153 return NS::get<value::Boolean>(v.storage_ ) == value::Boolean::True;
11251154}
11261155
1127- inline double to_number (const value &v) {
1128- if (!is_number (v)) {
1129- throw invalid_type_cast ();
1130- }
1156+ inline object to_object (const value &v) {
1157+ return as_object (v);
1158+ }
11311159
1132- return stod (as_string (v), nullptr );
1160+ inline array to_array (const value &v) {
1161+ return as_array (v);
11331162}
11341163
1135- inline int64_t to_integer ( const value &v) {
1136- if (! is_number (v)) {
1137- throw invalid_type_cast ();
1138- }
1164+ inline object & as_object (array &v) {
1165+ ( void )v;
1166+ throw invalid_type_cast ();
1167+ }
11391168
1140- return stoll (as_string (v), nullptr );
1169+ inline array &as_array (object &v) {
1170+ (void )v;
1171+ throw invalid_type_cast ();
11411172}
11421173
1143- inline object to_object (const value &v) {
1144- return as_object (v);
1174+ inline const object &as_object (const array &v) {
1175+ (void )v;
1176+ throw invalid_type_cast ();
11451177}
11461178
1147- inline array to_array (const value &v) {
1148- return as_array (v);
1179+ inline const array &as_array (const object &v) {
1180+ (void )v;
1181+ throw invalid_type_cast ();
11491182}
11501183
11511184inline object &as_object (value &v) {
@@ -1294,7 +1327,14 @@ inline std::string escape_string(NS::string_view s, Options options) {
12941327 r += " \\ t" ;
12951328 break ;
12961329 default :
1297- r += *it;
1330+ if (!isprint (*it)) {
1331+ r += " \\ u" ;
1332+ char buf[5 ];
1333+ snprintf (buf, sizeof (buf), " %04X" , *it);
1334+ r += buf;
1335+ } else {
1336+ r += *it;
1337+ }
12981338 break ;
12991339 }
13001340 } else if ((ch & 0xe0 ) == 0xc0 ) {
@@ -1514,43 +1554,43 @@ inline void value_to_string(std::ostream &os, const value &v, Options options) {
15141554}
15151555
15161556// serialize, not pretty printed
1517- inline void serialize_to_stream (std::ostream &os, const value &v, Options options);
1557+ inline void serialize (std::ostream &os, const value &v, Options options);
15181558
1519- inline void serialize_to_stream (std::ostream &os, const array &a, Options options) {
1559+ inline void serialize (std::ostream &os, const array &a, Options options) {
15201560 os << " [" ;
15211561 if (!a.empty ()) {
15221562 auto it = a.begin ();
15231563 auto e = a.end ();
15241564
1525- serialize_to_stream (os, *it++, options);
1565+ serialize (os, *it++, options);
15261566
15271567 for (; it != e; ++it) {
15281568 os << ' ,' ;
1529- serialize_to_stream (os, *it, options);
1569+ serialize (os, *it, options);
15301570 }
15311571 }
15321572 os << " ]" ;
15331573}
15341574
1535- inline void serialize_to_stream (std::ostream &os, const object &o, Options options) {
1575+ inline void serialize (std::ostream &os, const object &o, Options options) {
15361576 os << " {" ;
15371577 if (!o.empty ()) {
15381578 auto it = o.begin ();
15391579 auto e = o.end ();
15401580
15411581 os << ' "' << escape_string (it->first , options) << " \" :" ;
1542- serialize_to_stream (os, it->second , options);
1582+ serialize (os, it->second , options);
15431583 ++it;
15441584 for (; it != e; ++it) {
15451585 os << ' ,' ;
15461586 os << ' "' << escape_string (it->first , options) << " \" :" ;
1547- serialize_to_stream (os, it->second , options);
1587+ serialize (os, it->second , options);
15481588 }
15491589 }
15501590 os << " }" ;
15511591}
15521592
1553- inline void serialize_to_stream (std::ostream &os, const value &v, Options options) {
1593+ inline void serialize (std::ostream &os, const value &v, Options options) {
15541594
15551595 switch (v.type ()) {
15561596 case value::type_string:
@@ -1566,11 +1606,11 @@ inline void serialize_to_stream(std::ostream &os, const value &v, Options option
15661606 os << (to_bool (v) ? " true" : " false" );
15671607 break ;
15681608 case value::type_object: {
1569- serialize_to_stream (os, as_object (v), options);
1609+ serialize (os, as_object (v), options);
15701610 break ;
15711611 }
15721612 case value::type_array: {
1573- serialize_to_stream (os, as_array (v), options);
1613+ serialize (os, as_array (v), options);
15741614 break ;
15751615 }
15761616 case value::type_invalid:
@@ -1579,24 +1619,24 @@ inline void serialize_to_stream(std::ostream &os, const value &v, Options option
15791619}
15801620
15811621template <class T , class = typename std::enable_if<std::is_same<T, value>::value || std::is_same<T, object>::value || std::is_same<T, array>::value>::type>
1582- std::string serialize_to_string (const T &v, Options options) {
1622+ std::string serialize (const T &v, Options options) {
15831623 std::stringstream ss;
15841624
15851625 std::locale c_locale (" C" );
15861626 ss.imbue (c_locale);
15871627
1588- serialize_to_stream (ss, v, options);
1628+ serialize (ss, v, options);
15891629 return ss.str ();
15901630}
15911631
15921632template <class T , class = typename std::enable_if<std::is_same<T, value>::value || std::is_same<T, object>::value || std::is_same<T, array>::value>::type>
15931633std::string pretty_print (const T &v, Options options) {
1594- return value_to_string (v , options);
1634+ return value_to_string (value (v) , options);
15951635}
15961636
15971637template <class T , class = typename std::enable_if<std::is_same<T, value>::value || std::is_same<T, object>::value || std::is_same<T, array>::value>::type>
15981638void pretty_print (std::ostream &os, const T &v, Options options) {
1599- value_to_string (os, v , options);
1639+ value_to_string (os, value (v) , options);
16001640}
16011641
16021642}
@@ -1606,7 +1646,7 @@ std::string stringify(const T &v, Options options) {
16061646 if (options & Options::PrettyPrint) {
16071647 return detail::pretty_print (v, options);
16081648 } else {
1609- return detail::serialize_to_string (v, options);
1649+ return detail::serialize (v, options);
16101650 }
16111651}
16121652
@@ -1619,7 +1659,7 @@ void stringify(std::ostream &os, const T &v, Options options) {
16191659 if (options & Options::PrettyPrint) {
16201660 detail::pretty_print (os, v, options);
16211661 } else {
1622- detail::serialize_to_stream (os, v, options);
1662+ detail::serialize (os, v, options);
16231663 }
16241664}
16251665
@@ -1898,7 +1938,6 @@ inline value value::operator[](const ptr &ptr) const {
18981938 } else {
18991939 throw invalid_path ();
19001940 }
1901-
19021941 }
19031942
19041943 return *result;
@@ -1922,7 +1961,31 @@ inline value &value::operator[](const ptr &ptr) {
19221961 } else {
19231962 throw invalid_path ();
19241963 }
1964+ }
19251965
1966+ return *result;
1967+ }
1968+
1969+ inline value &value::create (const ptr &ptr) {
1970+ value *result = this ;
1971+ for (const std::string &ref : ptr) {
1972+
1973+ if (result->is_object ()) {
1974+ if (!has_key (result, ref)) {
1975+ result->insert (ref, object ());
1976+ }
1977+ result = &result->at (ref);
1978+ } else if (result->is_array ()) {
1979+ if (ref == " -" ) {
1980+ result->push_back (value ());
1981+ result = &result->at (result->size () - 1 );
1982+ } else {
1983+ std::size_t n = std::stoul (ref);
1984+ result = &result->at (n);
1985+ }
1986+ } else {
1987+ throw invalid_path ();
1988+ }
19261989 }
19271990
19281991 return *result;
@@ -1976,7 +2039,7 @@ inline bool operator==(const value &lhs, const value &rhs) {
19762039 case value::type_string:
19772040 return as_string (lhs) == as_string (rhs);
19782041 case value::type_number:
1979- return to_number (lhs) == to_number (rhs);
2042+ return to_number< double > (lhs) == to_number< double > (rhs);
19802043 case value::type_null:
19812044 return true ;
19822045 case value::type_boolean:
@@ -2239,6 +2302,8 @@ std::pair<object::iterator, bool> value::insert(std::pair<std::string, T> &&p) {
22392302}
22402303
22412304
2305+
2306+
22422307}
22432308
22442309#endif
0 commit comments