Branch data Line data Source code
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 : : #ifndef BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
7 : : #define BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
8 : :
9 : : #include <charconv>
10 : : #include <cstddef>
11 : : #include <cstdint>
12 : : #include <map>
13 : : #include <stdexcept>
14 : : #include <string>
15 : : #include <string_view>
16 : : #include <system_error>
17 : : #include <type_traits>
18 : : #include <utility>
19 : : #include <vector>
20 : :
21 : : // NOLINTNEXTLINE(misc-no-recursion)
22 : : class UniValue {
23 : : public:
24 : : enum VType { VNULL, VOBJ, VARR, VSTR, VNUM, VBOOL, };
25 : :
26 : : class type_error : public std::runtime_error
27 : : {
28 [ + - ]: 27 : using std::runtime_error::runtime_error;
29 : : };
30 : :
31 [ + + ]: 259490 : UniValue() { typ = VNULL; }
[ + - + - ]
[ + - + -
+ - ][ - -
+ + + - -
- - - ][ +
- + - + -
+ - + - +
- + - + -
+ - + - -
+ + - ]
[ + + + ][ +
- + - + -
+ - + - +
- + - ]
32 [ + - + - : 24214 : UniValue(UniValue::VType type, std::string str = {}) : typ{type}, val{std::move(str)} {}
+ - ]
33 : : template <typename Ref, typename T = std::remove_cv_t<std::remove_reference_t<Ref>>,
34 : : std::enable_if_t<std::is_floating_point_v<T> || // setFloat
35 : : std::is_same_v<bool, T> || // setBool
36 : : std::is_signed_v<T> || std::is_unsigned_v<T> || // setInt
37 : : std::is_constructible_v<std::string, T>, // setStr
38 : : bool> = true>
39 : 441496 : UniValue(Ref&& val)
40 [ + - ]: 441496 : {
41 : : if constexpr (std::is_floating_point_v<T>) {
42 [ + - ]: 84 : setFloat(val);
43 : : } else if constexpr (std::is_same_v<bool, T>) {
44 [ + - ]: 167837 : setBool(val);
45 : : } else if constexpr (std::is_signed_v<T>) {
46 [ + - ]: 1977 : setInt(int64_t{val});
47 : : } else if constexpr (std::is_unsigned_v<T>) {
48 [ + - ]: 297 : setInt(uint64_t{val});
49 : : } else {
50 [ + - ]: 271301 : setStr(std::string{std::forward<Ref>(val)});
[ + - + - ]
51 : : }
52 : 441496 : }
53 : :
54 : : void clear();
55 : :
56 : : void setNull();
57 : : void setBool(bool val);
58 : : void setNumStr(std::string str);
59 : : void setInt(uint64_t val);
60 : : void setInt(int64_t val);
61 [ + - + - : 4 : void setInt(int val_) { return setInt(int64_t{val_}); }
+ - + - ]
62 : : void setFloat(double val);
63 : : void setStr(std::string str);
64 : : void setArray();
65 : : void setObject();
66 : :
67 [ - - + + : 27899 : enum VType getType() const { return typ; }
- + + + +
- - ][ + + ]
[ - + - +
- + - + -
+ - + - +
- + - + -
+ - + ][ +
+ + - +
+ ]
68 [ + - + - ]: 210 : const std::string& getValStr() const { return val; }
[ + - # #
# # ][ # #
# # # # ]
[ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
69 [ + + # # : 180 : bool empty() const { return (values.size() == 0); }
# # # # #
# # # ][ -
+ - - - -
- - + + -
- ]
[ # # # # ]
[ + + + +
+ + + + ]
[ - + - +
- + - + +
- ]
70 : :
71 [ + + + + ]: 8776 : size_t size() const { return values.size(); }
[ + + + +
+ + + + ]
[ - - - -
- - - - -
- + + - -
- - ][ + -
# # # # #
# # # # #
# # # # ]
[ + + + +
+ + ][ - +
+ + + + +
+ - + +
+ ][ - + -
+ - + - +
- + - + -
+ - + -
+ ][ + - +
- + - + +
+ + + + +
- + - + -
+ + + + +
+ ][ - - -
- - - - -
+ - + + +
+ - + + +
+ + # # #
# ]
72 : :
73 : : void getObjMap(std::map<std::string,UniValue>& kv) const;
74 : : bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes) const;
75 : : const UniValue& operator[](const std::string& key) const;
76 : : const UniValue& operator[](size_t index) const;
77 [ + - + - ]: 59 : bool exists(const std::string& key) const { size_t i; return findKey(key, i); }
[ + - ][ # #
# # # # #
# # # ][ #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ][ - -
- - - - -
- - - - -
- - - - -
- - - - -
- - + - +
- + - + -
+ - + - +
- + - + -
- - - - -
- - - - -
- - - - +
- + - + -
+ - + - +
- + - ][ +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - ][ #
# # # #
# ]
78 : :
79 [ + + + + : 207390 : bool isNull() const { return (typ == VNULL); }
+ + + + ]
[ + - - +
- - - + -
+ - - - +
- + - + ]
[ - - - -
+ + + + -
- - + - -
- + ][ + -
+ - + - #
# # # # #
# # # # ]
[ + + + +
# # # # #
# # # # #
# # # # ]
[ - - - -
- - + - +
+ + + - -
- - - - -
- ][ - - -
- - - - -
- - - - -
- - - + +
+ + - + -
- - - # #
# # # # #
# # # # #
# # # # ]
[ + + # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ][ # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
[ + + + +
+ + + + +
+ # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # ]
[ # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
80 [ + + + + ]: 115078 : bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
81 [ + + + + ]: 1353673 : bool isFalse() const { return (typ == VBOOL) && (val != "1"); }
82 [ - + - + ]: 2 : bool isBool() const { return (typ == VBOOL); }
83 [ + + + - ]: 580 : bool isStr() const { return (typ == VSTR); }
[ - - + +
+ - ][ # # ]
[ - + - +
- + - + -
+ - + -
+ ][ + - -
+ + - -
+ ]
84 [ + - ][ - + : 169 : bool isNum() const { return (typ == VNUM); }
- + # # #
# ][ - - -
- - - +
+ ][ - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ ]
85 [ + + ]: 82531 : bool isArray() const { return (typ == VARR); }
[ # # # # ]
[ - + + +
+ + ][ + +
+ - + + +
+ ]
86 [ + + ]: 91 : bool isObject() const { return (typ == VOBJ); }
[ + + + - ]
[ - + - +
- + - + ]
87 : :
88 : : void push_back(UniValue val);
89 : : void push_backV(const std::vector<UniValue>& vec);
90 : : template <class It>
91 : : void push_backV(It first, It last);
92 : :
93 : : void pushKVEnd(std::string key, UniValue val);
94 : : void pushKV(std::string key, UniValue val);
95 : : void pushKVs(UniValue obj);
96 : :
97 : : std::string write(unsigned int prettyIndent = 0,
98 : : unsigned int indentLevel = 0) const;
99 : :
100 : : bool read(std::string_view raw);
101 : :
102 : : private:
103 : : UniValue::VType typ;
104 : : std::string val; // numbers are stored as C++ strings
105 : : std::vector<std::string> keys;
106 : : std::vector<UniValue> values;
107 : :
108 : : void checkType(const VType& expected) const;
109 : : bool findKey(const std::string& key, size_t& retIdx) const;
110 : : void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
111 : : void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
112 : :
113 : : public:
114 : : // Strict type-specific getters, these throw std::runtime_error if the
115 : : // value is of unexpected type
116 : : const std::vector<std::string>& getKeys() const;
117 : : const std::vector<UniValue>& getValues() const;
118 : : template <typename Int>
119 : : Int getInt() const;
120 : : bool get_bool() const;
121 : : const std::string& get_str() const;
122 : : double get_real() const;
123 : : const UniValue& get_obj() const;
124 : : const UniValue& get_array() const;
125 : :
126 [ + + + + : 20 : enum VType type() const { return getType(); }
- - ][ # # ]
127 : : const UniValue& find_value(std::string_view key) const;
128 : : };
129 : :
130 : : template <class It>
131 : 0 : void UniValue::push_backV(It first, It last)
132 : : {
133 : 0 : checkType(VARR);
134 : 0 : values.insert(values.end(), first, last);
135 : 0 : }
136 : :
137 : : template <typename Int>
138 : 1515 : Int UniValue::getInt() const
139 : : {
140 : : static_assert(std::is_integral<Int>::value);
141 : 1515 : checkType(VNUM);
142 : : Int result;
143 : 1513 : const auto [first_nonmatching, error_condition] = std::from_chars(val.data(), val.data() + val.size(), result);
144 [ + + + + ]: 1513 : if (first_nonmatching != val.data() + val.size() || error_condition != std::errc{}) {
145 [ + - ]: 4 : throw std::runtime_error("JSON integer out of range");
146 : : }
147 : 1509 : return result;
148 : : }
149 : :
150 : : enum jtokentype {
151 : : JTOK_ERR = -1,
152 : : JTOK_NONE = 0, // eof
153 : : JTOK_OBJ_OPEN,
154 : : JTOK_OBJ_CLOSE,
155 : : JTOK_ARR_OPEN,
156 : : JTOK_ARR_CLOSE,
157 : : JTOK_COLON,
158 : : JTOK_COMMA,
159 : : JTOK_KW_NULL,
160 : : JTOK_KW_TRUE,
161 : : JTOK_KW_FALSE,
162 : : JTOK_NUMBER,
163 : : JTOK_STRING,
164 : : };
165 : :
166 : : extern enum jtokentype getJsonToken(std::string& tokenVal,
167 : : unsigned int& consumed, const char *raw, const char *end);
168 : : extern const char *uvTypeName(UniValue::VType t);
169 : :
170 : : static inline bool jsonTokenIsValue(enum jtokentype jtt)
171 : : {
172 : : switch (jtt) {
173 : : case JTOK_KW_NULL:
174 : : case JTOK_KW_TRUE:
175 : : case JTOK_KW_FALSE:
176 : : case JTOK_NUMBER:
177 : : case JTOK_STRING:
178 : : return true;
179 : :
180 : : default:
181 : : return false;
182 : : }
183 : :
184 : : // not reached
185 : : }
186 : :
187 : 109080 : static inline bool json_isspace(int ch)
188 : : {
189 [ + - + - ]: 109074 : switch (ch) {
[ + + ]
190 : : case 0x20:
191 : : case 0x09:
192 : : case 0x0a:
193 : : case 0x0d:
194 : : return true;
195 : :
196 : 12 : default:
197 [ + - - + ]: 6 : return false;
198 : : }
199 : :
200 : : // not reached
201 : : }
202 : :
203 : : extern const UniValue NullUniValue;
204 : :
205 : : #endif // BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
|