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 <memory>
11 : : #include <sstream>
12 : : #include <string>
13 : : #include <utility>
14 : : #include <vector>
15 : :
16 : : const UniValue NullUniValue;
17 : :
18 : 10246598 : void UniValue::clear()
19 : : {
20 : 10246598 : typ = VNULL;
21 : 10246598 : val.clear();
22 : 10246598 : keys.clear();
23 : 10246598 : values.clear();
24 : 10246598 : }
25 : :
26 : 195462 : void UniValue::setNull()
27 : : {
28 : 195462 : clear();
29 : 195462 : }
30 : :
31 : 5646214 : void UniValue::setBool(bool val_)
32 : : {
33 : 5646214 : clear();
34 : 5646214 : typ = VBOOL;
35 [ + + ]: 5646214 : if (val_)
36 : 5260009 : val = "1";
37 : 5646214 : }
38 : :
39 : 1526277 : static bool validNumStr(const std::string& s)
40 : : {
41 [ - + ]: 1526277 : std::string tokenVal;
42 : 1526277 : unsigned int consumed;
43 [ - + + - ]: 1526277 : enum jtokentype tt = getJsonToken(tokenVal, consumed, s.data(), s.data() + s.size());
44 : 1526277 : return (tt == JTOK_NUMBER);
45 : 1526277 : }
46 : :
47 : 1526277 : void UniValue::setNumStr(std::string str)
48 : : {
49 [ + + ]: 1526277 : if (!validNumStr(str)) {
50 [ + - + - ]: 3 : throw std::runtime_error{"The string '" + str + "' is not a valid JSON number"};
51 : : }
52 : :
53 : 1526276 : clear();
54 : 1526276 : typ = VNUM;
55 : 1526276 : val = std::move(str);
56 : 1526276 : }
57 : :
58 : 719161 : void UniValue::setInt(uint64_t val_)
59 : : {
60 : 719161 : std::ostringstream oss;
61 : :
62 [ + - ]: 719161 : oss << val_;
63 : :
64 [ + - + - ]: 1438322 : return setNumStr(oss.str());
65 : 719161 : }
66 : :
67 : 734796 : void UniValue::setInt(int64_t val_)
68 : : {
69 : 734796 : std::ostringstream oss;
70 : :
71 [ + - ]: 734796 : oss << val_;
72 : :
73 [ + - + - ]: 1469592 : return setNumStr(oss.str());
74 : 734796 : }
75 : :
76 : 72284 : void UniValue::setFloat(double val_)
77 : : {
78 : 72284 : std::ostringstream oss;
79 : :
80 [ + - ]: 72284 : oss << std::setprecision(16) << val_;
81 : :
82 [ + - + - ]: 144568 : return setNumStr(oss.str());
83 : 72284 : }
84 : :
85 : 2496341 : void UniValue::setStr(std::string str)
86 : : {
87 : 2496341 : clear();
88 : 2496341 : typ = VSTR;
89 : 2496341 : val = std::move(str);
90 : 2496341 : }
91 : :
92 : 751 : void UniValue::setArray()
93 : : {
94 : 751 : clear();
95 : 751 : typ = VARR;
96 : 751 : }
97 : :
98 : 190413 : void UniValue::setObject()
99 : : {
100 : 190413 : clear();
101 : 190413 : typ = VOBJ;
102 : 190413 : }
103 : :
104 : 893639 : void UniValue::push_back(UniValue val)
105 : : {
106 : 893639 : checkType(VARR);
107 : :
108 : 893638 : values.push_back(std::move(val));
109 : 893638 : }
110 : :
111 : 2 : void UniValue::push_backV(const std::vector<UniValue>& vec)
112 : : {
113 : 2 : checkType(VARR);
114 : :
115 : 1 : values.insert(values.end(), vec.begin(), vec.end());
116 : 1 : }
117 : :
118 : 4252623 : void UniValue::pushKVEnd(std::string key, UniValue val)
119 : : {
120 : 4252623 : checkType(VOBJ);
121 : :
122 : 4252622 : keys.push_back(std::move(key));
123 : 4252622 : values.push_back(std::move(val));
124 : 4252622 : }
125 : :
126 : 4233087 : void UniValue::pushKV(std::string key, UniValue val)
127 : : {
128 : 4233087 : checkType(VOBJ);
129 : :
130 : 4233086 : size_t idx;
131 [ + + ]: 4233086 : if (findKey(key, idx))
132 : 10 : values[idx] = std::move(val);
133 : : else
134 [ + - ]: 8466152 : pushKVEnd(std::move(key), std::move(val));
135 : 4233086 : }
136 : :
137 : 9512 : void UniValue::pushKVs(UniValue obj)
138 : : {
139 : 9512 : checkType(VOBJ);
140 : 9511 : obj.checkType(VOBJ);
141 : :
142 [ - + + + ]: 24500 : for (size_t i = 0; i < obj.keys.size(); i++)
143 [ + - + - ]: 29978 : pushKVEnd(std::move(obj.keys.at(i)), std::move(obj.values.at(i)));
144 : 9511 : }
145 : :
146 : 378437 : void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const
147 : : {
148 [ + - ]: 378437 : if (typ != VOBJ)
149 : : return;
150 : :
151 : 378437 : kv.clear();
152 [ - + + + ]: 3652439 : for (size_t i = 0; i < keys.size(); i++)
153 : 3274002 : kv[keys[i]] = values[i];
154 : : }
155 : :
156 : 4480799 : bool UniValue::findKey(const std::string& key, size_t& retIdx) const
157 : : {
158 [ - + + + ]: 35932821 : for (size_t i = 0; i < keys.size(); i++) {
159 [ + + ]: 31678306 : if (keys[i] == key) {
160 : 226284 : retIdx = i;
161 : 226284 : return true;
162 : : }
163 : : }
164 : :
165 : : return false;
166 : : }
167 : :
168 : 11 : bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t) const
169 : : {
170 [ + - ]: 11 : if (typ != VOBJ) {
171 : : return false;
172 : : }
173 : :
174 [ + + ]: 51 : for (const auto& object: t) {
175 : 42 : size_t idx = 0;
176 [ + - ]: 42 : if (!findKey(object.first, idx)) {
177 : : return false;
178 : : }
179 : :
180 [ + + ]: 42 : if (values.at(idx).getType() != object.second) {
181 : : return false;
182 : : }
183 : : }
184 : :
185 : : return true;
186 : : }
187 : :
188 : 23925 : const UniValue& UniValue::operator[](const std::string& key) const
189 : : {
190 [ + + ]: 23925 : if (typ != VOBJ)
191 : : return NullUniValue;
192 : :
193 : 23863 : size_t index = 0;
194 [ + + ]: 23863 : if (!findKey(key, index))
195 : : return NullUniValue;
196 : :
197 : 21128 : return values.at(index);
198 : : }
199 : :
200 : 1817239 : const UniValue& UniValue::operator[](size_t index) const
201 : : {
202 [ + - ]: 1817239 : if (typ != VOBJ && typ != VARR)
203 : : return NullUniValue;
204 [ - + + + ]: 1817239 : if (index >= values.size())
205 : : return NullUniValue;
206 : :
207 : 1554613 : return values.at(index);
208 : : }
209 : :
210 : 13236212 : void UniValue::checkType(const VType& expected) const
211 : : {
212 [ + + ]: 13236212 : if (typ != expected) {
213 [ + - + - : 90 : throw type_error{"JSON value of type " + std::string{uvTypeName(typ)} + " is not of expected type " +
+ - ]
214 [ + - + - : 180 : std::string{uvTypeName(expected)}};
+ - ]
215 : : }
216 : 13236167 : }
217 : :
218 : 37735 : const char *uvTypeName(UniValue::VType t)
219 : : {
220 [ + + + + : 37735 : switch (t) {
+ - + ]
221 : : case UniValue::VNULL: return "null";
222 : 17 : case UniValue::VBOOL: return "bool";
223 : 10867 : case UniValue::VOBJ: return "object";
224 : 1140 : case UniValue::VARR: return "array";
225 : 15593 : case UniValue::VSTR: return "string";
226 : 86 : case UniValue::VNUM: return "number";
227 : : }
228 : :
229 : : // not reached
230 : 0 : return nullptr;
231 : : }
232 : :
233 : 852504 : const UniValue& UniValue::find_value(std::string_view key) const
234 : : {
235 [ - + + + ]: 2162276 : for (unsigned int i = 0; i < keys.size(); ++i) {
236 [ - + + + ]: 2139693 : if (keys[i] == key) {
237 : 829921 : return values.at(i);
238 : : }
239 : : }
240 : : return NullUniValue;
241 : : }
242 : :
243 : 29349 : void UniValue::reserve(size_t new_cap)
244 : : {
245 : 29349 : values.reserve(new_cap);
246 [ - + ]: 29349 : if (typ == VOBJ) {
247 : 0 : keys.reserve(new_cap);
248 : : }
249 : 29349 : }
|