diff options
Diffstat (limited to 'src/univalue/lib')
-rw-r--r-- | src/univalue/lib/univalue.cpp | 81 | ||||
-rw-r--r-- | src/univalue/lib/univalue_escapes.h | 262 | ||||
-rw-r--r-- | src/univalue/lib/univalue_get.cpp | 89 | ||||
-rw-r--r-- | src/univalue/lib/univalue_read.cpp | 13 | ||||
-rw-r--r-- | src/univalue/lib/univalue_utffilter.h | 119 | ||||
-rw-r--r-- | src/univalue/lib/univalue_write.cpp | 10 |
6 files changed, 69 insertions, 505 deletions
diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp index c4e59fae74..55e777b8ae 100644 --- a/src/univalue/lib/univalue.cpp +++ b/src/univalue/lib/univalue.cpp @@ -3,12 +3,15 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include <stdint.h> +#include <univalue.h> + #include <iomanip> +#include <map> +#include <memory> #include <sstream> -#include <stdlib.h> - -#include "univalue.h" +#include <string> +#include <utility> +#include <vector> const UniValue NullUniValue; @@ -20,19 +23,17 @@ void UniValue::clear() values.clear(); } -bool UniValue::setNull() +void UniValue::setNull() { clear(); - return true; } -bool UniValue::setBool(bool val_) +void UniValue::setBool(bool val_) { clear(); typ = VBOOL; if (val_) val = "1"; - return true; } static bool validNumStr(const std::string& s) @@ -43,18 +44,18 @@ static bool validNumStr(const std::string& s) return (tt == JTOK_NUMBER); } -bool UniValue::setNumStr(const std::string& val_) +void UniValue::setNumStr(const std::string& val_) { - if (!validNumStr(val_)) - return false; + if (!validNumStr(val_)) { + throw std::runtime_error{"The string '" + val_ + "' is not a valid JSON number"}; + } clear(); typ = VNUM; val = val_; - return true; } -bool UniValue::setInt(uint64_t val_) +void UniValue::setInt(uint64_t val_) { std::ostringstream oss; @@ -63,7 +64,7 @@ bool UniValue::setInt(uint64_t val_) return setNumStr(oss.str()); } -bool UniValue::setInt(int64_t val_) +void UniValue::setInt(int64_t val_) { std::ostringstream oss; @@ -72,86 +73,74 @@ bool UniValue::setInt(int64_t val_) return setNumStr(oss.str()); } -bool UniValue::setFloat(double val_) +void UniValue::setFloat(double val_) { std::ostringstream oss; oss << std::setprecision(16) << val_; - bool ret = setNumStr(oss.str()); - typ = VNUM; - return ret; + return setNumStr(oss.str()); } -bool UniValue::setStr(const std::string& val_) +void UniValue::setStr(const std::string& val_) { clear(); typ = VSTR; val = val_; - return true; } -bool UniValue::setArray() +void UniValue::setArray() { clear(); typ = VARR; - return true; } -bool UniValue::setObject() +void UniValue::setObject() { clear(); typ = VOBJ; - return true; } -bool UniValue::push_back(const UniValue& val_) +void UniValue::push_back(const UniValue& val_) { - if (typ != VARR) - return false; + checkType(VARR); values.push_back(val_); - return true; } -bool UniValue::push_backV(const std::vector<UniValue>& vec) +void UniValue::push_backV(const std::vector<UniValue>& vec) { - if (typ != VARR) - return false; + checkType(VARR); values.insert(values.end(), vec.begin(), vec.end()); - - return true; } void UniValue::__pushKV(const std::string& key, const UniValue& val_) { + checkType(VOBJ); + keys.push_back(key); values.push_back(val_); } -bool UniValue::pushKV(const std::string& key, const UniValue& val_) +void UniValue::pushKV(const std::string& key, const UniValue& val_) { - if (typ != VOBJ) - return false; + checkType(VOBJ); size_t idx; if (findKey(key, idx)) values[idx] = val_; else __pushKV(key, val_); - return true; } -bool UniValue::pushKVs(const UniValue& obj) +void UniValue::pushKVs(const UniValue& obj) { - if (typ != VOBJ || obj.typ != VOBJ) - return false; + checkType(VOBJ); + obj.checkType(VOBJ); for (size_t i = 0; i < obj.keys.size(); i++) __pushKV(obj.keys[i], obj.values.at(i)); - - return true; } void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const @@ -218,6 +207,14 @@ const UniValue& UniValue::operator[](size_t index) const return values.at(index); } +void UniValue::checkType(const VType& expected) const +{ + if (typ != expected) { + throw std::runtime_error{"JSON value of type " + std::string{uvTypeName(typ)} + " is not of expected type " + + std::string{uvTypeName(expected)}}; + } +} + const char *uvTypeName(UniValue::VType t) { switch (t) { diff --git a/src/univalue/lib/univalue_escapes.h b/src/univalue/lib/univalue_escapes.h deleted file mode 100644 index 3f714f8e5b..0000000000 --- a/src/univalue/lib/univalue_escapes.h +++ /dev/null @@ -1,262 +0,0 @@ -// Automatically generated file. Do not modify. -#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H -#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H -static const char *escapes[256] = { - "\\u0000", - "\\u0001", - "\\u0002", - "\\u0003", - "\\u0004", - "\\u0005", - "\\u0006", - "\\u0007", - "\\b", - "\\t", - "\\n", - "\\u000b", - "\\f", - "\\r", - "\\u000e", - "\\u000f", - "\\u0010", - "\\u0011", - "\\u0012", - "\\u0013", - "\\u0014", - "\\u0015", - "\\u0016", - "\\u0017", - "\\u0018", - "\\u0019", - "\\u001a", - "\\u001b", - "\\u001c", - "\\u001d", - "\\u001e", - "\\u001f", - nullptr, - nullptr, - "\\\"", - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - "\\\\", - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - "\\u007f", - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, -}; -#endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H diff --git a/src/univalue/lib/univalue_get.cpp b/src/univalue/lib/univalue_get.cpp index 5af89a3561..5c58f388dd 100644 --- a/src/univalue/lib/univalue_get.cpp +++ b/src/univalue/lib/univalue_get.cpp @@ -3,17 +3,18 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include <stdint.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <stdexcept> -#include <vector> +#include <univalue.h> + +#include <cerrno> +#include <cstdint> +#include <cstdlib> +#include <cstring> #include <limits> -#include <string> +#include <locale> #include <sstream> - -#include "univalue.h" +#include <stdexcept> +#include <string> +#include <vector> namespace { @@ -28,37 +29,6 @@ static bool ParsePrechecks(const std::string& str) return true; } -bool ParseInt32(const std::string& str, int32_t *out) -{ - if (!ParsePrechecks(str)) - return false; - char *endp = nullptr; - 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 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 && - n >= std::numeric_limits<int32_t>::min() && - n <= std::numeric_limits<int32_t>::max(); -} - -bool ParseInt64(const std::string& str, int64_t *out) -{ - if (!ParsePrechecks(str)) - return false; - char *endp = nullptr; - errno = 0; // strtoll will not set errno if valid - long long int n = strtoll(str.c_str(), &endp, 10); - if(out) *out = (int64_t)n; - // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow - // we still have to check that the returned value is within the range of an *int64_t*. - return endp && *endp == 0 && !errno && - n >= std::numeric_limits<int64_t>::min() && - n <= std::numeric_limits<int64_t>::max(); -} - bool ParseDouble(const std::string& str, double *out) { if (!ParsePrechecks(str)) @@ -76,8 +46,7 @@ bool ParseDouble(const std::string& str, double *out) const std::vector<std::string>& UniValue::getKeys() const { - if (typ != VOBJ) - throw std::runtime_error("JSON value is not an object as expected"); + checkType(VOBJ); return keys; } @@ -90,42 +59,19 @@ const std::vector<UniValue>& UniValue::getValues() const bool UniValue::get_bool() const { - if (typ != VBOOL) - throw std::runtime_error("JSON value is not a boolean as expected"); + checkType(VBOOL); return getBool(); } const std::string& UniValue::get_str() const { - if (typ != VSTR) - throw std::runtime_error("JSON value is not a string as expected"); + checkType(VSTR); return getValStr(); } -int UniValue::get_int() const -{ - if (typ != VNUM) - throw std::runtime_error("JSON value is not an integer as expected"); - int32_t retval; - if (!ParseInt32(getValStr(), &retval)) - throw std::runtime_error("JSON integer out of range"); - return retval; -} - -int64_t UniValue::get_int64() const -{ - if (typ != VNUM) - throw std::runtime_error("JSON value is not an integer as expected"); - int64_t retval; - if (!ParseInt64(getValStr(), &retval)) - throw std::runtime_error("JSON integer out of range"); - return retval; -} - double UniValue::get_real() const { - if (typ != VNUM) - throw std::runtime_error("JSON value is not a number as expected"); + checkType(VNUM); double retval; if (!ParseDouble(getValStr(), &retval)) throw std::runtime_error("JSON double out of range"); @@ -134,15 +80,12 @@ double UniValue::get_real() const const UniValue& UniValue::get_obj() const { - if (typ != VOBJ) - throw std::runtime_error("JSON value is not an object as expected"); + checkType(VOBJ); return *this; } const UniValue& UniValue::get_array() const { - if (typ != VARR) - throw std::runtime_error("JSON value is not an array as expected"); + checkType(VARR); return *this; } - diff --git a/src/univalue/lib/univalue_read.cpp b/src/univalue/lib/univalue_read.cpp index be39bfe57a..2f2385383c 100644 --- a/src/univalue/lib/univalue_read.cpp +++ b/src/univalue/lib/univalue_read.cpp @@ -2,11 +2,14 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include <string.h> +#include <univalue.h> +#include <univalue_utffilter.h> + +#include <cstdio> +#include <cstdint> +#include <cstring> +#include <string> #include <vector> -#include <stdio.h> -#include "univalue.h" -#include "univalue_utffilter.h" /* * According to stackexchange, the original json test suite wanted @@ -14,7 +17,7 @@ * so we will follow PHP's lead, which should be more than sufficient * (further stackexchange comments indicate depth > 32 rarely occurs). */ -static const size_t MAX_JSON_DEPTH = 512; +static constexpr size_t MAX_JSON_DEPTH = 512; static bool json_isdigit(int ch) { diff --git a/src/univalue/lib/univalue_utffilter.h b/src/univalue/lib/univalue_utffilter.h deleted file mode 100644 index c24ac58eaf..0000000000 --- a/src/univalue/lib/univalue_utffilter.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2016 Wladimir J. van der Laan -// Distributed under the MIT software license, see the accompanying -// file COPYING or https://opensource.org/licenses/mit-license.php. -#ifndef UNIVALUE_UTFFILTER_H -#define UNIVALUE_UTFFILTER_H - -#include <string> - -/** - * Filter that generates and validates UTF-8, as well as collates UTF-16 - * surrogate pairs as specified in RFC4627. - */ -class JSONUTF8StringFilter -{ -public: - explicit JSONUTF8StringFilter(std::string &s): - str(s), is_valid(true), codepoint(0), state(0), surpair(0) - { - } - // Write single 8-bit char (may be part of UTF-8 sequence) - void push_back(unsigned char ch) - { - if (state == 0) { - if (ch < 0x80) // 7-bit ASCII, fast direct pass-through - str.push_back(ch); - else if (ch < 0xc0) // Mid-sequence character, invalid in this state - is_valid = false; - else if (ch < 0xe0) { // Start of 2-byte sequence - codepoint = (ch & 0x1f) << 6; - state = 6; - } else if (ch < 0xf0) { // Start of 3-byte sequence - codepoint = (ch & 0x0f) << 12; - state = 12; - } else if (ch < 0xf8) { // Start of 4-byte sequence - codepoint = (ch & 0x07) << 18; - state = 18; - } else // Reserved, invalid - is_valid = false; - } else { - if ((ch & 0xc0) != 0x80) // Not a continuation, invalid - is_valid = false; - state -= 6; - codepoint |= (ch & 0x3f) << state; - if (state == 0) - push_back_u(codepoint); - } - } - // Write codepoint directly, possibly collating surrogate pairs - void push_back_u(unsigned int codepoint_) - { - if (state) // Only accept full codepoints in open state - is_valid = false; - if (codepoint_ >= 0xD800 && codepoint_ < 0xDC00) { // First half of surrogate pair - if (surpair) // Two subsequent surrogate pair openers - fail - is_valid = false; - else - surpair = codepoint_; - } else if (codepoint_ >= 0xDC00 && codepoint_ < 0xE000) { // Second half of surrogate pair - if (surpair) { // Open surrogate pair, expect second half - // Compute code point from UTF-16 surrogate pair - append_codepoint(0x10000 | ((surpair - 0xD800)<<10) | (codepoint_ - 0xDC00)); - surpair = 0; - } else // Second half doesn't follow a first half - fail - is_valid = false; - } else { - if (surpair) // First half of surrogate pair not followed by second - fail - is_valid = false; - else - append_codepoint(codepoint_); - } - } - // Check that we're in a state where the string can be ended - // No open sequences, no open surrogate pairs, etc - bool finalize() - { - if (state || surpair) - is_valid = false; - return is_valid; - } -private: - std::string &str; - bool is_valid; - // Current UTF-8 decoding state - unsigned int codepoint; - int state; // Top bit to be filled in for next UTF-8 byte, or 0 - - // Keep track of the following state to handle the following section of - // RFC4627: - // - // To escape an extended character that is not in the Basic Multilingual - // Plane, the character is represented as a twelve-character sequence, - // encoding the UTF-16 surrogate pair. So, for example, a string - // containing only the G clef character (U+1D11E) may be represented as - // "\uD834\uDD1E". - // - // Two subsequent \u.... may have to be replaced with one actual codepoint. - unsigned int surpair; // First half of open UTF-16 surrogate pair, or 0 - - void append_codepoint(unsigned int codepoint_) - { - if (codepoint_ <= 0x7f) - str.push_back((char)codepoint_); - else if (codepoint_ <= 0x7FF) { - str.push_back((char)(0xC0 | (codepoint_ >> 6))); - str.push_back((char)(0x80 | (codepoint_ & 0x3F))); - } else if (codepoint_ <= 0xFFFF) { - str.push_back((char)(0xE0 | (codepoint_ >> 12))); - str.push_back((char)(0x80 | ((codepoint_ >> 6) & 0x3F))); - str.push_back((char)(0x80 | (codepoint_ & 0x3F))); - } else if (codepoint_ <= 0x1FFFFF) { - str.push_back((char)(0xF0 | (codepoint_ >> 18))); - str.push_back((char)(0x80 | ((codepoint_ >> 12) & 0x3F))); - str.push_back((char)(0x80 | ((codepoint_ >> 6) & 0x3F))); - str.push_back((char)(0x80 | (codepoint_ & 0x3F))); - } - } -}; - -#endif diff --git a/src/univalue/lib/univalue_write.cpp b/src/univalue/lib/univalue_write.cpp index 3a2c580c7f..4a3cbba20f 100644 --- a/src/univalue/lib/univalue_write.cpp +++ b/src/univalue/lib/univalue_write.cpp @@ -2,10 +2,12 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or https://opensource.org/licenses/mit-license.php. -#include <iomanip> -#include <stdio.h> -#include "univalue.h" -#include "univalue_escapes.h" +#include <univalue.h> +#include <univalue_escapes.h> + +#include <memory> +#include <string> +#include <vector> static std::string json_escape(const std::string& inS) { |