Skip to content

Commit

Permalink
Handle .pushKV() and .checkObject() edge cases.
Browse files Browse the repository at this point in the history
pushKV: Behave properly in the face of duplicate keys.

checkObject: return error, if not object.

Inspired-by: Charles Yin <[email protected]> in PR bitcoin#37
  • Loading branch information
jgarzik committed Aug 3, 2017
1 parent 107db98 commit ceb1194
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 6 deletions.
1 change: 1 addition & 0 deletions include/univalue.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class UniValue {
}
bool push_backV(const std::vector<UniValue>& vec);

void __pushKV(const std::string& key, const UniValue& val);
bool pushKV(const std::string& key, const UniValue& val);
bool pushKV(const std::string& key, const std::string& val_) {
UniValue tmpVal(VSTR, val_);
Expand Down
22 changes: 16 additions & 6 deletions lib/univalue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -126,13 +126,22 @@ bool UniValue::push_backV(const std::vector<UniValue>& vec)
return true;
}

void UniValue::__pushKV(const std::string& key, const UniValue& val_)
{
keys.push_back(key);
values.push_back(val_);
}

bool UniValue::pushKV(const std::string& key, const UniValue& val_)
{
if (typ != VOBJ)
return false;

keys.push_back(key);
values.push_back(val_);
size_t idx;
if (findKey(key, idx))
values[idx] = val_;
else
__pushKV(key, val_);
return true;
}

Expand All @@ -141,10 +150,8 @@ bool UniValue::pushKVs(const UniValue& obj)
if (typ != VOBJ || obj.typ != VOBJ)
return false;

for (unsigned int i = 0; i < obj.keys.size(); i++) {
keys.push_back(obj.keys[i]);
values.push_back(obj.values.at(i));
}
for (size_t i = 0; i < obj.keys.size(); i++)
__pushKV(obj.keys[i], obj.values.at(i));

return true;
}
Expand All @@ -163,6 +170,9 @@ bool UniValue::findKey(const std::string& key, size_t& retIdx) const

bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t)
{
if (typ != VOBJ)
return false;

for (std::map<std::string,UniValue::VType>::const_iterator it = t.begin();
it != t.end(); ++it) {
size_t idx = 0;
Expand Down
13 changes: 13 additions & 0 deletions test/object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,19 @@ BOOST_AUTO_TEST_CASE(univalue_object)
obj.clear();
BOOST_CHECK(obj.empty());
BOOST_CHECK_EQUAL(obj.size(), 0);
BOOST_CHECK_EQUAL(obj.getType(), UniValue::VNULL);

BOOST_CHECK_EQUAL(obj.setObject(), true);
UniValue uv;
uv.setInt(42);
obj.__pushKV("age", uv);
BOOST_CHECK_EQUAL(obj.size(), 1);
BOOST_CHECK_EQUAL(obj["age"].getValStr(), "42");

uv.setInt(43);
obj.pushKV("age", uv);
BOOST_CHECK_EQUAL(obj.size(), 1);
BOOST_CHECK_EQUAL(obj["age"].getValStr(), "43");
}

static const char *json1 =
Expand Down

0 comments on commit ceb1194

Please sign in to comment.