Merge commit '982709199f1b4e9e35211c419a81938f9f1dd4ed' into bitcoin
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user