@@ -65,11 +65,12 @@ inline bool is_null(const value &v) noexcept;
65
65
// conversion (you get a copy)
66
66
inline std::string to_string (const value &v);
67
67
inline bool to_bool (const value &v);
68
- inline double to_number (const value &v);
69
- inline int64_t to_integer (const value &v);
70
68
inline object to_object (const value &v);
71
69
inline array to_array (const value &v);
72
70
71
+ template <class T , class = typename std::enable_if<std::is_arithmetic<T>::value>::type>
72
+ T to_number (const value &v);
73
+
73
74
// interpretation (you get a reference)
74
75
inline object &as_object (value &v);
75
76
inline array &as_array (value &v);
@@ -91,9 +92,9 @@ inline value parse(NS::string_view s);
91
92
92
93
// convert a value to a JSON string
93
94
enum Options {
94
- None = 0x00 ,
95
- EscapeUnicode = 0x01 ,
96
- PrettyPrint = 0x02 ,
95
+ None = 0x00 ,
96
+ EscapeUnicode = 0x01 ,
97
+ PrettyPrint = 0x02 ,
97
98
};
98
99
99
100
constexpr 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) {
205
206
*out++ = static_cast <uint8_t >(0x80 | (cp & 0x3f ));
206
207
}
207
208
}
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);
208
235
}
209
236
210
237
/* *
@@ -632,8 +659,8 @@ class value {
632
659
633
660
public:
634
661
// 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);
637
664
638
665
value (array &&a);
639
666
value (object &&o);
@@ -723,6 +750,8 @@ class value {
723
750
value operator [](const ptr &ptr) const ;
724
751
value &operator [](const ptr &ptr);
725
752
753
+ value &create (const ptr &ptr);
754
+
726
755
public:
727
756
// array like interface
728
757
template <class T >
@@ -1124,28 +1153,32 @@ inline bool to_bool(const value &v) {
1124
1153
return NS::get<value::Boolean>(v.storage_ ) == value::Boolean::True;
1125
1154
}
1126
1155
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
+ }
1131
1159
1132
- return stod (as_string (v), nullptr );
1160
+ inline array to_array (const value &v) {
1161
+ return as_array (v);
1133
1162
}
1134
1163
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
+ }
1139
1168
1140
- return stoll (as_string (v), nullptr );
1169
+ inline array &as_array (object &v) {
1170
+ (void )v;
1171
+ throw invalid_type_cast ();
1141
1172
}
1142
1173
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 ();
1145
1177
}
1146
1178
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 ();
1149
1182
}
1150
1183
1151
1184
inline object &as_object (value &v) {
@@ -1294,7 +1327,14 @@ inline std::string escape_string(NS::string_view s, Options options) {
1294
1327
r += " \\ t" ;
1295
1328
break ;
1296
1329
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
+ }
1298
1338
break ;
1299
1339
}
1300
1340
} else if ((ch & 0xe0 ) == 0xc0 ) {
@@ -1514,43 +1554,43 @@ inline void value_to_string(std::ostream &os, const value &v, Options options) {
1514
1554
}
1515
1555
1516
1556
// 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);
1518
1558
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) {
1520
1560
os << " [" ;
1521
1561
if (!a.empty ()) {
1522
1562
auto it = a.begin ();
1523
1563
auto e = a.end ();
1524
1564
1525
- serialize_to_stream (os, *it++, options);
1565
+ serialize (os, *it++, options);
1526
1566
1527
1567
for (; it != e; ++it) {
1528
1568
os << ' ,' ;
1529
- serialize_to_stream (os, *it, options);
1569
+ serialize (os, *it, options);
1530
1570
}
1531
1571
}
1532
1572
os << " ]" ;
1533
1573
}
1534
1574
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) {
1536
1576
os << " {" ;
1537
1577
if (!o.empty ()) {
1538
1578
auto it = o.begin ();
1539
1579
auto e = o.end ();
1540
1580
1541
1581
os << ' "' << escape_string (it->first , options) << " \" :" ;
1542
- serialize_to_stream (os, it->second , options);
1582
+ serialize (os, it->second , options);
1543
1583
++it;
1544
1584
for (; it != e; ++it) {
1545
1585
os << ' ,' ;
1546
1586
os << ' "' << escape_string (it->first , options) << " \" :" ;
1547
- serialize_to_stream (os, it->second , options);
1587
+ serialize (os, it->second , options);
1548
1588
}
1549
1589
}
1550
1590
os << " }" ;
1551
1591
}
1552
1592
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) {
1554
1594
1555
1595
switch (v.type ()) {
1556
1596
case value::type_string:
@@ -1566,11 +1606,11 @@ inline void serialize_to_stream(std::ostream &os, const value &v, Options option
1566
1606
os << (to_bool (v) ? " true" : " false" );
1567
1607
break ;
1568
1608
case value::type_object: {
1569
- serialize_to_stream (os, as_object (v), options);
1609
+ serialize (os, as_object (v), options);
1570
1610
break ;
1571
1611
}
1572
1612
case value::type_array: {
1573
- serialize_to_stream (os, as_array (v), options);
1613
+ serialize (os, as_array (v), options);
1574
1614
break ;
1575
1615
}
1576
1616
case value::type_invalid:
@@ -1579,24 +1619,24 @@ inline void serialize_to_stream(std::ostream &os, const value &v, Options option
1579
1619
}
1580
1620
1581
1621
template <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) {
1583
1623
std::stringstream ss;
1584
1624
1585
1625
std::locale c_locale (" C" );
1586
1626
ss.imbue (c_locale);
1587
1627
1588
- serialize_to_stream (ss, v, options);
1628
+ serialize (ss, v, options);
1589
1629
return ss.str ();
1590
1630
}
1591
1631
1592
1632
template <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>
1593
1633
std::string pretty_print (const T &v, Options options) {
1594
- return value_to_string (v , options);
1634
+ return value_to_string (value (v) , options);
1595
1635
}
1596
1636
1597
1637
template <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>
1598
1638
void 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);
1600
1640
}
1601
1641
1602
1642
}
@@ -1606,7 +1646,7 @@ std::string stringify(const T &v, Options options) {
1606
1646
if (options & Options::PrettyPrint) {
1607
1647
return detail::pretty_print (v, options);
1608
1648
} else {
1609
- return detail::serialize_to_string (v, options);
1649
+ return detail::serialize (v, options);
1610
1650
}
1611
1651
}
1612
1652
@@ -1619,7 +1659,7 @@ void stringify(std::ostream &os, const T &v, Options options) {
1619
1659
if (options & Options::PrettyPrint) {
1620
1660
detail::pretty_print (os, v, options);
1621
1661
} else {
1622
- detail::serialize_to_stream (os, v, options);
1662
+ detail::serialize (os, v, options);
1623
1663
}
1624
1664
}
1625
1665
@@ -1898,7 +1938,6 @@ inline value value::operator[](const ptr &ptr) const {
1898
1938
} else {
1899
1939
throw invalid_path ();
1900
1940
}
1901
-
1902
1941
}
1903
1942
1904
1943
return *result;
@@ -1922,7 +1961,31 @@ inline value &value::operator[](const ptr &ptr) {
1922
1961
} else {
1923
1962
throw invalid_path ();
1924
1963
}
1964
+ }
1925
1965
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
+ }
1926
1989
}
1927
1990
1928
1991
return *result;
@@ -1976,7 +2039,7 @@ inline bool operator==(const value &lhs, const value &rhs) {
1976
2039
case value::type_string:
1977
2040
return as_string (lhs) == as_string (rhs);
1978
2041
case value::type_number:
1979
- return to_number (lhs) == to_number (rhs);
2042
+ return to_number< double > (lhs) == to_number< double > (rhs);
1980
2043
case value::type_null:
1981
2044
return true ;
1982
2045
case value::type_boolean:
@@ -2239,6 +2302,8 @@ std::pair<object::iterator, bool> value::insert(std::pair<std::string, T> &&p) {
2239
2302
}
2240
2303
2241
2304
2305
+
2306
+
2242
2307
}
2243
2308
2244
2309
#endif
0 commit comments