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