diff --git a/include/hjson/hjson.h b/include/hjson/hjson.h index 3f794a9..92e45bd 100644 --- a/include/hjson/hjson.h +++ b/include/hjson/hjson.h @@ -293,6 +293,15 @@ class Value { Value& at(const std::string& key); const Value& at(const char *key) const; Value& at(const char *key); + +#if __cplusplus >= 201703L + // These are functions available in C++17 and greater only + // This function will add a value to a vector without a copy + void push_back(Value&&); + // This function can insert a value into the map without an allocation + void insert(const std::string&key, Value&&); +#endif // __cplusplus >= 201703L + // Iterations are always done in alphabetical key order. Returns a default // constructed iterator if this Value is of any other type than Map. std::map::iterator begin(); @@ -367,7 +376,7 @@ class MapProxy : public Value { MapProxy(Value&&); public: - ~MapProxy(); + ~MapProxy() override; MapProxy& operator =(const MapProxy&); MapProxy& operator =(const Value&); MapProxy& operator =(Value&&); diff --git a/src/hjson_value.cpp b/src/hjson_value.cpp index 38e2616..248ed02 100644 --- a/src/hjson_value.cpp +++ b/src/hjson_value.cpp @@ -347,6 +347,27 @@ Value& Value::at(const char *name) { return at(std::string(name)); } +#if __cplusplus >= 201703L +void Value::insert(const std::string&key, Value&& other) +{ + switch (prv->type) + { + case Type::Undefined: + prv->~ValueImpl(); + // Recreate the private object using the same memory block. + new(&(*prv)) ValueImpl(Type::Map); + // Fall through + case Type::Map: + try { + prv->m->m.insert_or_assign(key, std::move(other)); + } catch(const std::out_of_range&) {} + return; + default: + throw type_mismatch("Must be of type Map for that operation."); + } +} +#endif // __cplusplus >= 201703L + const Value Value::operator[](const std::string& name) const { if (prv->type == Type::Undefined) { @@ -1326,6 +1347,20 @@ void Value::push_back(const Value& other) { prv->v->push_back(other); } +#if __cplusplus >= 201703L +void Value::push_back(Value&& other) { + if (prv->type == Type::Undefined) { + prv->~ValueImpl(); + // Recreate the private object using the same memory block. + new(&(*prv)) ValueImpl(Type::Vector); + } else if (prv->type != Type::Vector) { + throw type_mismatch("Must be of type Undefined or Vector for that operation."); + } + + prv->v->push_back(std::move(other)); +} +#endif // __cplusplus >= 201703L + void Value::move(int from, int to) { switch (prv->type)