From c02309204b8195476945f7066e8d96c60246db08 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Thu, 4 Jun 2015 11:40:03 +0200 Subject: univalue: add strict type checking --- src/univalue/univalue.cpp | 79 ++++++++++++++++++++++++++++++++++++++++++++++- src/univalue/univalue.h | 32 ++++++++----------- 2 files changed, 91 insertions(+), 20 deletions(-) (limited to 'src/univalue') diff --git a/src/univalue/univalue.cpp b/src/univalue/univalue.cpp index e8fc513433..6920c44c96 100644 --- a/src/univalue/univalue.cpp +++ b/src/univalue/univalue.cpp @@ -6,8 +6,12 @@ #include #include #include +#include // std::runtime_error + #include "univalue.h" +#include "utilstrencodings.h" // ParseXX + using namespace std; const UniValue NullUniValue; @@ -224,4 +228,77 @@ const UniValue& find_value( const UniValue& obj, const std::string& name) } return NullUniValue; -} \ No newline at end of file +} + +std::vector UniValue::getKeys() const +{ + if (typ != VOBJ) + throw std::runtime_error("JSON value is not an object as expected"); + return keys; +} + +std::vector UniValue::getValues() const +{ + if (typ != VOBJ && typ != VARR) + throw std::runtime_error("JSON value is not an object or array as expected"); + return values; +} + +bool UniValue::get_bool() const +{ + if (typ != VBOOL) + throw std::runtime_error("JSON value is not a boolean as expected"); + return getBool(); +} + +std::string UniValue::get_str() const +{ + if (typ != VSTR) + throw std::runtime_error("JSON value is not a string as expected"); + 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 != VREAL && typ != VNUM) + throw std::runtime_error("JSON value is not a number as expected"); + double retval; + if (!ParseDouble(getValStr(), &retval)) + throw std::runtime_error("JSON double out of range"); + return retval; +} + +const UniValue& UniValue::get_obj() const +{ + if (typ != VOBJ) + throw std::runtime_error("JSON value is not an object as expected"); + return *this; +} + +const UniValue& UniValue::get_array() const +{ + if (typ != VARR) + throw std::runtime_error("JSON value is not an array as expected"); + return *this; +} + diff --git a/src/univalue/univalue.h b/src/univalue/univalue.h index 57a96abe26..79018bb787 100644 --- a/src/univalue/univalue.h +++ b/src/univalue/univalue.h @@ -13,7 +13,6 @@ #include // .get_int64() #include // std::pair -#include // atoi(), atof() TODO: remove class UniValue { public: @@ -75,7 +74,7 @@ public: bool isNull() const { return (typ == VNULL); } bool isTrue() const { return (typ == VBOOL) && (val == "1"); } - bool isFalse() const { return (!isTrue()); } + bool isFalse() const { return (typ == VBOOL) && (val != "1"); } bool isBool() const { return (typ == VBOOL); } bool isStr() const { return (typ == VSTR); } bool isNum() const { return (typ == VNUM); } @@ -140,27 +139,22 @@ private: void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const; public: - // - // The following were added for compatibility with json_spirit. - // Most duplicate other methods, and should be removed. - // - std::vector getKeys() const { return keys; } - std::vector getValues() const { return values; } - bool get_bool() const { return getBool(); } - std::string get_str() const { return getValStr(); } - int get_int() const { return atoi(getValStr().c_str()); } - double get_real() const { return atof(getValStr().c_str()); } - const UniValue& get_obj() const { return *this; } - const UniValue& get_array() const { return *this; } + // Strict type-specific getters, these throw std::runtime_error if the + // value is of unexpected type + std::vector getKeys() const; + std::vector getValues() const; + bool get_bool() const; + std::string get_str() const; + int get_int() const; + int64_t get_int64() const; + double get_real() const; + const UniValue& get_obj() const; + const UniValue& get_array() const; + enum VType type() const { return getType(); } bool push_back(std::pair pear) { return pushKV(pear.first, pear.second); } - int64_t get_int64() const { - int64_t ret; - std::istringstream(getValStr()) >> ret; - return ret; - } friend const UniValue& find_value( const UniValue& obj, const std::string& name); }; -- cgit v1.2.3