Browse Source

univalue: Avoid unnecessary roundtrip through double for numbers

JSON makes no distinction between numbers and reals, and our code
doesn't need to do so either.

This removes VREAL, as well as its specific post-processing in
`UniValue::write`. Non-monetary amounts do not need to be forcibly
formatted with 8 decimals, so the extra roundtrip was unnecessary
(and potentially loses precision).
0.13
Wladimir J. van der Laan 10 years ago
parent
commit
7650449a67
  1. 3
      qa/rpc-tests/rest.py
  2. 2
      src/rpcserver.cpp
  3. 6
      src/test/univalue_tests.cpp
  4. 5
      src/univalue/univalue.cpp
  5. 3
      src/univalue/univalue.h
  6. 7
      src/univalue/univalue_write.cpp

3
qa/rpc-tests/rest.py

@ -14,6 +14,7 @@ from struct import * @@ -14,6 +14,7 @@ from struct import *
import binascii
import json
import StringIO
import decimal
try:
import http.client as httplib
@ -243,7 +244,7 @@ class RESTTest (BitcoinTestFramework): @@ -243,7 +244,7 @@ class RESTTest (BitcoinTestFramework):
response_header_json = http_get_call(url.hostname, url.port, '/rest/headers/1/'+bb_hash+self.FORMAT_SEPARATOR+"json", "", True)
assert_equal(response_header_json.status, 200)
response_header_json_str = response_header_json.read()
json_obj = json.loads(response_header_json_str)
json_obj = json.loads(response_header_json_str, parse_float=decimal.Decimal)
assert_equal(len(json_obj), 1) #ensure that there is one header in the json response
assert_equal(json_obj[0]['hash'], bb_hash) #request/response hash should be the same

2
src/rpcserver.cpp

@ -120,7 +120,7 @@ void RPCTypeCheckObj(const UniValue& o, @@ -120,7 +120,7 @@ void RPCTypeCheckObj(const UniValue& o,
CAmount AmountFromValue(const UniValue& value)
{
if (!value.isReal() && !value.isNum())
if (!value.isNum())
throw JSONRPCError(RPC_TYPE_ERROR, "Amount is not a number");
CAmount amount;
if (!ParseFixedPoint(value.getValStr(), 8, &amount))

6
src/test/univalue_tests.cpp

@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(univalue_constructor) @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE(univalue_constructor)
double vd = -7.21;
UniValue v7(vd);
BOOST_CHECK(v7.isReal());
BOOST_CHECK(v7.isNum());
BOOST_CHECK_EQUAL(v7.getValStr(), "-7.21");
string vs("yawn");
@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE(univalue_set) @@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE(univalue_set)
BOOST_CHECK_EQUAL(v.getValStr(), "zum");
BOOST_CHECK(v.setFloat(-1.01));
BOOST_CHECK(v.isReal());
BOOST_CHECK(v.isNum());
BOOST_CHECK_EQUAL(v.getValStr(), "-1.01");
BOOST_CHECK(v.setInt((int)1023));
@ -272,7 +272,7 @@ BOOST_AUTO_TEST_CASE(univalue_object) @@ -272,7 +272,7 @@ BOOST_AUTO_TEST_CASE(univalue_object)
objTypes["distance"] = UniValue::VNUM;
objTypes["time"] = UniValue::VNUM;
objTypes["calories"] = UniValue::VNUM;
objTypes["temperature"] = UniValue::VREAL;
objTypes["temperature"] = UniValue::VNUM;
objTypes["cat1"] = UniValue::VNUM;
objTypes["cat2"] = UniValue::VNUM;
BOOST_CHECK(obj.checkObject(objTypes));

5
src/univalue/univalue.cpp

@ -86,7 +86,7 @@ bool UniValue::setFloat(double val) @@ -86,7 +86,7 @@ bool UniValue::setFloat(double val)
oss << std::setprecision(16) << val;
bool ret = setNumStr(oss.str());
typ = VREAL;
typ = VNUM;
return ret;
}
@ -210,7 +210,6 @@ const char *uvTypeName(UniValue::VType t) @@ -210,7 +210,6 @@ const char *uvTypeName(UniValue::VType t)
case UniValue::VARR: return "array";
case UniValue::VSTR: return "string";
case UniValue::VNUM: return "number";
case UniValue::VREAL: return "number";
}
// not reached
@ -280,7 +279,7 @@ int64_t UniValue::get_int64() const @@ -280,7 +279,7 @@ int64_t UniValue::get_int64() const
double UniValue::get_real() const
{
if (typ != VREAL && typ != VNUM)
if (typ != VNUM)
throw std::runtime_error("JSON value is not a number as expected");
double retval;
if (!ParseDouble(getValStr(), &retval))

3
src/univalue/univalue.h

@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
class UniValue {
public:
enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VREAL, VBOOL, };
enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
UniValue() { typ = VNULL; }
UniValue(UniValue::VType initialType, const std::string& initialStr = "") {
@ -78,7 +78,6 @@ public: @@ -78,7 +78,6 @@ public:
bool isBool() const { return (typ == VBOOL); }
bool isStr() const { return (typ == VSTR); }
bool isNum() const { return (typ == VNUM); }
bool isReal() const { return (typ == VREAL); }
bool isArray() const { return (typ == VARR); }
bool isObject() const { return (typ == VOBJ); }

7
src/univalue/univalue_write.cpp

@ -61,13 +61,6 @@ string UniValue::write(unsigned int prettyIndent, @@ -61,13 +61,6 @@ string UniValue::write(unsigned int prettyIndent,
case VSTR:
s += "\"" + json_escape(val) + "\"";
break;
case VREAL:
{
std::stringstream ss;
ss << std::showpoint << std::fixed << std::setprecision(8) << get_real();
s += ss.str();
}
break;
case VNUM:
s += val;
break;

Loading…
Cancel
Save