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 : : #include <univalue.h>
7 : :
8 : : #include <iomanip>
9 : : #include <map>
10 : : #include <sstream>
11 : : #include <string>
12 : : #include <utility>
13 : : #include <vector>
14 : :
15 : : const UniValue NullUniValue;
16 : :
17 : 16175875 : void UniValue::clear()
18 : : {
19 : 16175875 : typ = VNULL;
20 : 16175875 : val.clear();
21 : 16175875 : keys.clear();
22 : 16175875 : values.clear();
23 : 16175875 : }
24 : :
25 : 0 : void UniValue::setNull()
26 : : {
27 : 0 : clear();
28 : 0 : }
29 : :
30 : 92682 : void UniValue::setBool(bool val_)
31 : : {
32 : 92682 : clear();
33 : 92682 : typ = VBOOL;
34 [ + + ]: 92682 : if (val_)
35 : 43890 : val = "1";
36 : 92682 : }
37 : :
38 : 6050605 : static bool validNumStr(const std::string& s)
39 : : {
40 [ - + ]: 6050605 : std::string tokenVal;
41 : 6050605 : unsigned int consumed;
42 [ - + + - ]: 6050605 : enum jtokentype tt = getJsonToken(tokenVal, consumed, s.data(), s.data() + s.size());
43 : 6050605 : return (tt == JTOK_NUMBER);
44 : 6050605 : }
45 : :
46 : 6050605 : void UniValue::setNumStr(std::string str)
47 : : {
48 [ - + ]: 6050605 : if (!validNumStr(str)) {
49 [ # # # # ]: 0 : throw std::runtime_error{"The string '" + str + "' is not a valid JSON number"};
50 : : }
51 : :
52 : 6050605 : clear();
53 : 6050605 : typ = VNUM;
54 : 6050605 : val = std::move(str);
55 : 6050605 : }
56 : :
57 : 33363 : void UniValue::setInt(uint64_t val_)
58 : : {
59 : 33363 : std::ostringstream oss;
60 : :
61 [ + - ]: 33363 : oss << val_;
62 : :
63 [ + - + - ]: 66726 : return setNumStr(oss.str());
64 : 33363 : }
65 : :
66 : 6017155 : void UniValue::setInt(int64_t val_)
67 : : {
68 : 6017155 : std::ostringstream oss;
69 : :
70 [ + - ]: 6017155 : oss << val_;
71 : :
72 [ + - + - ]: 12034310 : return setNumStr(oss.str());
73 : 6017155 : }
74 : :
75 : 87 : void UniValue::setFloat(double val_)
76 : : {
77 : 87 : std::ostringstream oss;
78 : :
79 [ + - ]: 87 : oss << std::setprecision(16) << val_;
80 : :
81 [ + - + - ]: 174 : return setNumStr(oss.str());
82 : 87 : }
83 : :
84 : 9999276 : void UniValue::setStr(std::string str)
85 : : {
86 : 9999276 : clear();
87 : 9999276 : typ = VSTR;
88 : 9999276 : val = std::move(str);
89 : 9999276 : }
90 : :
91 : 8061 : void UniValue::setArray()
92 : : {
93 : 8061 : clear();
94 : 8061 : typ = VARR;
95 : 8061 : }
96 : :
97 : 3472 : void UniValue::setObject()
98 : : {
99 : 3472 : clear();
100 : 3472 : typ = VOBJ;
101 : 3472 : }
102 : :
103 : 3924026 : void UniValue::push_back(UniValue val)
104 : : {
105 : 3924026 : checkType(VARR);
106 : :
107 : 3924026 : values.push_back(std::move(val));
108 : 3924026 : }
109 : :
110 : 0 : void UniValue::push_backV(const std::vector<UniValue>& vec)
111 : : {
112 : 0 : checkType(VARR);
113 : :
114 : 0 : values.insert(values.end(), vec.begin(), vec.end());
115 : 0 : }
116 : :
117 : 18688999 : void UniValue::pushKVEnd(std::string key, UniValue val)
118 : : {
119 : 18688999 : checkType(VOBJ);
120 : :
121 : 18688999 : keys.push_back(std::move(key));
122 : 18688999 : values.push_back(std::move(val));
123 : 18688999 : }
124 : :
125 : 18652446 : void UniValue::pushKV(std::string key, UniValue val)
126 : : {
127 : 18652446 : checkType(VOBJ);
128 : :
129 : 18652446 : size_t idx;
130 [ + + ]: 18652446 : if (findKey(key, idx))
131 : 1127 : values[idx] = std::move(val);
132 : : else
133 [ + - ]: 37302638 : pushKVEnd(std::move(key), std::move(val));
134 : 18652446 : }
135 : :
136 : 15 : void UniValue::pushKVs(UniValue obj)
137 : : {
138 : 15 : checkType(VOBJ);
139 : 15 : obj.checkType(VOBJ);
140 : :
141 [ - + + + ]: 59 : for (size_t i = 0; i < obj.keys.size(); i++)
142 [ + - + - ]: 88 : pushKVEnd(std::move(obj.keys.at(i)), std::move(obj.values.at(i)));
143 : 15 : }
144 : :
145 : 0 : void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const
146 : : {
147 [ # # ]: 0 : if (typ != VOBJ)
148 : : return;
149 : :
150 : 0 : kv.clear();
151 [ # # # # ]: 0 : for (size_t i = 0; i < keys.size(); i++)
152 : 0 : kv[keys[i]] = values[i];
153 : : }
154 : :
155 : 18786036 : bool UniValue::findKey(const std::string& key, size_t& retIdx) const
156 : : {
157 [ - + + + ]: 45415248 : for (size_t i = 0; i < keys.size(); i++) {
158 [ + + ]: 26763595 : if (keys[i] == key) {
159 : 134383 : retIdx = i;
160 : 134383 : return true;
161 : : }
162 : : }
163 : :
164 : : return false;
165 : : }
166 : :
167 : 0 : bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t) const
168 : : {
169 [ # # ]: 0 : if (typ != VOBJ) {
170 : : return false;
171 : : }
172 : :
173 [ # # ]: 0 : for (const auto& object: t) {
174 : 0 : size_t idx = 0;
175 [ # # ]: 0 : if (!findKey(object.first, idx)) {
176 : : return false;
177 : : }
178 : :
179 [ # # ]: 0 : if (values.at(idx).getType() != object.second) {
180 : : return false;
181 : : }
182 : : }
183 : :
184 : : return true;
185 : : }
186 : :
187 : 133439 : const UniValue& UniValue::operator[](const std::string& key) const
188 : : {
189 [ + + ]: 133439 : if (typ != VOBJ)
190 : : return NullUniValue;
191 : :
192 : 133431 : size_t index = 0;
193 [ + + ]: 133431 : if (!findKey(key, index))
194 : : return NullUniValue;
195 : :
196 : 133256 : return values.at(index);
197 : : }
198 : :
199 : 90813 : const UniValue& UniValue::operator[](size_t index) const
200 : : {
201 [ + - ]: 90813 : if (typ != VOBJ && typ != VARR)
202 : : return NullUniValue;
203 [ - + + + ]: 90813 : if (index >= values.size())
204 : : return NullUniValue;
205 : :
206 : 80071 : return values.at(index);
207 : : }
208 : :
209 : 41572157 : void UniValue::checkType(const VType& expected) const
210 : : {
211 [ + + ]: 41572157 : if (typ != expected) {
212 [ + - + - : 24374 : throw type_error{"JSON value of type " + std::string{uvTypeName(typ)} + " is not of expected type " +
+ - ]
213 [ + - + - : 48748 : std::string{uvTypeName(expected)}};
+ - ]
214 : : }
215 : 41559970 : }
216 : :
217 : 24594 : const char *uvTypeName(UniValue::VType t)
218 : : {
219 [ + + + + : 24594 : switch (t) {
+ - + ]
220 : : case UniValue::VNULL: return "null";
221 : 51 : case UniValue::VBOOL: return "bool";
222 : 276 : case UniValue::VOBJ: return "object";
223 : 306 : case UniValue::VARR: return "array";
224 : 11961 : case UniValue::VSTR: return "string";
225 : 4163 : case UniValue::VNUM: return "number";
226 : : }
227 : :
228 : : // not reached
229 : 0 : return nullptr;
230 : : }
231 : :
232 : 21337 : const UniValue& UniValue::find_value(std::string_view key) const
233 : : {
234 [ - + + + ]: 621151 : for (unsigned int i = 0; i < keys.size(); ++i) {
235 [ - + + + ]: 605597 : if (keys[i] == key) {
236 : 5783 : return values.at(i);
237 : : }
238 : : }
239 : : return NullUniValue;
240 : : }
241 : :
242 : 23016 : void UniValue::reserve(size_t new_cap)
243 : : {
244 : 23016 : values.reserve(new_cap);
245 [ - + ]: 23016 : if (typ == VOBJ) {
246 : 0 : keys.reserve(new_cap);
247 : : }
248 : 23016 : }
|