diff --git a/src/univalue/.travis.yml b/src/univalue/.travis.yml index 132743d34..43a1ed362 100644 --- a/src/univalue/.travis.yml +++ b/src/univalue/.travis.yml @@ -25,7 +25,6 @@ addons: - pkg-config before_script: - - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew uninstall libtool; brew install libtool; fi - if [ -n "$USE_SHELL" ]; then export CONFIG_SHELL="$USE_SHELL"; fi - test -n "$USE_SHELL" && eval '"$USE_SHELL" -c "./autogen.sh"' || ./autogen.sh diff --git a/src/univalue/README.md b/src/univalue/README.md index 4a496f6bf..7c62c3397 100644 --- a/src/univalue/README.md +++ b/src/univalue/README.md @@ -12,33 +12,10 @@ an arbitrary depth. This class is aligned with the JSON standard, [RFC 7159](https://tools.ietf.org/html/rfc7159.html). -## Motivation +## Library usage -UniValue is a reaction to json_spirit, seeking to minimize template -and memory use, providing a straightforward RAII class compatible with -link-time optimization and embedded uses. - -## Status - -The current production version is available from the [stable-1.0.x branch](https://github.com/jgarzik/univalue/tree/stable-1.0.x). - -The current development series is 1.1.x, and is pushed to the `master` branch. - -The next stable version will be 1.2.0, to be released immediately -following the conclusion of the 1.1.x series, similar to [this -variant](https://en.wikipedia.org/wiki/Software_versioning#Odd-numbered_versions_for_development_releases) -of semver. - -## Installation - -This project is a standard GNU -[autotools](https://www.gnu.org/software/automake/manual/html_node/Autotools-Introduction.html) -project. Build and install instructions are available in the `INSTALL` -file provided with GNU autotools. - -``` -$ ./autogen.sh -$ ./configure -$ make -``` +This is a fork of univalue used by Bitcoin Core. It is not maintained for usage +by other projects. Notably, the API may break in non-backward-compatible ways. +Other projects looking for a maintained library should use the upstream +univalue at https://github.com/jgarzik/univalue. diff --git a/src/univalue/configure.ac b/src/univalue/configure.ac index 16c7ef7af..39cd00621 100644 --- a/src/univalue/configure.ac +++ b/src/univalue/configure.ac @@ -1,7 +1,7 @@ m4_define([libunivalue_major_version], [1]) m4_define([libunivalue_minor_version], [1]) -m4_define([libunivalue_micro_version], [4]) -m4_define([libunivalue_interface_age], [4]) +m4_define([libunivalue_micro_version], [3]) +m4_define([libunivalue_interface_age], [3]) # If you need a modifier for the version number. # Normally empty, but can be used to make "fixup" releases. m4_define([libunivalue_extraversion], []) @@ -14,7 +14,7 @@ m4_define([libunivalue_age], [m4_eval(libunivalue_binary_age - libunivalue_inter m4_define([libunivalue_version], [libunivalue_major_version().libunivalue_minor_version().libunivalue_micro_version()libunivalue_extraversion()]) -AC_INIT([univalue], [1.1.1], +AC_INIT([univalue], [1.0.3], [https://github.com/jgarzik/univalue/]) dnl make the compilation flags quiet unless V=1 is used diff --git a/src/univalue/include/univalue.h b/src/univalue/include/univalue.h index 996e75e30..ff81e26a4 100644 --- a/src/univalue/include/univalue.h +++ b/src/univalue/include/univalue.h @@ -14,14 +14,17 @@ #include #include -#include // std::pair +#include // .get_int64() class UniValue { public: enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, }; - UniValue() : typ(VNULL) {} - UniValue(UniValue::VType type, const std::string& value = std::string()) : typ(type), val(value) {} + UniValue() { typ = VNULL; } + UniValue(UniValue::VType initialType, const std::string& initialStr = "") { + typ = initialType; + val = initialStr; + } UniValue(uint64_t val_) { setInt(val_); } @@ -46,15 +49,6 @@ public: } void clear(); - void reserve(size_t n) { - if (typ == VOBJ || typ == VARR) { - if (typ == VOBJ) - keys.reserve(n); - values.reserve(n); - } else if (typ != VNULL) { - val.reserve(n); - } - } bool setNull(); bool setBool(bool val); @@ -90,10 +84,66 @@ public: bool isObject() const { return (typ == VOBJ); } bool push_back(const UniValue& val); + bool push_back(const std::string& val_) { + UniValue tmpVal(VSTR, val_); + return push_back(tmpVal); + } + bool push_back(const char *val_) { + std::string s(val_); + return push_back(s); + } + bool push_back(uint64_t val_) { + UniValue tmpVal(val_); + return push_back(tmpVal); + } + bool push_back(int64_t val_) { + UniValue tmpVal(val_); + return push_back(tmpVal); + } + bool push_back(bool val_) { + UniValue tmpVal(val_); + return push_back(tmpVal); + } + bool push_back(int val_) { + UniValue tmpVal(val_); + return push_back(tmpVal); + } + bool push_back(double val_) { + UniValue tmpVal(val_); + return push_back(tmpVal); + } 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_); + return pushKV(key, tmpVal); + } + bool pushKV(const std::string& key, const char *val_) { + std::string _val(val_); + return pushKV(key, _val); + } + bool pushKV(const std::string& key, int64_t val_) { + UniValue tmpVal(val_); + return pushKV(key, tmpVal); + } + bool pushKV(const std::string& key, uint64_t val_) { + UniValue tmpVal(val_); + return pushKV(key, tmpVal); + } + bool pushKV(const std::string& key, bool val_) { + UniValue tmpVal(val_); + return pushKV(key, tmpVal); + } + bool pushKV(const std::string& key, int val_) { + UniValue tmpVal((int64_t)val_); + return pushKV(key, tmpVal); + } + bool pushKV(const std::string& key, double val_) { + UniValue tmpVal(val_); + return pushKV(key, tmpVal); + } bool pushKVs(const UniValue& obj); std::string write(unsigned int prettyIndent = 0, @@ -129,76 +179,9 @@ public: const UniValue& get_array() const; enum VType type() const { return getType(); } - bool push_back(std::pair pear) { - return pushKV(pear.first, pear.second); - } friend const UniValue& find_value( const UniValue& obj, const std::string& name); }; -// -// The following were added for compatibility with json_spirit. -// Most duplicate other methods, and should be removed. -// -static inline std::pair Pair(const char *cKey, const char *cVal) -{ - std::string key(cKey); - UniValue uVal(cVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, std::string strVal) -{ - std::string key(cKey); - UniValue uVal(strVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, uint64_t u64Val) -{ - std::string key(cKey); - UniValue uVal(u64Val); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, int64_t i64Val) -{ - std::string key(cKey); - UniValue uVal(i64Val); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, bool iVal) -{ - std::string key(cKey); - UniValue uVal(iVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, int iVal) -{ - std::string key(cKey); - UniValue uVal(iVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, double dVal) -{ - std::string key(cKey); - UniValue uVal(dVal); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(const char *cKey, const UniValue& uVal) -{ - std::string key(cKey); - return std::make_pair(key, uVal); -} - -static inline std::pair Pair(std::string key, const UniValue& uVal) -{ - return std::make_pair(key, uVal); -} - enum jtokentype { JTOK_ERR = -1, JTOK_NONE = 0, // eof diff --git a/src/univalue/lib/univalue_get.cpp b/src/univalue/lib/univalue_get.cpp index 8b2da7555..293a49487 100644 --- a/src/univalue/lib/univalue_get.cpp +++ b/src/univalue/lib/univalue_get.cpp @@ -11,7 +11,6 @@ #include #include #include -#include #include "univalue.h" @@ -36,7 +35,7 @@ bool ParseInt32(const std::string& str, int32_t *out) errno = 0; // strtol will not set errno if valid long int n = strtol(str.c_str(), &endp, 10); if(out) *out = (int32_t)n; - // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow + // Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit // platforms the size of these types may be different. return endp && *endp == 0 && !errno && diff --git a/src/univalue/lib/univalue_read.cpp b/src/univalue/lib/univalue_read.cpp index 7c17c4bec..f8a5d4d76 100644 --- a/src/univalue/lib/univalue_read.cpp +++ b/src/univalue/lib/univalue_read.cpp @@ -273,7 +273,7 @@ bool UniValue::read(const char *raw, size_t size) tok = getJsonToken(tokenVal, consumed, raw, end); if (tok == JTOK_NONE || tok == JTOK_ERR) - goto return_fail; + return false; raw += consumed; bool isValueOpen = jsonTokenIsValue(tok) || @@ -281,33 +281,33 @@ bool UniValue::read(const char *raw, size_t size) if (expect(VALUE)) { if (!isValueOpen) - goto return_fail; + return false; clearExpect(VALUE); } else if (expect(ARR_VALUE)) { bool isArrValue = isValueOpen || (tok == JTOK_ARR_CLOSE); if (!isArrValue) - goto return_fail; + return false; clearExpect(ARR_VALUE); } else if (expect(OBJ_NAME)) { bool isObjName = (tok == JTOK_OBJ_CLOSE || tok == JTOK_STRING); if (!isObjName) - goto return_fail; + return false; } else if (expect(COLON)) { if (tok != JTOK_COLON) - goto return_fail; + return false; clearExpect(COLON); } else if (!expect(COLON) && (tok == JTOK_COLON)) { - goto return_fail; + return false; } if (expect(NOT_VALUE)) { if (isValueOpen) - goto return_fail; + return false; clearExpect(NOT_VALUE); } @@ -332,7 +332,7 @@ bool UniValue::read(const char *raw, size_t size) } if (stack.size() > MAX_JSON_DEPTH) - goto return_fail; + return false; if (utyp == VOBJ) setExpect(OBJ_NAME); @@ -344,12 +344,12 @@ bool UniValue::read(const char *raw, size_t size) case JTOK_OBJ_CLOSE: case JTOK_ARR_CLOSE: { if (!stack.size() || (last_tok == JTOK_COMMA)) - goto return_fail; + return false; VType utyp = (tok == JTOK_OBJ_CLOSE ? VOBJ : VARR); UniValue *top = stack.back(); if (utyp != top->getType()) - goto return_fail; + return false; stack.pop_back(); clearExpect(OBJ_NAME); @@ -359,11 +359,11 @@ bool UniValue::read(const char *raw, size_t size) case JTOK_COLON: { if (!stack.size()) - goto return_fail; + return false; UniValue *top = stack.back(); if (top->getType() != VOBJ) - goto return_fail; + return false; setExpect(VALUE); break; @@ -372,7 +372,7 @@ bool UniValue::read(const char *raw, size_t size) case JTOK_COMMA: { if (!stack.size() || (last_tok == JTOK_COMMA) || (last_tok == JTOK_ARR_OPEN)) - goto return_fail; + return false; UniValue *top = stack.back(); if (top->getType() == VOBJ) @@ -446,19 +446,15 @@ bool UniValue::read(const char *raw, size_t size) } default: - goto return_fail; + return false; } } while (!stack.empty ()); /* Check that nothing follows the initial construct (parsed above). */ tok = getJsonToken(tokenVal, consumed, raw, end); if (tok != JTOK_NONE) - goto return_fail; + return false; return true; - -return_fail: - clear(); - return false; } diff --git a/src/univalue/lib/univalue_write.cpp b/src/univalue/lib/univalue_write.cpp index db039fcb0..d31414edd 100644 --- a/src/univalue/lib/univalue_write.cpp +++ b/src/univalue/lib/univalue_write.cpp @@ -3,6 +3,7 @@ // file COPYING or https://opensource.org/licenses/mit-license.php. #include +#include #include #include "univalue.h" #include "univalue_escapes.h" diff --git a/src/univalue/test/object.cpp b/src/univalue/test/object.cpp index b2b86dc1a..042acfe45 100644 --- a/src/univalue/test/object.cpp +++ b/src/univalue/test/object.cpp @@ -142,8 +142,6 @@ BOOST_AUTO_TEST_CASE(univalue_set) BOOST_CHECK(v.isArray()); BOOST_CHECK_EQUAL(v.size(), 0); - BOOST_CHECK(v.setStr("")); - v.reserve(3); BOOST_CHECK(v.setStr("zum")); BOOST_CHECK(v.isStr()); BOOST_CHECK_EQUAL(v.getValStr(), "zum"); @@ -189,7 +187,6 @@ BOOST_AUTO_TEST_CASE(univalue_set) BOOST_AUTO_TEST_CASE(univalue_array) { UniValue arr(UniValue::VARR); - arr.reserve(9); UniValue v((int64_t)1023LL); BOOST_CHECK(arr.push_back(v)); @@ -213,19 +210,31 @@ BOOST_AUTO_TEST_CASE(univalue_array) BOOST_CHECK(arr.push_back((int64_t) -400LL)); BOOST_CHECK(arr.push_back((int) -401)); BOOST_CHECK(arr.push_back(-40.1)); + BOOST_CHECK(arr.push_back(true)); BOOST_CHECK_EQUAL(arr.empty(), false); - BOOST_CHECK_EQUAL(arr.size(), 9); + BOOST_CHECK_EQUAL(arr.size(), 10); BOOST_CHECK_EQUAL(arr[0].getValStr(), "1023"); + BOOST_CHECK_EQUAL(arr[0].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[1].getValStr(), "zippy"); + BOOST_CHECK_EQUAL(arr[1].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[2].getValStr(), "pippy"); + BOOST_CHECK_EQUAL(arr[2].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[3].getValStr(), "boing"); + BOOST_CHECK_EQUAL(arr[3].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[4].getValStr(), "going"); + BOOST_CHECK_EQUAL(arr[4].getType(), UniValue::VSTR); BOOST_CHECK_EQUAL(arr[5].getValStr(), "400"); + BOOST_CHECK_EQUAL(arr[5].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[6].getValStr(), "-400"); + BOOST_CHECK_EQUAL(arr[6].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[7].getValStr(), "-401"); + BOOST_CHECK_EQUAL(arr[7].getType(), UniValue::VNUM); BOOST_CHECK_EQUAL(arr[8].getValStr(), "-40.1"); + BOOST_CHECK_EQUAL(arr[8].getType(), UniValue::VNUM); + BOOST_CHECK_EQUAL(arr[9].getValStr(), "1"); + BOOST_CHECK_EQUAL(arr[9].getType(), UniValue::VBOOL); BOOST_CHECK_EQUAL(arr[999].getValStr(), ""); @@ -240,8 +249,6 @@ BOOST_AUTO_TEST_CASE(univalue_object) std::string strKey, strVal; UniValue v; - obj.reserve(11); - strKey = "age"; v.setInt(100); BOOST_CHECK(obj.pushKV(strKey, v));