Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements on HJson creation #47

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion include/hjson/hjson.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<std::string, Value>::iterator begin();
Expand Down Expand Up @@ -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&&);
Expand Down
35 changes: 35 additions & 0 deletions src/hjson_value.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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&) {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would cause std::out_of_range to be thrown, and why should it be ignored?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right in that it does not make a lot of sense, maybe just not have a catch and throw whatever exception came from the container?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes better to not have a catch.

return;
default:
throw type_mismatch("Must be of type Map for that operation.");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation seems to support type Undefined too, not just type Map.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true, this implementation follows a similar scheme as to that of operator [] , where if the Value is of type undefined, we assume the user wanted map and thus we convert it to a map type and then treat it as a map insertion.

}
}
#endif // __cplusplus >= 201703L


const Value Value::operator[](const std::string& name) const {
if (prv->type == Type::Undefined) {
Expand Down Expand Up @@ -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)
Expand Down