aboutsummaryrefslogtreecommitdiff
path: root/src/univalue
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2015-06-04 18:41:21 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2015-06-04 18:41:39 +0200
commit466f0ea0e66b88285c7797ab36ba777725324e83 (patch)
treee06cb762ad0fbb0b6b4c8274774d96868e416eb1 /src/univalue
parentdbd855023158e1c5ca2c5f0e8be552ecfb455834 (diff)
parent44c7474446d5a020bc06bf2f2b87572f42e54e9e (diff)
downloadbitcoin-466f0ea0e66b88285c7797ab36ba777725324e83.tar.xz
Merge pull request #6121
44c7474 univalue: add type check unit tests (Jonas Schnelli) c023092 univalue: add strict type checking (Wladimir J. van der Laan) 7e98a3c util: Add ParseInt64 and ParseDouble functions (Wladimir J. van der Laan) 043df2b Simplify RPCclient, adapt json_parse_error test (Wladimir J. van der Laan) 519eede fix univalue json parse tests (Jonas Schnelli) c7fbbc7 fix missing univalue types during constructing (Jonas Schnelli) 8f7e4ab fix rpc batching univalue issue (Jonas Schnelli) 9a8897f Remove JSON Spirit wrapper, remove JSON Spirit leftovers (Jonas Schnelli) 3df0411 remove JSON Spirit UniValue wrapper (Jonas Schnelli) 1f263c8 fix rpc unit test, plain numbers are not JSON compatible object (Jonas Schnelli) e04d9c2 univalue: correct bool support (Jonas Schnelli) 0c5b2cf univalue: add support for real, fix percision and make it json_spirit compatible (Jonas Schnelli) 21c10de special threatment for null,true,false because they are non valid json (Jonas Schnelli) 6c7bee0 expicit set UniValue type to avoid empty values (Jonas Schnelli) 53b4671 extend conversion to UniValue (Jonas Schnelli) 15982a8 Convert tree to using univalue. Eliminate all json_spirit uses. (Jeff Garzik) 5e3060c UniValue: export NullUniValue global constant (Jeff Garzik) efc7883 UniValue: prefer .size() to .count(), to harmonize w/ existing tree (Jeff Garzik)
Diffstat (limited to 'src/univalue')
-rw-r--r--src/univalue/univalue.cpp107
-rw-r--r--src/univalue/univalue.h101
-rw-r--r--src/univalue/univalue_write.cpp9
3 files changed, 207 insertions, 10 deletions
diff --git a/src/univalue/univalue.cpp b/src/univalue/univalue.cpp
index 4e445a542a..6920c44c96 100644
--- a/src/univalue/univalue.cpp
+++ b/src/univalue/univalue.cpp
@@ -4,12 +4,17 @@
#include <stdint.h>
#include <ctype.h>
+#include <iomanip>
#include <sstream>
+#include <stdexcept> // std::runtime_error
+
#include "univalue.h"
+#include "utilstrencodings.h" // ParseXX
+
using namespace std;
-static const UniValue nullValue;
+const UniValue NullUniValue;
void UniValue::clear()
{
@@ -78,9 +83,11 @@ bool UniValue::setFloat(double val)
string s;
ostringstream oss;
- oss << val;
+ oss << std::setprecision(16) << val;
- return setNumStr(oss.str());
+ bool ret = setNumStr(oss.str());
+ typ = VREAL;
+ return ret;
}
bool UniValue::setStr(const string& val_)
@@ -175,11 +182,11 @@ bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t)
const UniValue& UniValue::operator[](const std::string& key) const
{
if (typ != VOBJ)
- return nullValue;
+ return NullUniValue;
int index = findKey(key);
if (index < 0)
- return nullValue;
+ return NullUniValue;
return values[index];
}
@@ -187,9 +194,9 @@ const UniValue& UniValue::operator[](const std::string& key) const
const UniValue& UniValue::operator[](unsigned int index) const
{
if (typ != VOBJ && typ != VARR)
- return nullValue;
+ return NullUniValue;
if (index >= values.size())
- return nullValue;
+ return NullUniValue;
return values[index];
}
@@ -203,9 +210,95 @@ const char *uvTypeName(UniValue::VType t)
case UniValue::VARR: return "array";
case UniValue::VSTR: return "string";
case UniValue::VNUM: return "number";
+ case UniValue::VREAL: return "number";
}
// not reached
return NULL;
}
+const UniValue& find_value( const UniValue& obj, const std::string& name)
+{
+ for (unsigned int i = 0; i < obj.keys.size(); i++)
+ {
+ if( obj.keys[i] == name )
+ {
+ return obj.values[i];
+ }
+ }
+
+ return NullUniValue;
+}
+
+std::vector<std::string> UniValue::getKeys() const
+{
+ if (typ != VOBJ)
+ throw std::runtime_error("JSON value is not an object as expected");
+ return keys;
+}
+
+std::vector<UniValue> 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 88d73b8c64..79018bb787 100644
--- a/src/univalue/univalue.h
+++ b/src/univalue/univalue.h
@@ -11,9 +11,12 @@
#include <map>
#include <cassert>
+#include <sstream> // .get_int64()
+#include <utility> // std::pair
+
class UniValue {
public:
- enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
+ enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VREAL, VBOOL, };
UniValue() { typ = VNULL; }
UniValue(UniValue::VType initialType, const std::string& initialStr = "") {
@@ -26,6 +29,9 @@ public:
UniValue(int64_t val_) {
setInt(val_);
}
+ UniValue(bool val_) {
+ setBool(val_);
+ }
UniValue(int val_) {
setInt(val_);
}
@@ -58,7 +64,7 @@ public:
std::string getValStr() const { return val; }
bool empty() const { return (values.size() == 0); }
- size_t count() const { return values.size(); }
+ size_t size() const { return values.size(); }
bool getBool() const { return isTrue(); }
bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes);
@@ -68,10 +74,11 @@ 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); }
+ bool isReal() const { return (typ == VREAL); }
bool isArray() const { return (typ == VARR); }
bool isObject() const { return (typ == VOBJ); }
@@ -130,8 +137,91 @@ private:
int findKey(const std::string& key) const;
void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
+
+public:
+ // Strict type-specific getters, these throw std::runtime_error if the
+ // value is of unexpected type
+ std::vector<std::string> getKeys() const;
+ std::vector<UniValue> 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<std::string,UniValue> 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<std::string,UniValue> Pair(const char *cKey, const char *cVal)
+{
+ std::string key(cKey);
+ UniValue uVal(cVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, std::string strVal)
+{
+ std::string key(cKey);
+ UniValue uVal(strVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, uint64_t u64Val)
+{
+ std::string key(cKey);
+ UniValue uVal(u64Val);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, int64_t i64Val)
+{
+ std::string key(cKey);
+ UniValue uVal(i64Val);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, bool iVal)
+{
+ std::string key(cKey);
+ UniValue uVal(iVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, int iVal)
+{
+ std::string key(cKey);
+ UniValue uVal(iVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, double dVal)
+{
+ std::string key(cKey);
+ UniValue uVal(dVal);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(const char *cKey, const UniValue& uVal)
+{
+ std::string key(cKey);
+ return std::make_pair(key, uVal);
+}
+
+static inline std::pair<std::string,UniValue> Pair(std::string key, const UniValue& uVal)
+{
+ return std::make_pair(key, uVal);
+}
+
enum jtokentype {
JTOK_ERR = -1,
JTOK_NONE = 0, // eof
@@ -152,4 +242,9 @@ extern enum jtokentype getJsonToken(std::string& tokenVal,
unsigned int& consumed, const char *raw);
extern const char *uvTypeName(UniValue::VType t);
+extern const UniValue NullUniValue;
+
+const UniValue& find_value( const UniValue& obj, const std::string& name);
+
#endif // BITCOIN_UNIVALUE_UNIVALUE_H
+
diff --git a/src/univalue/univalue_write.cpp b/src/univalue/univalue_write.cpp
index 9a1d364c95..d360c253b0 100644
--- a/src/univalue/univalue_write.cpp
+++ b/src/univalue/univalue_write.cpp
@@ -3,6 +3,8 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <ctype.h>
+#include <iomanip>
+#include <sstream>
#include <stdio.h>
#include "univalue.h"
#include "univalue_escapes.h"
@@ -59,6 +61,13 @@ string UniValue::write(unsigned int prettyIndent,
case VSTR:
s += "\"" + json_escape(val) + "\"";
break;
+ case VREAL:
+ {
+ std::stringstream ss;
+ ss << std::showpoint << std::fixed << std::setprecision(8) << get_real();
+ s += ss.str();
+ }
+ break;
case VNUM:
s += val;
break;