Skip to content

Commit d3cac7c

Browse files
committed
Implemented functions to create and modify values.
Implemented formatting print function.
1 parent ae4e732 commit d3cac7c

File tree

2 files changed

+239
-0
lines changed

2 files changed

+239
-0
lines changed

Include/cppcson.hpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,24 @@ class Value {
166166
public:
167167
using iterator = std::vector<Value>::const_iterator;
168168

169+
static Value newBool(bool value);
170+
171+
static Value newInt(int64_t value);
172+
173+
static Value newFloat(double value);
174+
175+
static Value newString(const std::string &value);
176+
177+
static Value newNull();
178+
179+
static Value newArray();
180+
181+
static Value newArray(std::vector<Value> &&list);
182+
183+
static Value newObject();
184+
185+
static Value newObject(std::map<std::string, Value> &&map);
186+
169187
Value(Value &&other) noexcept;
170188

171189
Value(const Value &) = delete;
@@ -214,6 +232,18 @@ class Value {
214232

215233
bool contains(const std::string &key) const;
216234

235+
void add(Value &&value);
236+
237+
void add(uint32_t index, Value &&value);
238+
239+
void add(const std::string &key, Value &&value);
240+
241+
bool remove(uint32_t index);
242+
243+
bool remove(const std::string &key);
244+
245+
void clear();
246+
217247
Keys keys() const;
218248

219249
iterator begin() const;
@@ -237,6 +267,8 @@ extern const Options DEFAULT_OPTIONS;
237267

238268
Value parse(std::istream &stream, const Options &options = DEFAULT_OPTIONS);
239269

270+
void print(std::ostream &stream, const Value &value);
271+
240272
std::string escapeKey(const std::string &str);
241273

242274
std::string escape(const std::string &str);

Source/cppcson.cpp

Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,52 @@ void Value::ensureKind(Value::Kind expected) const {
222222
}
223223
}
224224

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+
225271
Value::Value(Value &&other) noexcept
226272
: kind(other.kind), location(other.location), path(other.path),
227273
strValue(other.strValue), nonStrValue(other.nonStrValue) {
@@ -341,6 +387,84 @@ bool Value::contains(const std::string &key) const {
341387
return nonStrValue.objectValue->find(key) != nonStrValue.objectValue->end();
342388
}
343389

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+
344468
Keys Value::keys() const {
345469
ensureKind(Kind::Object);
346470

@@ -1220,6 +1344,89 @@ Value parse(std::istream &stream, const Options &options) {
12201344
return Parser(stream, options).parse();
12211345
}
12221346

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+
12231430
std::string escapeKey(const std::string &str) {
12241431
if (str.find_first_of(" \"\'\n\r\t\\.[],{}") == std::string::npos) {
12251432
return str;

0 commit comments

Comments
 (0)