[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