Bitcoin ABC  0.26.3
P2P Digital Currency
univalue_get.cpp
Go to the documentation of this file.
1 // Copyright 2014 BitPay Inc.
2 // Copyright 2015 Bitcoin Core Developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://opensource.org/licenses/mit-license.php.
5 
6 #include <stdint.h>
7 #include <errno.h>
8 #include <string.h>
9 #include <stdlib.h>
10 #include <stdexcept>
11 #include <vector>
12 #include <limits>
13 #include <string>
14 #include <sstream>
15 
16 #include "univalue.h"
17 
18 namespace
19 {
20 static bool ParsePrechecks(const std::string& str)
21 {
22  if (str.empty()) // No empty string allowed
23  return false;
24  if (str.size() >= 1 && (json_isspace(str[0]) || json_isspace(str[str.size()-1]))) // No padding allowed
25  return false;
26  if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
27  return false;
28  return true;
29 }
30 
31 bool ParseInt32(const std::string& str, int32_t *out)
32 {
33  if (!ParsePrechecks(str))
34  return false;
35  char *endp = NULL;
36  errno = 0; // strtol will not set errno if valid
37  long int n = strtol(str.c_str(), &endp, 10);
38  if(out) *out = (int32_t)n;
39  // Note that strtol returns a *long int*, so even if strtol doesn't report a over/underflow
40  // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
41  // platforms the size of these types may be different.
42  return endp && *endp == 0 && !errno &&
43  n >= std::numeric_limits<int32_t>::min() &&
44  n <= std::numeric_limits<int32_t>::max();
45 }
46 
47 bool ParseInt64(const std::string& str, int64_t *out)
48 {
49  if (!ParsePrechecks(str))
50  return false;
51  char *endp = NULL;
52  errno = 0; // strtoll will not set errno if valid
53  long long int n = strtoll(str.c_str(), &endp, 10);
54  if(out) *out = (int64_t)n;
55  // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow
56  // we still have to check that the returned value is within the range of an *int64_t*.
57  return endp && *endp == 0 && !errno &&
58  n >= std::numeric_limits<int64_t>::min() &&
59  n <= std::numeric_limits<int64_t>::max();
60 }
61 
62 bool ParseDouble(const std::string& str, double *out)
63 {
64  if (!ParsePrechecks(str))
65  return false;
66  if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
67  return false;
68  std::istringstream text(str);
69  text.imbue(std::locale::classic());
70  double result;
71  text >> result;
72  if(out) *out = result;
73  return text.eof() && !text.fail();
74 }
75 }
76 
77 const std::vector<std::string>& UniValue::getKeys() const
78 {
79  if (typ != VOBJ)
80  throw std::runtime_error("JSON value is not an object as expected");
81  return keys;
82 }
83 
84 const std::vector<UniValue>& UniValue::getValues() const
85 {
86  if (typ != VOBJ && typ != VARR)
87  throw std::runtime_error("JSON value is not an object or array as expected");
88  return values;
89 }
90 
91 bool UniValue::get_bool() const
92 {
93  if (typ != VBOOL)
94  throw std::runtime_error("JSON value is not a boolean as expected");
95  return getBool();
96 }
97 
98 const std::string& UniValue::get_str() const
99 {
100  if (typ != VSTR)
101  throw std::runtime_error("JSON value is not a string as expected");
102  return getValStr();
103 }
104 
105 int UniValue::get_int() const
106 {
107  if (typ != VNUM)
108  throw std::runtime_error("JSON value is not an integer as expected");
109  int32_t retval;
110  if (!ParseInt32(getValStr(), &retval))
111  throw std::runtime_error("JSON integer out of range");
112  return retval;
113 }
114 
115 int64_t UniValue::get_int64() const
116 {
117  if (typ != VNUM)
118  throw std::runtime_error("JSON value is not an integer as expected");
119  int64_t retval;
120  if (!ParseInt64(getValStr(), &retval))
121  throw std::runtime_error("JSON integer out of range");
122  return retval;
123 }
124 
125 double UniValue::get_real() const
126 {
127  if (typ != VNUM)
128  throw std::runtime_error("JSON value is not a number as expected");
129  double retval;
130  if (!ParseDouble(getValStr(), &retval))
131  throw std::runtime_error("JSON double out of range");
132  return retval;
133 }
134 
136 {
137  if (typ != VOBJ)
138  throw std::runtime_error("JSON value is not an object as expected");
139  return *this;
140 }
141 
143 {
144  if (typ != VARR)
145  throw std::runtime_error("JSON value is not an array as expected");
146  return *this;
147 }
148 
UniValue::VType typ
Definition: univalue.h:115
const std::string & get_str() const
@ VOBJ
Definition: univalue.h:27
@ VSTR
Definition: univalue.h:27
@ VARR
Definition: univalue.h:27
@ VNUM
Definition: univalue.h:27
@ VBOOL
Definition: univalue.h:27
int64_t get_int64() const
const UniValue & get_obj() const
const std::string & getValStr() const
Definition: univalue.h:77
const std::vector< UniValue > & getValues() const
const std::vector< std::string > & getKeys() const
std::vector< UniValue > values
Definition: univalue.h:118
std::vector< std::string > keys
Definition: univalue.h:117
const UniValue & get_array() const
bool getBool() const
Definition: univalue.h:82
double get_real() const
bool get_bool() const
int get_int() const
static bool ParsePrechecks(const std::string &str)
bool ParseInt32(const std::string &str, int32_t *out)
Convert string to signed 32-bit integer with strict parse error feedback.
bool ParseInt64(const std::string &str, int64_t *out)
Convert string to signed 64-bit integer with strict parse error feedback.
bool ParseDouble(const std::string &str, double *out)
Convert string to double with strict parse error feedback.
static bool json_isspace(int ch)
Definition: univalue.h:245