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 [ + - ]: 45 : using std::runtime_error::runtime_error;
29 : : };
30 : :
31 [ + + + ][ + : 1988445 : UniValue() { typ = VNULL; }
- + - + -
+ - + - +
- + - ][ +
- + + + -
+ + + - ]
[ + - + -
+ - ][ + +
+ - + - +
- + - + -
+ - + - +
- + - - +
+ - ]
[ + + + ][ -
- + + + -
- - - - ]
32 [ + - + - : 3743734 : 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 : 13716547 : UniValue(Ref&& val)
40 [ + - ]: 13716547 : {
41 : : if constexpr (std::is_floating_point_v<T>) {
42 [ + - ]: 79220 : setFloat(val);
43 : : } else if constexpr (std::is_same_v<bool, T>) {
44 [ + - ]: 7710467 : setBool(val);
45 : : } else if constexpr (std::is_signed_v<T>) {
46 [ + - ]: 790906 : setInt(int64_t{val});
47 : : } else if constexpr (std::is_unsigned_v<T>) {
48 [ + - ]: 803388 : setInt(uint64_t{val});
49 : : } else {
50 [ + - + - ]: 4332566 : setStr(std::string{std::forward<Ref>(val)});
[ + - ]
51 : : }
52 : 13716547 : }
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 [ + + + + : 9270581 : enum VType getType() const { return typ; }
+ + - + -
+ - + - +
- + - + -
+ - + ][ +
+ + - +
+ ][ + + +
+ - + + +
+ - - ][ -
- + + - +
+ + + -
- ]
68 [ + + - + : 40033 : const std::string& getValStr() const { return val; }
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ ][ + - +
- + - ][ +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ][ + -
+ - # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ]
[ # # # # ]
69 [ + + - + : 1228742 : bool empty() const { return (values.size() == 0); }
- + - + +
- ]
[ + + + + ]
[ + + + +
- + + + ]
[ + + + +
+ + + + +
+ - - ][ -
- - - - -
- - + + -
- ]
70 : :
71 [ + + + + : 3376618 : size_t size() const { return values.size(); }
+ + + + #
# # # ][ +
+ + + + +
# # ][ + +
+ + + + +
+ + + +
+ ][ + + +
- + - + +
+ + + + +
- + - + -
+ + + + +
+ ][ + + -
+ + + + +
+ + + + +
+ + + -
+ ][ + + +
+ + + + -
+ + ][ + +
+ + + + +
+ ][ # # #
# # # # #
# # # # #
# ][ - - -
- - - - -
- - + + -
- - - ][ #
# # # # #
# # # # #
# # # ]
72 : :
73 : : void reserve(size_t new_cap);
74 : :
75 : : void getObjMap(std::map<std::string,UniValue>& kv) const;
76 : : bool checkObject(const std::map<std::string,UniValue::VType>& memberTypes) const;
77 : : const UniValue& operator[](const std::string& key) const;
78 : : const UniValue& operator[](size_t index) const;
79 [ + - + - : 227954 : bool exists(const std::string& key) const { size_t i; return findKey(key, i); }
+ - + - +
- ][ + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- ][ + - +
- # # # #
# # ][ + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - ][ + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
[ # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
80 : :
81 [ + + + + : 2256364 : bool isNull() const { return (typ == VNULL); }
+ + + + +
+ + + + +
+ + + + ]
[ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + ][ -
+ + + + +
+ + + + +
+ + + + +
- - - - ]
[ - - - -
+ + + + -
- + - - -
- + ]
[ + + + + ]
[ + + + +
+ + + + ]
[ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + ][ + +
+ + + + +
+ + + + +
+ + + + +
+ - + - +
+ + + + +
+ - + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + -
+ + + + +
+ - ][ + +
+ + + + +
+ # # # #
# # # # #
# ][ + + +
+ + - + +
+ + + + +
+ + + + +
+ + + + +
+ + - + -
+ + + + +
+ + + + +
+ + + - +
+ + + # #
# # # # #
# # # # #
# # # # #
# ][ + + +
+ + + + -
+ + + + +
+ + + + +
+ - # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# ][ + + +
+ + + # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ]
82 [ + + + + ]: 7117584 : bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
83 [ + + + + ]: 2256476 : bool isFalse() const { return (typ == VBOOL) && (val != "1"); }
84 [ - + - + ]: 2 : bool isBool() const { return (typ == VBOOL); }
85 [ + + + + : 13497 : bool isStr() const { return (typ == VSTR); }
+ - - + ]
[ + + - +
- + - + -
+ - + -
+ ][ + + +
+ + - ]
[ # # ][ - -
+ + + - ]
86 [ + + - + : 53407 : bool isNum() const { return (typ == VNUM); }
- + - + -
+ - + - +
- + - + -
+ - + -
+ ]
[ + + + + ]
[ + + + +
+ - + + ]
[ - - - -
- - + + ]
87 [ + + + + : 309240 : bool isArray() const { return (typ == VARR); }
+ + ][ + +
+ - + + +
- ][ + + +
+ + + #
# ]
[ # # # # ]
88 [ + + + - ]: 611700 : bool isObject() const { return (typ == VOBJ); }
[ + + + + ]
[ - + - +
- + - + ]
89 : :
90 : : void push_back(UniValue val);
91 : : void push_backV(const std::vector<UniValue>& vec);
92 : : template <class It>
93 : : void push_backV(It first, It last);
94 : :
95 : : void pushKVEnd(std::string key, UniValue val);
96 : : void pushKV(std::string key, UniValue val);
97 : : void pushKVs(UniValue obj);
98 : :
99 : : std::string write(unsigned int prettyIndent = 0,
100 : : unsigned int indentLevel = 0) const;
101 : :
102 : : bool read(std::string_view raw);
103 : :
104 : : private:
105 : : UniValue::VType typ;
106 : : std::string val; // numbers are stored as C++ strings
107 : : std::vector<std::string> keys;
108 : : std::vector<UniValue> values;
109 : :
110 : : void checkType(const VType& expected) const;
111 : : bool findKey(const std::string& key, size_t& retIdx) const;
112 : : void writeArray(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
113 : : void writeObject(unsigned int prettyIndent, unsigned int indentLevel, std::string& s) const;
114 : :
115 : : public:
116 : : // Strict type-specific getters, these throw std::runtime_error if the
117 : : // value is of unexpected type
118 : : const std::vector<std::string>& getKeys() const;
119 : : const std::vector<UniValue>& getValues() const;
120 : : template <typename Int>
121 : : Int getInt() const;
122 : : bool get_bool() const;
123 : : const std::string& get_str() const;
124 : : double get_real() const;
125 : : const UniValue& get_obj() const;
126 : : const UniValue& get_array() const;
127 : :
128 [ # # ]: 15292 : enum VType type() const { return getType(); }
[ + + + - ]
129 : : const UniValue& find_value(std::string_view key) const;
130 : : };
131 : :
132 : : template <class It>
133 : 76 : void UniValue::push_backV(It first, It last)
134 : : {
135 : 76 : checkType(VARR);
136 : 76 : values.insert(values.end(), first, last);
137 : 76 : }
138 : :
139 : : template <typename Int>
140 : 69464 : Int UniValue::getInt() const
141 : : {
142 : : static_assert(std::is_integral_v<Int>);
143 : 69464 : checkType(VNUM);
144 : : Int result;
145 : 69448 : const auto [first_nonmatching, error_condition] = std::from_chars(val.data(), val.data() + val.size(), result);
146 [ + + + + ]: 69448 : if (first_nonmatching != val.data() + val.size() || error_condition != std::errc{}) {
147 [ + - ]: 9 : throw std::runtime_error("JSON integer out of range");
148 : : }
149 : 69439 : return result;
150 : : }
151 : :
152 : : enum jtokentype {
153 : : JTOK_ERR = -1,
154 : : JTOK_NONE = 0, // eof
155 : : JTOK_OBJ_OPEN,
156 : : JTOK_OBJ_CLOSE,
157 : : JTOK_ARR_OPEN,
158 : : JTOK_ARR_CLOSE,
159 : : JTOK_COLON,
160 : : JTOK_COMMA,
161 : : JTOK_KW_NULL,
162 : : JTOK_KW_TRUE,
163 : : JTOK_KW_FALSE,
164 : : JTOK_NUMBER,
165 : : JTOK_STRING,
166 : : };
167 : :
168 : : extern enum jtokentype getJsonToken(std::string& tokenVal,
169 : : unsigned int& consumed, const char *raw, const char *end);
170 : : extern const char *uvTypeName(UniValue::VType t);
171 : :
172 : : static inline bool jsonTokenIsValue(enum jtokentype jtt)
173 : : {
174 : : switch (jtt) {
175 : : case JTOK_KW_NULL:
176 : : case JTOK_KW_TRUE:
177 : : case JTOK_KW_FALSE:
178 : : case JTOK_NUMBER:
179 : : case JTOK_STRING:
180 : : return true;
181 : :
182 : : default:
183 : : return false;
184 : : }
185 : :
186 : : // not reached
187 : : }
188 : :
189 : 7988135 : static inline bool json_isspace(int ch)
190 : : {
191 [ + + # # ]: 7988095 : switch (ch) {
[ + - + - ]
192 : : case 0x20:
193 : : case 0x09:
194 : : case 0x0a:
195 : : case 0x0d:
196 : : return true;
197 : :
198 : 80 : default:
199 [ + - - + ]: 40 : return false;
200 : : }
201 : :
202 : : // not reached
203 : : }
204 : :
205 : : extern const UniValue NullUniValue;
206 : :
207 : : #endif // BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
|