From ceb1194137421afba01e8c1042bf75f3a2cdddc3 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Thu, 3 Aug 2017 10:18:59 -0400 Subject: [PATCH] Handle .pushKV() and .checkObject() edge cases. pushKV: Behave properly in the face of duplicate keys. checkObject: return error, if not object. Inspired-by: Charles Yin in PR #37 --- include/univalue.h | 1 + lib/univalue.cpp | 22 ++++++++++++++++------ test/object.cpp | 13 +++++++++++++ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/include/univalue.h b/include/univalue.h index c9a5690eed43d6..e732e27b532a7b 100644 --- a/include/univalue.h +++ b/include/univalue.h @@ -111,6 +111,7 @@ class UniValue { } bool push_backV(const std::vector& 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_); diff --git a/lib/univalue.cpp b/lib/univalue.cpp index af8f2203350dbc..97a38c9b97be69 100644 --- a/lib/univalue.cpp +++ b/lib/univalue.cpp @@ -126,13 +126,22 @@ bool UniValue::push_backV(const std::vector& 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; } @@ -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; } @@ -163,6 +170,9 @@ bool UniValue::findKey(const std::string& key, size_t& retIdx) const bool UniValue::checkObject(const std::map& t) { + if (typ != VOBJ) + return false; + for (std::map::const_iterator it = t.begin(); it != t.end(); ++it) { size_t idx = 0; diff --git a/test/object.cpp b/test/object.cpp index 7c4f21c85f57a5..c47f1048b354b6 100644 --- a/test/object.cpp +++ b/test/object.cpp @@ -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 =