@@ -222,6 +222,52 @@ void Value::ensureKind(Value::Kind expected) const {
222
222
}
223
223
}
224
224
225
+ Value Value::newBool (bool value) {
226
+ return Value::fromBool (Location::unknown (), " " , value);
227
+ }
228
+
229
+ Value Value::newInt (int64_t value) {
230
+ return Value::fromInt (Location::unknown (), " " , value);
231
+ }
232
+
233
+ Value Value::newFloat (double value) {
234
+ return Value::fromFloat (Location::unknown (), " " , value);
235
+ }
236
+
237
+ Value Value::newString (const std::string &value) {
238
+ return Value::fromString (Location::unknown (), " " , value);
239
+ }
240
+
241
+ Value Value::newNull () { return Value::fromNull (Location::unknown (), " " ); }
242
+
243
+ Value Value::newArray () {
244
+ return Value::fromArray (Location::unknown (), " " , &EMPTY_VECTOR);
245
+ }
246
+
247
+ Value Value::newArray (std::vector<Value> &&list) {
248
+ const std::vector<Value> *arrayValue = &EMPTY_VECTOR;
249
+
250
+ if (!list.empty ()) {
251
+ arrayValue = new std::vector<Value>(std::move (list));
252
+ }
253
+
254
+ return Value::fromArray (Location::unknown (), " " , arrayValue);
255
+ }
256
+
257
+ Value Value::newObject () {
258
+ return Value::fromObject (Location::unknown (), " " , &EMPTY_MAP);
259
+ }
260
+
261
+ Value Value::newObject (std::map<std::string, Value> &&map) {
262
+ const std::map<std::string, Value> *objectValue = &EMPTY_MAP;
263
+
264
+ if (!map.empty ()) {
265
+ objectValue = new std::map<std::string, Value>(std::move (map));
266
+ }
267
+
268
+ return Value::fromObject (Location::unknown (), " " , objectValue);
269
+ }
270
+
225
271
Value::Value (Value &&other) noexcept
226
272
: kind(other.kind), location(other.location), path(other.path),
227
273
strValue(other.strValue), nonStrValue(other.nonStrValue) {
@@ -341,6 +387,84 @@ bool Value::contains(const std::string &key) const {
341
387
return nonStrValue.objectValue ->find (key) != nonStrValue.objectValue ->end ();
342
388
}
343
389
390
+ void Value::add (Value &&value) {
391
+ ensureKind (Kind::Array);
392
+
393
+ if (nonStrValue.arrayValue == &EMPTY_VECTOR) {
394
+ nonStrValue.arrayValue = new std::vector<Value>();
395
+ }
396
+
397
+ const_cast <std::vector<Value> *>(nonStrValue.arrayValue )
398
+ ->push_back (std::move (value));
399
+ }
400
+
401
+ void Value::add (uint32_t index, Value &&value) {
402
+ ensureKind (Kind::Array);
403
+
404
+ if (nonStrValue.arrayValue == &EMPTY_VECTOR) {
405
+ nonStrValue.arrayValue = new std::vector<Value>();
406
+ }
407
+
408
+ const_cast <std::vector<Value> *>(nonStrValue.arrayValue )
409
+ ->insert (nonStrValue.arrayValue ->begin () + index, std::move (value));
410
+ }
411
+
412
+ void Value::add (const std::string &key, Value &&value) {
413
+ ensureKind (Kind::Object);
414
+
415
+ if (nonStrValue.objectValue == &EMPTY_MAP) {
416
+ nonStrValue.objectValue = new std::map<std::string, Value>();
417
+ }
418
+
419
+ const_cast <std::map<std::string, Value> *>(nonStrValue.objectValue )
420
+ ->emplace (key, std::move (value));
421
+ }
422
+
423
+ bool Value::remove (uint32_t index) {
424
+ ensureKind (Kind::Array);
425
+
426
+ if (index < nonStrValue.arrayValue ->size ()) {
427
+ const_cast <std::vector<Value> *>(nonStrValue.arrayValue )
428
+ ->erase (nonStrValue.arrayValue ->begin () + index);
429
+ return true ;
430
+ }
431
+
432
+ return false ;
433
+ }
434
+
435
+ bool Value::remove (const std::string &key) {
436
+ ensureKind (Kind::Object);
437
+
438
+ auto itr = nonStrValue.objectValue ->find (key);
439
+ if (itr != nonStrValue.objectValue ->end ()) {
440
+ const_cast <std::map<std::string, Value> *>(nonStrValue.objectValue )
441
+ ->erase (itr);
442
+ return true ;
443
+ }
444
+
445
+ return false ;
446
+ }
447
+
448
+ void Value::clear () {
449
+ switch (kind) {
450
+ case Kind::Array: {
451
+ if (nonStrValue.arrayValue != &EMPTY_VECTOR) {
452
+ const_cast <std::vector<Value> *>(nonStrValue.arrayValue )->clear ();
453
+ }
454
+ break ;
455
+ }
456
+ case Kind::Object: {
457
+ if (nonStrValue.objectValue != &EMPTY_MAP) {
458
+ const_cast <std::map<std::string, Value> *>(nonStrValue.objectValue )
459
+ ->clear ();
460
+ }
461
+ break ;
462
+ }
463
+ default :
464
+ break ;
465
+ }
466
+ }
467
+
344
468
Keys Value::keys () const {
345
469
ensureKind (Kind::Object);
346
470
@@ -1220,6 +1344,89 @@ Value parse(std::istream &stream, const Options &options) {
1220
1344
return Parser (stream, options).parse ();
1221
1345
}
1222
1346
1347
+ static void print (std::ostream &stream, const Value &value, int32_t indent,
1348
+ bool topMost) {
1349
+ switch (value.getKind ()) {
1350
+ case Value::Kind::Bool: {
1351
+ stream << (value.asBool () ? " true" : " false" );
1352
+ break ;
1353
+ }
1354
+ case Value::Kind::Int: {
1355
+ stream << value.asInt ();
1356
+ break ;
1357
+ }
1358
+ case Value::Kind::Float: {
1359
+ stream << value.asFloat ();
1360
+ break ;
1361
+ }
1362
+ case Value::Kind::String: {
1363
+ stream << escape (value.asString ());
1364
+ break ;
1365
+ }
1366
+ case Value::Kind::Null: {
1367
+ stream << " null" ;
1368
+ break ;
1369
+ }
1370
+ case Value::Kind::Array: {
1371
+ stream << " [" ;
1372
+ if (value.getItemCount () == 0 ) {
1373
+ stream << " ]" ;
1374
+ } else {
1375
+ indent += 2 ;
1376
+
1377
+ for (uint32_t i = 0 ; i < value.getItemCount (); ++i) {
1378
+ if (i > 0 && value.item (i - 1 ).getKind () == Value::Kind::Object) {
1379
+ stream << " \n " << std::string (indent - 2 , ' ' ) << " ," ;
1380
+ }
1381
+
1382
+ stream << " \n " << std::string (indent, ' ' );
1383
+ print (stream, value.item (i), indent, false );
1384
+ }
1385
+
1386
+ indent -= 2 ;
1387
+ stream << " \n " << std::string (indent, ' ' ) << " ]" ;
1388
+ }
1389
+ break ;
1390
+ }
1391
+ case Value::Kind::Object: {
1392
+ if (value.getItemCount () == 0 ) {
1393
+ stream << " {}" ;
1394
+ } else {
1395
+ if (!topMost) {
1396
+ indent += 2 ;
1397
+ }
1398
+
1399
+ auto first = true ;
1400
+ for (auto &key : value.keys ()) {
1401
+ auto &itemValue = value.item (key);
1402
+
1403
+ if (first) {
1404
+ first = false ;
1405
+ } else {
1406
+ stream << " \n " << std::string (indent, ' ' );
1407
+ }
1408
+
1409
+ stream << escapeKey (key) << " :" ;
1410
+
1411
+ if (itemValue.getKind () == Value::Kind::Object) {
1412
+ stream << " \n " << std::string (indent + 2 , ' ' );
1413
+ } else {
1414
+ stream << " " ;
1415
+ }
1416
+ print (stream, itemValue, indent, false );
1417
+ }
1418
+ }
1419
+ break ;
1420
+ }
1421
+ default :
1422
+ unreachable ();
1423
+ }
1424
+ }
1425
+
1426
+ void print (std::ostream &stream, const Value &value) {
1427
+ print (stream, value, 0 , true );
1428
+ }
1429
+
1223
1430
std::string escapeKey (const std::string &str) {
1224
1431
if (str.find_first_of (" \"\'\n\r\t\\ .[],{}" ) == std::string::npos) {
1225
1432
return str;
0 commit comments