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 [ + + # # ]: 258319 : UniValue() { typ = VNULL; }
[ + - + -
# # # # #
# # # # #
# # ][ + -
+ - - + +
- + - + -
+ - + - ]
[ + - + -
+ - + - +
- + - + -
+ - + - +
- - + +
- ][ + - +
- + + ]
[ + + + ][ -
- + + + -
- - - - ]
32 [ + - + - : 25010 : 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 : 441309 : UniValue(Ref&& val)
40 [ + + ]: 441309 : {
41 : : if constexpr (std::is_floating_point_v<T>) {
42 [ + - ]: 90 : setFloat(val);
43 : : } else if constexpr (std::is_same_v<bool, T>) {
44 [ + - ]: 168020 : setBool(val);
45 : : } else if constexpr (std::is_signed_v<T>) {
46 [ + - ]: 1801 : setInt(int64_t{val});
47 : : } else if constexpr (std::is_unsigned_v<T>) {
48 [ + - ]: 257 : setInt(uint64_t{val});
49 : : } else {
50 [ + - ]: 271141 : setStr(std::string{std::forward<Ref>(val)});
[ + - + - ]
51 : : }
52 : 441309 : }
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 [ - + - + : 28784 : enum VType getType() const { return typ; }
- + - + -
+ - + - +
- + - + -
+ - + ][ +
+ + - +
+ ][ + + #
# # # ][ -
- + + - +
+ + + -
- ]
68 [ + + ][ - + : 199 : const std::string& getValStr() const { return val; }
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- + - + -
+ - + ][ #
# # # #
# ][ # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # ]
69 [ - + + + ]: 175 : bool empty() const { return (values.size() == 0); }
[ - + - +
- + - + -
+ - + - +
- + + - ]
[ - - - -
- - - - -
- - - - -
- - - + +
+ - - -
- ][ # # #
# # # #
# ][ - + +
+ - + + +
- + + + -
+ + + ]
70 : :
71 [ - + - + : 8808 : 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 [ # # # # : 19 : bool exists(const std::string& key) const { size_t i; return findKey(key, i); }
# # # # #
# ][ + - +
- + - + -
+ - + - +
- + - + -
+ - + - +
- # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ +
- + - # #
# # # # #
# # # # #
# # # # #
# # # ][ #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ][ + - #
# # # # #
# # ][ # #
# # # # ]
80 : :
81 [ + - - + : 206097 : bool isNull() const { return (typ == VNULL); }
- - - + -
+ - - - +
- + - + ]
[ + + + +
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ][ - - -
- - - + -
+ + + + -
- - - - -
- - # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ][ - - -
- - - - -
- - - - -
- - - + +
+ + - + -
- - - ][ #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # ][ +
+ + + + +
+ + # # #
# # # # #
# # ][ # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # # #
# # # #
# ][ + + #
# # # ][ +
+ + + + +
+ + + + ]
[ + - + -
+ - # # #
# ][ - - -
- + + + +
- - + - -
- - + ]
82 [ + + + + ]: 115269 : bool isTrue() const { return (typ == VBOOL) && (val == "1"); }
83 [ + + + + ]: 1352331 : bool isFalse() const { return (typ == VBOOL) && (val != "1"); }
84 [ - + - + ]: 2 : bool isBool() const { return (typ == VBOOL); }
85 [ + - + - ]: 556 : bool isStr() const { return (typ == VSTR); }
[ + - - +
+ - - + ]
[ - + - +
- + - + -
+ - + -
+ ][ - - +
+ + - ][ #
# # # #
# ]
86 [ - - # # ]: 165 : bool isNum() const { return (typ == VNUM); }
[ - + - + ]
[ - + - +
- + - + -
+ - + - +
- + - + -
+ - + -
+ ][ - - -
- - - +
+ ]
87 [ - + + + : 82658 : bool isArray() const { return (typ == VARR); }
+ + ][ + +
# # # # ]
[ + + + -
+ + + - ]
[ # # # # ]
88 [ + + ]: 82 : 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 [ # # # # ]: 10 : enum VType type() const { return getType(); }
[ + + - - ]
129 : : const UniValue& find_value(std::string_view key) const;
130 : : };
131 : :
132 : : template <class It>
133 : 0 : void UniValue::push_backV(It first, It last)
134 : : {
135 : 0 : checkType(VARR);
136 : 0 : values.insert(values.end(), first, last);
137 : 0 : }
138 : :
139 : : template <typename Int>
140 : 1503 : Int UniValue::getInt() const
141 : : {
142 : : static_assert(std::is_integral_v<Int>);
143 : 1503 : checkType(VNUM);
144 : : Int result;
145 [ - + ]: 1501 : const auto [first_nonmatching, error_condition] = std::from_chars(val.data(), val.data() + val.size(), result);
146 [ - + + + : 1501 : if (first_nonmatching != val.data() + val.size() || error_condition != std::errc{}) {
+ + ]
147 [ + - ]: 4 : throw std::runtime_error("JSON integer out of range");
148 : : }
149 : 1497 : 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 : 49085 : static inline bool jsonTokenIsValue(enum jtokentype jtt)
173 : : {
174 [ + + ]: 49085 : 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 : 31018 : default:
183 [ + + ]: 31018 : return false;
184 : : }
185 : :
186 : : // not reached
187 : : }
188 : :
189 : 111181 : static inline bool json_isspace(int ch)
190 : : {
191 [ + - + - ]: 111175 : switch (ch) {
[ + + ]
192 : : case 0x20:
193 : : case 0x09:
194 : : case 0x0a:
195 : : case 0x0d:
196 : : return true;
197 : :
198 : 12 : default:
199 [ + - - + ]: 6 : return false;
200 : : }
201 : :
202 : : // not reached
203 : : }
204 : :
205 : : extern const UniValue NullUniValue;
206 : :
207 : : #endif // BITCOIN_UNIVALUE_INCLUDE_UNIVALUE_H
|