Skip to content

Commit

Permalink
keep insertion order in merge and clone
Browse files Browse the repository at this point in the history
  • Loading branch information
trobro committed Jul 12, 2020
1 parent 8171026 commit 0ce1954
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 12 deletions.
4 changes: 3 additions & 1 deletion README.md
Expand Up @@ -29,7 +29,7 @@ The C++ implementation of Hjson is based on [hjson-go](https://github.com/hjson/

# Compiling

The easiest way to use hjson-cpp is to simply include all of the files from the folders `src` and `include` into you own project. The only requirement is that your compiler fully supports C++11.
The easiest way to use hjson-cpp is to simply include all of the files from the folders `src` and `include` into your own project. The only requirement is that your compiler fully supports C++11.

GCC 4.8 has the C++11 headers for regex, but unfortunately not a working implementation, so for GCC at least version 4.9 is required.

Expand Down Expand Up @@ -247,6 +247,8 @@ assert(val1.key(1) == "zeta");
assert(val1[0] == 2);
```
The insertion order is kept when cloning or merging *Hjson::Value* maps.
### Performance
Hjson is not much optimized for speed. But if you require fast(-ish) execution, escpecially in a multithreaded application, you can experiment with different values for the Cmake option `HJSON_NUMBER_PARSER`. The default value `StringStream` uses C++ string streams with the locale `classic` imbued to ensure that dots are used as decimal separators rather than commas.
Expand Down
18 changes: 11 additions & 7 deletions src/hjson_value.cpp
Expand Up @@ -741,8 +741,8 @@ Value Value::clone() const {
case ValueImpl::IMPL_MAP:
{
Value ret;
for (auto it = begin(); it != end(); ++it) {
ret[it->first] = it->second.clone();
for (int index = 0; index < size(); ++index) {
ret[key(index)] = operator[](index).clone();
}
return ret;
}
Expand Down Expand Up @@ -1209,13 +1209,17 @@ Value Merge(const Value base, const Value ext) {
if (!ext.defined()) {
merged = base.clone();
} else if (base.type() == Value::MAP && ext.type() == Value::MAP) {
for (auto it = ext.begin(); it != ext.end(); ++it) {
merged[it->first] = Merge(base[it->first], it->second);
for (int index = 0; index < base.size(); ++index) {
if (ext[base.key(index)].defined()) {
merged[base.key(index)] = Merge(base[index], ext[base.key(index)]);
} else {
merged[base.key(index)] = base[index].clone();
}
}

for (auto it = base.begin(); it != base.end(); ++it) {
if (!merged[it->first].defined()) {
merged[it->first] = it->second.clone();
for (int index = 0; index < ext.size(); ++index) {
if (!merged[ext.key(index)].defined()) {
merged[ext.key(index)] = ext[index].clone();
}
}
} else {
Expand Down
16 changes: 12 additions & 4 deletions test/test_value.cpp
Expand Up @@ -650,8 +650,7 @@ void test_value() {
}

{
Hjson::Value base = Hjson::Unmarshal(R"(
{
std::string baseStr = R"({
debug: false
rect: {
x: 0
Expand All @@ -672,8 +671,8 @@ void test_value() {
width: 200
height: 200
}
}
)");
})";
Hjson::Value base = Hjson::Unmarshal(baseStr);

Hjson::Value ext = Hjson::Unmarshal(R"(
{
Expand Down Expand Up @@ -704,5 +703,14 @@ void test_value() {
assert(merged["scale"] == 3);
assert(merged["window"]["y"] == 37);
assert(merged["otherWindow"]["x"] == 17);
// The insertion order must have been kept in the merge.
assert(merged.key(1) == "rect");
// The insertion order must have been kept in the clone.
auto baseClone = base.clone();
auto options = Hjson::DefaultOptions();
options.bracesSameLine = true;
options.preserveInsertionOrder = true;
auto baseCloneStr = Hjson::MarshalWithOptions(baseClone, options);
assert(baseCloneStr == baseStr);
}
}

0 comments on commit 0ce1954

Please sign in to comment.