diff options
author | MarcoFalke <falke.marco@gmail.com> | 2015-12-02 12:28:14 +0100 |
---|---|---|
committer | MarcoFalke <falke.marco@gmail.com> | 2015-12-02 12:28:48 +0100 |
commit | fad4ea836dc7cd1bb13c7394a6fadff419e4b026 (patch) | |
tree | ff7f84f4820a67a433c25e42b7914f3fced26193 /src/univalue/lib | |
parent | 1b0241fcec3e00d13658090e26cfa1f05133116e (diff) | |
parent | 982709199f1b4e9e35211c419a81938f9f1dd4ed (diff) |
Merge commit '982709199f1b4e9e35211c419a81938f9f1dd4ed' into bitcoin
Diffstat (limited to 'src/univalue/lib')
-rw-r--r-- | src/univalue/lib/univalue.cpp | 21 | ||||
-rw-r--r-- | src/univalue/lib/univalue_escapes.h | 56 | ||||
-rw-r--r-- | src/univalue/lib/univalue_read.cpp | 107 | ||||
-rw-r--r-- | src/univalue/lib/univalue_write.cpp | 7 |
4 files changed, 122 insertions, 69 deletions
diff --git a/src/univalue/lib/univalue.cpp b/src/univalue/lib/univalue.cpp index 883e8651fe..0076d6678e 100644 --- a/src/univalue/lib/univalue.cpp +++ b/src/univalue/lib/univalue.cpp @@ -4,7 +4,6 @@ // file COPYING or http://www.opensource.org/licenses/mit-license.php. #include <stdint.h> -#include <ctype.h> #include <errno.h> #include <iomanip> #include <limits> @@ -21,7 +20,7 @@ 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 + if (str.size() >= 1 && (json_isspace(str[0]) || json_isspace(str[str.size()-1]))) // No padding allowed return false; if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed return false; @@ -210,7 +209,7 @@ bool UniValue::pushKVs(const UniValue& obj) for (unsigned int i = 0; i < obj.keys.size(); i++) { keys.push_back(obj.keys[i]); - values.push_back(obj.values[i]); + values.push_back(obj.values.at(i)); } return true; @@ -234,7 +233,7 @@ bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t) if (idx < 0) return false; - if (values[idx].getType() != it->second) + if (values.at(idx).getType() != it->second) return false; } @@ -250,7 +249,7 @@ const UniValue& UniValue::operator[](const std::string& key) const if (index < 0) return NullUniValue; - return values[index]; + return values.at(index); } const UniValue& UniValue::operator[](unsigned int index) const @@ -260,7 +259,7 @@ const UniValue& UniValue::operator[](unsigned int index) const if (index >= values.size()) return NullUniValue; - return values[index]; + return values.at(index); } const char *uvTypeName(UniValue::VType t) @@ -278,15 +277,11 @@ const char *uvTypeName(UniValue::VType t) return NULL; } -const UniValue& find_value( const UniValue& obj, const std::string& name) +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]; - } - } + if (obj.keys[i] == name) + return obj.values.at(i); return NullUniValue; } diff --git a/src/univalue/lib/univalue_escapes.h b/src/univalue/lib/univalue_escapes.h index 4133b24ca1..74596aab6d 100644 --- a/src/univalue/lib/univalue_escapes.h +++ b/src/univalue/lib/univalue_escapes.h @@ -2,38 +2,38 @@ #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, + "\\u0000", + "\\u0001", + "\\u0002", + "\\u0003", + "\\u0004", + "\\u0005", + "\\u0006", + "\\u0007", "\\b", "\\t", "\\n", - NULL, + "\\u000b", "\\f", "\\r", - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, + "\\u000e", + "\\u000f", + "\\u0010", + "\\u0011", + "\\u0012", + "\\u0013", + "\\u0014", + "\\u0015", + "\\u0016", + "\\u0017", + "\\u0018", + "\\u0019", + "\\u001a", + "\\u001b", + "\\u001c", + "\\u001d", + "\\u001e", + "\\u001f", NULL, NULL, "\\\"", @@ -129,7 +129,7 @@ static const char *escapes[256] = { NULL, NULL, NULL, - NULL, + "\\u007f", NULL, NULL, NULL, diff --git a/src/univalue/lib/univalue_read.cpp b/src/univalue/lib/univalue_read.cpp index 64591234cb..c7516b9628 100644 --- a/src/univalue/lib/univalue_read.cpp +++ b/src/univalue/lib/univalue_read.cpp @@ -9,6 +9,11 @@ using namespace std; +static bool json_isdigit(int ch) +{ + return ((ch >= '0') && (ch <= '9')); +} + // convert hexadecimal string to unsigned integer static const char *hatoui(const char *first, const char *last, unsigned int& out) @@ -17,7 +22,7 @@ static const char *hatoui(const char *first, const char *last, for (; first != last; ++first) { int digit; - if (isdigit(*first)) + if (json_isdigit(*first)) digit = *first - '0'; else if (*first >= 'a' && *first <= 'f') @@ -44,7 +49,7 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, const char *rawStart = raw; - while ((*raw) && (isspace(*raw))) // skip whitespace + while ((*raw) && (json_isspace(*raw))) // skip whitespace raw++; switch (*raw) { @@ -113,18 +118,18 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, const char *first = raw; const char *firstDigit = first; - if (!isdigit(*firstDigit)) + if (!json_isdigit(*firstDigit)) firstDigit++; - if ((*firstDigit == '0') && isdigit(firstDigit[1])) + if ((*firstDigit == '0') && json_isdigit(firstDigit[1])) return JTOK_ERR; numStr += *raw; // copy first char raw++; - if ((*first == '-') && (!isdigit(*raw))) + if ((*first == '-') && (!json_isdigit(*raw))) return JTOK_ERR; - while ((*raw) && isdigit(*raw)) { // copy digits + while ((*raw) && json_isdigit(*raw)) { // copy digits numStr += *raw; raw++; } @@ -134,9 +139,9 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, numStr += *raw; // copy . raw++; - if (!isdigit(*raw)) + if (!json_isdigit(*raw)) return JTOK_ERR; - while ((*raw) && isdigit(*raw)) { // copy digits + while ((*raw) && json_isdigit(*raw)) { // copy digits numStr += *raw; raw++; } @@ -152,9 +157,9 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, raw++; } - if (!isdigit(*raw)) + if (!json_isdigit(*raw)) return JTOK_ERR; - while ((*raw) && isdigit(*raw)) { // copy digits + while ((*raw) && json_isdigit(*raw)) { // copy digits numStr += *raw; raw++; } @@ -236,12 +241,23 @@ enum jtokentype getJsonToken(string& tokenVal, unsigned int& consumed, } } +enum expect_bits { + EXP_OBJ_NAME = (1U << 0), + EXP_COLON = (1U << 1), + EXP_ARR_VALUE = (1U << 2), + EXP_VALUE = (1U << 3), + EXP_NOT_VALUE = (1U << 4), +}; + +#define expect(bit) (expectMask & (EXP_##bit)) +#define setExpect(bit) (expectMask |= EXP_##bit) +#define clearExpect(bit) (expectMask &= ~EXP_##bit) + bool UniValue::read(const char *raw) { clear(); - bool expectName = false; - bool expectColon = false; + uint32_t expectMask = 0; vector<UniValue*> stack; string tokenVal; @@ -256,6 +272,41 @@ bool UniValue::read(const char *raw) return false; raw += consumed; + bool isValueOpen = jsonTokenIsValue(tok) || + tok == JTOK_OBJ_OPEN || tok == JTOK_ARR_OPEN; + + if (expect(VALUE)) { + if (!isValueOpen) + return false; + clearExpect(VALUE); + + } else if (expect(ARR_VALUE)) { + bool isArrValue = isValueOpen || (tok == JTOK_ARR_CLOSE); + if (!isArrValue) + return false; + + clearExpect(ARR_VALUE); + + } else if (expect(OBJ_NAME)) { + bool isObjName = (tok == JTOK_OBJ_CLOSE || tok == JTOK_STRING); + if (!isObjName) + return false; + + } else if (expect(COLON)) { + if (tok != JTOK_COLON) + return false; + clearExpect(COLON); + + } else if (!expect(COLON) && (tok == JTOK_COLON)) { + return false; + } + + if (expect(NOT_VALUE)) { + if (isValueOpen) + return false; + clearExpect(NOT_VALUE); + } + switch (tok) { case JTOK_OBJ_OPEN: @@ -277,13 +328,15 @@ bool UniValue::read(const char *raw) } if (utyp == VOBJ) - expectName = true; + setExpect(OBJ_NAME); + else + setExpect(ARR_VALUE); break; } case JTOK_OBJ_CLOSE: case JTOK_ARR_CLOSE: { - if (!stack.size() || expectColon || (last_tok == JTOK_COMMA)) + if (!stack.size() || (last_tok == JTOK_COMMA)) return false; VType utyp = (tok == JTOK_OBJ_CLOSE ? VOBJ : VARR); @@ -292,37 +345,40 @@ bool UniValue::read(const char *raw) return false; stack.pop_back(); - expectName = false; + clearExpect(OBJ_NAME); + setExpect(NOT_VALUE); break; } case JTOK_COLON: { - if (!stack.size() || expectName || !expectColon) + if (!stack.size()) return false; UniValue *top = stack.back(); if (top->getType() != VOBJ) return false; - expectColon = false; + setExpect(VALUE); break; } case JTOK_COMMA: { - if (!stack.size() || expectName || expectColon || + if (!stack.size() || (last_tok == JTOK_COMMA) || (last_tok == JTOK_ARR_OPEN)) return false; UniValue *top = stack.back(); if (top->getType() == VOBJ) - expectName = true; + setExpect(OBJ_NAME); + else + setExpect(ARR_VALUE); break; } case JTOK_KW_NULL: case JTOK_KW_TRUE: case JTOK_KW_FALSE: { - if (!stack.size() || expectName || expectColon) + if (!stack.size()) return false; UniValue tmpVal; @@ -342,17 +398,19 @@ bool UniValue::read(const char *raw) UniValue *top = stack.back(); top->values.push_back(tmpVal); + setExpect(NOT_VALUE); break; } case JTOK_NUMBER: { - if (!stack.size() || expectName || expectColon) + if (!stack.size()) return false; UniValue tmpVal(VNUM, tokenVal); UniValue *top = stack.back(); top->values.push_back(tmpVal); + setExpect(NOT_VALUE); break; } @@ -362,15 +420,16 @@ bool UniValue::read(const char *raw) UniValue *top = stack.back(); - if (expectName) { + if (expect(OBJ_NAME)) { top->keys.push_back(tokenVal); - expectName = false; - expectColon = true; + clearExpect(OBJ_NAME); + setExpect(COLON); } else { UniValue tmpVal(VSTR, tokenVal); top->values.push_back(tmpVal); } + setExpect(NOT_VALUE); break; } diff --git a/src/univalue/lib/univalue_write.cpp b/src/univalue/lib/univalue_write.cpp index bce3997af7..ceb4cc9166 100644 --- a/src/univalue/lib/univalue_write.cpp +++ b/src/univalue/lib/univalue_write.cpp @@ -2,7 +2,6 @@ // 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> @@ -25,10 +24,10 @@ static string json_escape(const string& inS) if (escStr) outS += escStr; - else if (isprint(ch)) + else if (ch < 0x80) outS += ch; - else { + else { // TODO handle UTF-8 properly char tmpesc[16]; sprintf(tmpesc, "\\u%04x", ch); outS += tmpesc; @@ -113,7 +112,7 @@ void UniValue::writeObject(unsigned int prettyIndent, unsigned int indentLevel, s += "\"" + json_escape(keys[i]) + "\":"; if (prettyIndent) s += " "; - s += values[i].write(prettyIndent, indentLevel + 1); + s += values.at(i).write(prettyIndent, indentLevel + 1); if (i != (values.size() - 1)) s += ","; if (prettyIndent) |