[Pkg-bitcoin-commits] [libunivalue] 16/76: sync with bitcoin/src/univalue
Jonas Smedegaard
dr at jones.dk
Mon Apr 4 09:18:28 UTC 2016
This is an automated email from the git hooks/post-receive script.
js pushed a commit to branch master
in repository libunivalue.
commit d0ec6ad70f2a1590138adbcbb78ab8f0c1f8a47e
Author: Jonas Schnelli <jonas.schnelli at include7.ch>
Date: Thu Aug 20 18:25:42 2015 +0200
sync with bitcoin/src/univalue
+ add optional num parsing functions
---
Makefile.am | 5 +-
gen.cpp | 77 ++++++++++++++++
numberparse.cpp | 66 ++++++++++++++
numberparse.h | 18 ++++
univalue.cpp | 250 ++++++++++++++++++++++++++++++++++++++++++--------
univalue.h | 218 ++++++++++++++++++++++++++++++++++++++------
univalue_escapes.h | 262 +++++++++++++++++++++++++++++++++++++++++++++++++++++
univalue_read.cpp | 128 ++++++++++++--------------
univalue_write.cpp | 67 +++++---------
9 files changed, 909 insertions(+), 182 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 62d4d7f..75a58fe 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,12 +1,13 @@
-include_HEADERS = univalue.h
+include_HEADERS = univalue.h univalue_escapes.h
lib_LIBRARIES = libunivalue.a
libunivalue_a_SOURCES = \
univalue.cpp \
univalue_read.cpp \
- univalue_write.cpp
+ univalue_write.cpp \
+ numberparse.cpp
TESTS = unitester
diff --git a/gen.cpp b/gen.cpp
new file mode 100644
index 0000000..5e5a4d4
--- /dev/null
+++ b/gen.cpp
@@ -0,0 +1,77 @@
+// Copyright 2014 BitPay Inc.
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+//
+// To re-create univalue_escapes.h:
+// $ g++ -o gen gen.cpp
+// $ ./gen > univalue_escapes.h
+//
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+#include "univalue.h"
+
+using namespace std;
+
+static bool initEscapes;
+static const char *escapes[256];
+
+static void initJsonEscape()
+{
+ escapes[(int)'"'] = "\\\"";
+ escapes[(int)'\\'] = "\\\\";
+ escapes[(int)'\b'] = "\\b";
+ escapes[(int)'\f'] = "\\f";
+ escapes[(int)'\n'] = "\\n";
+ escapes[(int)'\r'] = "\\r";
+ escapes[(int)'\t'] = "\\t";
+
+ initEscapes = true;
+}
+
+static void outputEscape()
+{
+ printf( "// Automatically generated file. Do not modify.\n"
+ "#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n"
+ "#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n"
+ "static const char *escapes[256] = {\n");
+
+ for (unsigned int i = 0; i < 256; i++) {
+ if (!escapes[i]) {
+ printf("\tNULL,\n");
+ } else {
+ printf("\t\"");
+
+ unsigned int si;
+ for (si = 0; si < strlen(escapes[i]); si++) {
+ char ch = escapes[i][si];
+ switch (ch) {
+ case '"':
+ printf("\\\"");
+ break;
+ case '\\':
+ printf("\\\\");
+ break;
+ default:
+ printf("%c", escapes[i][si]);
+ break;
+ }
+ }
+
+ printf("\",\n");
+ }
+ }
+
+ printf( "};\n"
+ "#endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H\n");
+}
+
+int main (int argc, char *argv[])
+{
+ initJsonEscape();
+ outputEscape();
+ return 0;
+}
+
diff --git a/numberparse.cpp b/numberparse.cpp
new file mode 100644
index 0000000..feb18fb
--- /dev/null
+++ b/numberparse.cpp
@@ -0,0 +1,66 @@
+// Copyright 2015 Bitcoin Core Developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#include "numberparse.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <locale>
+#include <sstream>
+
+static bool ParsePrechecks(const std::string& str)
+{
+ if (str.empty()) // No empty string allowed
+ return false;
+ if (str.size() >= 1 && (isspace(str[0]) || isspace(str[str.size()-1]))) // No padding allowed
+ return false;
+ if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
+ return false;
+ return true;
+}
+
+bool ParseInt32(const std::string& str, int32_t *out)
+{
+ if (!ParsePrechecks(str))
+ return false;
+ char *endp = NULL;
+ 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
+ // 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 = NULL;
+ 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))
+ return false;
+ if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
+ return false;
+ std::istringstream text(str);
+ text.imbue(std::locale::classic());
+ double result;
+ text >> result;
+ if(out) *out = result;
+ return text.eof() && !text.fail();
+}
\ No newline at end of file
diff --git a/numberparse.h b/numberparse.h
new file mode 100644
index 0000000..7a91634
--- /dev/null
+++ b/numberparse.h
@@ -0,0 +1,18 @@
+// Copyright 2015 Bitcoin Core Developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
+#ifndef __UNIVALUE_NUMBERPARSE_H__
+#define __UNIVALUE_NUMBERPARSE_H__
+
+#include <stdint.h>
+#include <ctype.h>
+
+#include <string>
+
+static bool ParsePrechecks(const std::string& str);
+bool ParseInt32(const std::string& str, int32_t *out);
+bool ParseInt64(const std::string& str, int64_t *out);
+bool ParseDouble(const std::string& str, double *out);
+
+#endif //__UNIVALUE_NUMBERPARSE_H__
\ No newline at end of file
diff --git a/univalue.cpp b/univalue.cpp
index 996aa2a..8244d87 100644
--- a/univalue.cpp
+++ b/univalue.cpp
@@ -1,14 +1,28 @@
// Copyright 2014 BitPay Inc.
-// Distributed under the MIT/X11 software license, see the accompanying
+// Copyright 2015 Bitcoin Core Developers
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <stdint.h>
#include <ctype.h>
+#include <iomanip>
#include <sstream>
+#include <stdexcept>
+
#include "univalue.h"
+#ifdef EXTERNAL_NUM_PARSE
+extern bool ParseInt32(const std::string& str, int32_t *out);
+extern bool ParseInt64(const std::string& str, int64_t *out);
+extern bool ParseDouble(const std::string& str, double *out);
+#else
+#include "numberparse.h"
+#endif
+
using namespace std;
+const UniValue NullUniValue;
+
void UniValue::clear()
{
typ = VNULL;
@@ -23,48 +37,26 @@ bool UniValue::setNull()
return true;
}
-bool UniValue::setBool(bool val)
+bool UniValue::setBool(bool val_)
{
clear();
- typ = (val ? VTRUE : VFALSE);
+ typ = VBOOL;
+ if (val_)
+ val = "1";
return true;
}
static bool validNumStr(const string& s)
{
- bool seenDec = false;
- for (unsigned int i = 0; i < s.size(); i++) {
- switch (s[i]) {
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
- // do nothing
- break;
-
- case '.':
- if (seenDec)
- return false;
- seenDec = true;
- break;
-
- default:
- return false;
- }
- }
-
- return true;
+ string tokenVal;
+ unsigned int consumed;
+ enum jtokentype tt = getJsonToken(tokenVal, consumed, s.c_str());
+ return (tt == JTOK_NUMBER);
}
-bool UniValue::setNumStr(string val_)
+bool UniValue::setNumStr(const string& val_)
{
- if (!validNumStr(val))
+ if (!validNumStr(val_))
return false;
clear();
@@ -73,7 +65,7 @@ bool UniValue::setNumStr(string val_)
return true;
}
-bool UniValue::setInt(int64_t val)
+bool UniValue::setInt(uint64_t val)
{
string s;
ostringstream oss;
@@ -83,7 +75,7 @@ bool UniValue::setInt(int64_t val)
return setNumStr(oss.str());
}
-bool UniValue::setFloat(double val)
+bool UniValue::setInt(int64_t val)
{
string s;
ostringstream oss;
@@ -93,7 +85,19 @@ bool UniValue::setFloat(double val)
return setNumStr(oss.str());
}
-bool UniValue::setStr(string val_)
+bool UniValue::setFloat(double val)
+{
+ string s;
+ ostringstream oss;
+
+ oss << std::setprecision(16) << val;
+
+ bool ret = setNumStr(oss.str());
+ typ = VNUM;
+ return ret;
+}
+
+bool UniValue::setStr(const string& val_)
{
clear();
typ = VSTR;
@@ -115,7 +119,7 @@ bool UniValue::setObject()
return true;
}
-bool UniValue::push(UniValue& val)
+bool UniValue::push_back(const UniValue& val)
{
if (typ != VARR)
return false;
@@ -124,7 +128,17 @@ bool UniValue::push(UniValue& val)
return true;
}
-bool UniValue::pushKV(string key, UniValue& val)
+bool UniValue::push_backV(const std::vector<UniValue>& vec)
+{
+ if (typ != VARR)
+ return false;
+
+ values.insert(values.end(), vec.begin(), vec.end());
+
+ return true;
+}
+
+bool UniValue::pushKV(const std::string& key, const UniValue& val)
{
if (typ != VOBJ)
return false;
@@ -134,3 +148,163 @@ bool UniValue::pushKV(string key, UniValue& val)
return true;
}
+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[i]);
+ }
+
+ return true;
+}
+
+int UniValue::findKey(const std::string& key) const
+{
+ for (unsigned int i = 0; i < keys.size(); i++) {
+ if (keys[i] == key)
+ return (int) i;
+ }
+
+ return -1;
+}
+
+bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t)
+{
+ for (std::map<std::string,UniValue::VType>::const_iterator it = t.begin();
+ it != t.end(); it++) {
+ int idx = findKey(it->first);
+ if (idx < 0)
+ return false;
+
+ if (values[idx].getType() != it->second)
+ return false;
+ }
+
+ return true;
+}
+
+const UniValue& UniValue::operator[](const std::string& key) const
+{
+ if (typ != VOBJ)
+ return NullUniValue;
+
+ int index = findKey(key);
+ if (index < 0)
+ return NullUniValue;
+
+ return values[index];
+}
+
+const UniValue& UniValue::operator[](unsigned int index) const
+{
+ if (typ != VOBJ && typ != VARR)
+ return NullUniValue;
+ if (index >= values.size())
+ return NullUniValue;
+
+ return values[index];
+}
+
+const char *uvTypeName(UniValue::VType t)
+{
+ switch (t) {
+ case UniValue::VNULL: return "null";
+ case UniValue::VBOOL: return "bool";
+ case UniValue::VOBJ: return "object";
+ case UniValue::VARR: return "array";
+ case UniValue::VSTR: return "string";
+ case UniValue::VNUM: 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 != 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/univalue.h b/univalue.h
index 73eb361..ac05116 100644
--- a/univalue.h
+++ b/univalue.h
@@ -1,73 +1,131 @@
// Copyright 2014 BitPay Inc.
-// Distributed under the MIT/X11 software license, see the accompanying
+// Copyright 2015 Bitcoin Core Developers
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef __UNIVALUE_H__
#define __UNIVALUE_H__
#include <stdint.h>
+
#include <string>
#include <vector>
+#include <map>
#include <cassert>
+#include <sstream> // .get_int64()
+#include <utility> // std::pair
+
class UniValue {
public:
- enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VTRUE, VFALSE, };
+ enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
UniValue() { typ = VNULL; }
UniValue(UniValue::VType initialType, const std::string& initialStr = "") {
typ = initialType;
val = initialStr;
}
+ UniValue(uint64_t val_) {
+ setInt(val_);
+ }
UniValue(int64_t val_) {
setInt(val_);
}
+ UniValue(bool val_) {
+ setBool(val_);
+ }
+ UniValue(int val_) {
+ setInt(val_);
+ }
+ UniValue(double val_) {
+ setFloat(val_);
+ }
+ UniValue(const std::string& val_) {
+ setStr(val_);
+ }
+ UniValue(const char *val_) {
+ std::string s(val_);
+ setStr(s);
+ }
~UniValue() {}
void clear();
bool setNull();
bool setBool(bool val);
- bool setNumStr(std::string val);
+ bool setNumStr(const std::string& val);
+ bool setInt(uint64_t val);
bool setInt(int64_t val);
+ bool setInt(int val) { return setInt((int64_t)val); }
bool setFloat(double val);
- bool setStr(std::string val);
+ bool setStr(const std::string& val);
bool setArray();
bool setObject();
- enum VType getType() { return typ; }
- std::string getValStr() { return val; }
+ enum VType getType() const { return typ; }
+ const std::string& getValStr() const { return val; }
+ bool empty() const { return (values.size() == 0); }
- bool isNull() { return (typ == VNULL); }
- bool isTrue() { return (typ == VTRUE); }
- bool isFalse() { return (typ == VFALSE); }
- bool isBool() { return (typ == VTRUE || typ == VFALSE); }
- bool isStr() { return (typ == VSTR); }
- bool isNum() { return (typ == VNUM); }
- bool isArray() { return (typ == VARR); }
- bool isObject() { return (typ == VOBJ); }
+ size_t size() const { return values.size(); }
- bool push(UniValue& val);
- bool push(const std::string& val_) {
+ bool getBool() const { return isTrue(); }
+ bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes);
+ const UniValue& operator[](const std::string& key) const;
+ const UniValue& operator[](unsigned int index) const;
+ bool exists(const std::string& key) const { return (findKey(key) >= 0); }
+
+ bool isNull() const { return (typ == VNULL); }
+ bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
+ 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 isArray() const { return (typ == VARR); }
+ 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(tmpVal);
+ return push_back(tmpVal);
+ }
+ bool push_back(const char *val_) {
+ std::string s(val_);
+ return push_back(s);
}
+ bool push_backV(const std::vector<UniValue>& vec);
- bool pushKV(std::string key, UniValue& val);
- bool pushKV(std::string key, const std::string 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(std::string key, int64_t val) {
+ 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, 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,
- unsigned int indentLevel = 0);
+ unsigned int indentLevel = 0) const;
bool read(const char *raw);
- bool read(std::string rawStr) {
+ bool read(const std::string& rawStr) {
return read(rawStr.c_str());
}
@@ -77,10 +135,116 @@ private:
std::vector<std::string> keys;
std::vector<UniValue> values;
- void writeOpen(unsigned int prettyIndent, unsigned int indentLevel, std::string& s);
- void writeClose(unsigned int prettyIndent, unsigned int indentLevel, std::string& s);
- void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s);
- void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s);
+ 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
+ JTOK_OBJ_OPEN,
+ JTOK_OBJ_CLOSE,
+ JTOK_ARR_OPEN,
+ JTOK_ARR_CLOSE,
+ JTOK_COLON,
+ JTOK_COMMA,
+ JTOK_KW_NULL,
+ JTOK_KW_TRUE,
+ JTOK_KW_FALSE,
+ JTOK_NUMBER,
+ JTOK_STRING,
};
-#endif // __UNIVALUE_H__
+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 // __UNIVALUE_H__
\ No newline at end of file
diff --git a/univalue_escapes.h b/univalue_escapes.h
new file mode 100644
index 0000000..4133b24
--- /dev/null
+++ b/univalue_escapes.h
@@ -0,0 +1,262 @@
+// Automatically generated file. Do not modify.
+#ifndef BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
+#define BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
+static const char *escapes[256] = {
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "\\b",
+ "\\t",
+ "\\n",
+ NULL,
+ "\\f",
+ "\\r",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "\\\"",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ "\\\\",
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+#endif // BITCOIN_UNIVALUE_UNIVALUE_ESCAPES_H
diff --git a/univalue_read.cpp b/univalue_read.cpp
index a72d0ea..2617718 100644
--- a/univalue_read.cpp
+++ b/univalue_read.cpp
@@ -1,5 +1,5 @@
// Copyright 2014 BitPay Inc.
-// Distributed under the MIT/X11 software license, see the accompanying
+// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <string.h>
@@ -9,22 +9,6 @@
using namespace std;
-enum tokentype {
- TOK_ERR = -1,
- TOK_NONE = 0, // eof
- TOK_OBJ_OPEN,
- TOK_OBJ_CLOSE,
- TOK_ARR_OPEN,
- TOK_ARR_CLOSE,
- TOK_COLON,
- TOK_COMMA,
- TOK_KW_NULL,
- TOK_KW_TRUE,
- TOK_KW_FALSE,
- TOK_NUMBER,
- TOK_STRING,
-};
-
// convert hexadecimal string to unsigned integer
static const char *hatoui(const char *first, const char *last,
unsigned int& out)
@@ -52,7 +36,7 @@ static const char *hatoui(const char *first, const char *last,
return first;
}
-enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
+enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed,
const char *raw)
{
tokenVal.clear();
@@ -66,33 +50,33 @@ enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
switch (*raw) {
case 0:
- return TOK_NONE;
+ return JTOK_NONE;
case '{':
raw++;
consumed = (raw - rawStart);
- return TOK_OBJ_OPEN;
+ return JTOK_OBJ_OPEN;
case '}':
raw++;
consumed = (raw - rawStart);
- return TOK_OBJ_CLOSE;
+ return JTOK_OBJ_CLOSE;
case '[':
raw++;
consumed = (raw - rawStart);
- return TOK_ARR_OPEN;
+ return JTOK_ARR_OPEN;
case ']':
raw++;
consumed = (raw - rawStart);
- return TOK_ARR_CLOSE;
+ return JTOK_ARR_CLOSE;
case ':':
raw++;
consumed = (raw - rawStart);
- return TOK_COLON;
+ return JTOK_COLON;
case ',':
raw++;
consumed = (raw - rawStart);
- return TOK_COMMA;
+ return JTOK_COMMA;
case 'n':
case 't':
@@ -100,17 +84,17 @@ enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
if (!strncmp(raw, "null", 4)) {
raw += 4;
consumed = (raw - rawStart);
- return TOK_KW_NULL;
+ return JTOK_KW_NULL;
} else if (!strncmp(raw, "true", 4)) {
raw += 4;
consumed = (raw - rawStart);
- return TOK_KW_TRUE;
+ return JTOK_KW_TRUE;
} else if (!strncmp(raw, "false", 5)) {
raw += 5;
consumed = (raw - rawStart);
- return TOK_KW_FALSE;
+ return JTOK_KW_FALSE;
} else
- return TOK_ERR;
+ return JTOK_ERR;
case '-':
case '0':
@@ -132,13 +116,13 @@ enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
if (!isdigit(*firstDigit))
firstDigit++;
if ((*firstDigit == '0') && isdigit(firstDigit[1]))
- return TOK_ERR;
+ return JTOK_ERR;
numStr += *raw; // copy first char
raw++;
if ((*first == '-') && (!isdigit(*raw)))
- return TOK_ERR;
+ return JTOK_ERR;
while ((*raw) && isdigit(*raw)) { // copy digits
numStr += *raw;
@@ -151,7 +135,7 @@ enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
raw++;
if (!isdigit(*raw))
- return TOK_ERR;
+ return JTOK_ERR;
while ((*raw) && isdigit(*raw)) { // copy digits
numStr += *raw;
raw++;
@@ -169,7 +153,7 @@ enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
}
if (!isdigit(*raw))
- return TOK_ERR;
+ return JTOK_ERR;
while ((*raw) && isdigit(*raw)) { // copy digits
numStr += *raw;
raw++;
@@ -178,7 +162,7 @@ enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
tokenVal = numStr;
consumed = (raw - rawStart);
- return TOK_NUMBER;
+ return JTOK_NUMBER;
}
case '"': {
@@ -188,7 +172,7 @@ enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
while (*raw) {
if (*raw < 0x20)
- return TOK_ERR;
+ return JTOK_ERR;
else if (*raw == '\\') {
raw++; // skip backslash
@@ -204,30 +188,27 @@ enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
case 't': valStr += "\t"; break;
case 'u': {
- char buf[4] = {0,0,0,0};
- char *last = &buf[0];
unsigned int codepoint;
if (hatoui(raw + 1, raw + 1 + 4, codepoint) !=
raw + 1 + 4)
- return TOK_ERR;
+ return JTOK_ERR;
if (codepoint <= 0x7f)
- *last = (char)codepoint;
+ valStr.push_back((char)codepoint);
else if (codepoint <= 0x7FF) {
- *last++ = (char)(0xC0 | (codepoint >> 6));
- *last = (char)(0x80 | (codepoint & 0x3F));
+ valStr.push_back((char)(0xC0 | (codepoint >> 6)));
+ valStr.push_back((char)(0x80 | (codepoint & 0x3F)));
} else if (codepoint <= 0xFFFF) {
- *last++ = (char)(0xE0 | (codepoint >> 12));
- *last++ = (char)(0x80 | ((codepoint >> 6) & 0x3F));
- *last = (char)(0x80 | (codepoint & 0x3F));
+ valStr.push_back((char)(0xE0 | (codepoint >> 12)));
+ valStr.push_back((char)(0x80 | ((codepoint >> 6) & 0x3F)));
+ valStr.push_back((char)(0x80 | (codepoint & 0x3F)));
}
- valStr += buf;
raw += 4;
break;
}
default:
- return TOK_ERR;
+ return JTOK_ERR;
}
@@ -247,11 +228,11 @@ enum tokentype getJsonToken(string& tokenVal, unsigned int& consumed,
tokenVal = valStr;
consumed = (raw - rawStart);
- return TOK_STRING;
+ return JTOK_STRING;
}
default:
- return TOK_ERR;
+ return JTOK_ERR;
}
}
@@ -263,23 +244,23 @@ bool UniValue::read(const char *raw)
bool expectColon = false;
vector<UniValue*> stack;
- enum tokentype tok = TOK_NONE;
- enum tokentype last_tok = TOK_NONE;
+ enum jtokentype tok = JTOK_NONE;
+ enum jtokentype last_tok = JTOK_NONE;
while (1) {
last_tok = tok;
string tokenVal;
unsigned int consumed;
tok = getJsonToken(tokenVal, consumed, raw);
- if (tok == TOK_NONE || tok == TOK_ERR)
+ if (tok == JTOK_NONE || tok == JTOK_ERR)
break;
raw += consumed;
switch (tok) {
- case TOK_OBJ_OPEN:
- case TOK_ARR_OPEN: {
- VType utyp = (tok == TOK_OBJ_OPEN ? VOBJ : VARR);
+ case JTOK_OBJ_OPEN:
+ case JTOK_ARR_OPEN: {
+ VType utyp = (tok == JTOK_OBJ_OPEN ? VOBJ : VARR);
if (!stack.size()) {
if (utyp == VOBJ)
setObject();
@@ -300,12 +281,12 @@ bool UniValue::read(const char *raw)
break;
}
- case TOK_OBJ_CLOSE:
- case TOK_ARR_CLOSE: {
- if (!stack.size() || expectColon || (last_tok == TOK_COMMA))
+ case JTOK_OBJ_CLOSE:
+ case JTOK_ARR_CLOSE: {
+ if (!stack.size() || expectColon || (last_tok == JTOK_COMMA))
return false;
- VType utyp = (tok == TOK_OBJ_CLOSE ? VOBJ : VARR);
+ VType utyp = (tok == JTOK_OBJ_CLOSE ? VOBJ : VARR);
UniValue *top = stack.back();
if (utyp != top->getType())
return false;
@@ -315,7 +296,7 @@ bool UniValue::read(const char *raw)
break;
}
- case TOK_COLON: {
+ case JTOK_COLON: {
if (!stack.size() || expectName || !expectColon)
return false;
@@ -327,9 +308,9 @@ bool UniValue::read(const char *raw)
break;
}
- case TOK_COMMA: {
+ case JTOK_COMMA: {
if (!stack.size() || expectName || expectColon ||
- (last_tok == TOK_COMMA) || (last_tok == TOK_ARR_OPEN))
+ (last_tok == JTOK_COMMA) || (last_tok == JTOK_ARR_OPEN))
return false;
UniValue *top = stack.back();
@@ -338,28 +319,33 @@ bool UniValue::read(const char *raw)
break;
}
- case TOK_KW_NULL:
- case TOK_KW_TRUE:
- case TOK_KW_FALSE: {
+ case JTOK_KW_NULL:
+ case JTOK_KW_TRUE:
+ case JTOK_KW_FALSE: {
if (!stack.size() || expectName || expectColon)
return false;
- VType utyp;
+ UniValue tmpVal;
switch (tok) {
- case TOK_KW_NULL: utyp = VNULL; break;
- case TOK_KW_TRUE: utyp = VTRUE; break;
- case TOK_KW_FALSE: utyp = VFALSE; break;
+ case JTOK_KW_NULL:
+ // do nothing more
+ break;
+ case JTOK_KW_TRUE:
+ tmpVal.setBool(true);
+ break;
+ case JTOK_KW_FALSE:
+ tmpVal.setBool(false);
+ break;
default: /* impossible */ break;
}
- UniValue tmpVal(utyp);
UniValue *top = stack.back();
top->values.push_back(tmpVal);
break;
}
- case TOK_NUMBER: {
+ case JTOK_NUMBER: {
if (!stack.size() || expectName || expectColon)
return false;
@@ -370,7 +356,7 @@ bool UniValue::read(const char *raw)
break;
}
- case TOK_STRING: {
+ case JTOK_STRING: {
if (!stack.size())
return false;
diff --git a/univalue_write.cpp b/univalue_write.cpp
index 2b70f70..bce3997 100644
--- a/univalue_write.cpp
+++ b/univalue_write.cpp
@@ -1,37 +1,20 @@
// Copyright 2014 BitPay Inc.
-// Distributed under the MIT/X11 software license, see the accompanying
+// Distributed under the MIT software license, see the accompanying
// 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"
// TODO: Using UTF8
using namespace std;
-static bool initEscapes;
-static const char *escapes[256];
-
-static void initJsonEscape()
-{
- escapes['"'] = "\\\"";
- escapes['\\'] = "\\\\";
- escapes['/'] = "\\/";
- escapes['\b'] = "\\b";
- escapes['\f'] = "\\f";
- escapes['\n'] = "\\n";
- escapes['\r'] = "\\r";
- escapes['\t'] = "\\t";
-
- initEscapes = true;
-}
-
static string json_escape(const string& inS)
{
- if (!initEscapes)
- initJsonEscape();
-
string outS;
outS.reserve(inS.size() * 2);
@@ -56,7 +39,7 @@ static string json_escape(const string& inS)
}
string UniValue::write(unsigned int prettyIndent,
- unsigned int indentLevel)
+ unsigned int indentLevel) const
{
string s;
s.reserve(1024);
@@ -81,29 +64,20 @@ string UniValue::write(unsigned int prettyIndent,
case VNUM:
s += val;
break;
- case VTRUE:
- s += "true";
- break;
- case VFALSE:
- s += "false";
+ case VBOOL:
+ s += (val == "1" ? "true" : "false");
break;
}
return s;
}
-static string spaceStr;
-
-static string indentStr(unsigned int prettyIndent, unsigned int indentLevel)
+static void indentStr(unsigned int prettyIndent, unsigned int indentLevel, string& s)
{
- unsigned int spaces = prettyIndent * indentLevel;
- while (spaceStr.size() < spaces)
- spaceStr += " ";
-
- return spaceStr.substr(0, spaces);
+ s.append(prettyIndent * indentLevel, ' ');
}
-void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, string& s)
+void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
{
s += "[";
if (prettyIndent)
@@ -111,20 +85,23 @@ void UniValue::writeArray(unsigned int prettyIndent, unsigned int indentLevel, s
for (unsigned int i = 0; i < values.size(); i++) {
if (prettyIndent)
- s += indentStr(prettyIndent, indentLevel);
+ indentStr(prettyIndent, indentLevel, s);
s += values[i].write(prettyIndent, indentLevel + 1);
- if (i != (values.size() - 1))
- s += ", ";
+ if (i != (values.size() - 1)) {
+ s += ",";
+ if (prettyIndent)
+ s += " ";
+ }
if (prettyIndent)
s += "\n";
}
if (prettyIndent)
- s += indentStr(prettyIndent, indentLevel - 1);
+ indentStr(prettyIndent, indentLevel - 1, s);
s += "]";
}
-void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, string& s)
+void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, string& s) const
{
s += "{";
if (prettyIndent)
@@ -132,8 +109,10 @@ void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel,
for (unsigned int i = 0; i < keys.size(); i++) {
if (prettyIndent)
- s += indentStr(prettyIndent, indentLevel);
- s += "\"" + json_escape(keys[i]) + "\": ";
+ indentStr(prettyIndent, indentLevel, s);
+ s += "\"" + json_escape(keys[i]) + "\":";
+ if (prettyIndent)
+ s += " ";
s += values[i].write(prettyIndent, indentLevel + 1);
if (i != (values.size() - 1))
s += ",";
@@ -142,7 +121,7 @@ void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel,
}
if (prettyIndent)
- s += indentStr(prettyIndent, indentLevel - 1);
+ indentStr(prettyIndent, indentLevel - 1, s);
s += "}";
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-bitcoin/libunivalue.git
More information about the Pkg-bitcoin-commits
mailing list