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 4716 : const UniValue NullUniValue; 17 : 18 14521428 : void UniValue::clear() 19 : { 20 14521428 : typ = VNULL; 21 14521428 : val.clear(); 22 14521428 : keys.clear(); 23 14521428 : values.clear(); 24 14521428 : } 25 : 26 1 : void UniValue::setNull() 27 : { 28 1 : clear(); 29 1 : } 30 : 31 2483297 : void UniValue::setBool(bool val_) 32 : { 33 2483297 : clear(); 34 2483297 : typ = VBOOL; 35 2483297 : if (val_) 36 1216674 : val = "1"; 37 2483297 : } 38 : 39 6402137 : static bool validNumStr(const std::string& s) 40 : { 41 6402137 : std::string tokenVal; 42 : unsigned int consumed; 43 6402137 : enum jtokentype tt = getJsonToken(tokenVal, consumed, s.data(), s.data() + s.size()); 44 6402137 : return (tt == JTOK_NUMBER); 45 6402137 : } 46 : 47 6402137 : void UniValue::setNumStr(std::string str) 48 : { 49 6402137 : if (!validNumStr(str)) { 50 1 : throw std::runtime_error{"The string '" + str + "' is not a valid JSON number"}; 51 : } 52 : 53 6402136 : clear(); 54 6402136 : typ = VNUM; 55 6402136 : val = std::move(str); 56 6402137 : } 57 : 58 3044812 : void UniValue::setInt(uint64_t val_) 59 : { 60 3044812 : std::ostringstream oss; 61 : 62 3044812 : oss << val_; 63 : 64 3044812 : return setNumStr(oss.str()); 65 3044812 : } 66 : 67 3208027 : void UniValue::setInt(int64_t val_) 68 : { 69 3208027 : std::ostringstream oss; 70 : 71 3208027 : oss << val_; 72 : 73 3208027 : return setNumStr(oss.str()); 74 3208027 : } 75 : 76 149263 : void UniValue::setFloat(double val_) 77 : { 78 149263 : std::ostringstream oss; 79 : 80 149263 : oss << std::setprecision(16) << val_; 81 : 82 149263 : return setNumStr(oss.str()); 83 149263 : } 84 : 85 4573231 : void UniValue::setStr(std::string str) 86 : { 87 4573231 : clear(); 88 4573231 : typ = VSTR; 89 4573231 : val = std::move(str); 90 4573231 : } 91 : 92 37950 : void UniValue::setArray() 93 : { 94 37950 : clear(); 95 37950 : typ = VARR; 96 37950 : } 97 : 98 511909 : void UniValue::setObject() 99 : { 100 511909 : clear(); 101 511909 : typ = VOBJ; 102 511909 : } 103 : 104 1608483 : void UniValue::push_back(UniValue val) 105 : { 106 1608483 : checkType(VARR); 107 : 108 1608483 : values.push_back(std::move(val)); 109 1608483 : } 110 : 111 2 : void UniValue::push_backV(const std::vector<UniValue>& vec) 112 : { 113 2 : checkType(VARR); 114 : 115 2 : values.insert(values.end(), vec.begin(), vec.end()); 116 2 : } 117 : 118 13904468 : void UniValue::__pushKV(std::string key, UniValue val) 119 : { 120 13904468 : checkType(VOBJ); 121 : 122 13904468 : keys.push_back(std::move(key)); 123 13904468 : values.push_back(std::move(val)); 124 13904468 : } 125 : 126 13913153 : void UniValue::pushKV(std::string key, UniValue val) 127 : { 128 13913153 : checkType(VOBJ); 129 : 130 : size_t idx; 131 13913153 : if (findKey(key, idx)) 132 30279 : values[idx] = std::move(val); 133 : else 134 13882874 : __pushKV(std::move(key), std::move(val)); 135 13913153 : } 136 : 137 7789 : void UniValue::pushKVs(UniValue obj) 138 : { 139 7789 : checkType(VOBJ); 140 7789 : obj.checkType(VOBJ); 141 : 142 20693 : for (size_t i = 0; i < obj.keys.size(); i++) 143 12904 : __pushKV(std::move(obj.keys.at(i)), std::move(obj.values.at(i))); 144 7789 : } 145 : 146 1 : void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const 147 : { 148 1 : if (typ != VOBJ) 149 0 : return; 150 : 151 1 : kv.clear(); 152 3 : for (size_t i = 0; i < keys.size(); i++) 153 2 : kv[keys[i]] = values[i]; 154 1 : } 155 : 156 14116073 : bool UniValue::findKey(const std::string& key, size_t& retIdx) const 157 : { 158 113730894 : for (size_t i = 0; i < keys.size(); i++) { 159 99804477 : if (keys[i] == key) { 160 189656 : retIdx = i; 161 189656 : return true; 162 : } 163 99614821 : } 164 : 165 13926417 : return false; 166 14116073 : } 167 : 168 9 : bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t) const 169 : { 170 9 : if (typ != VOBJ) { 171 0 : return false; 172 : } 173 : 174 43 : for (const auto& object: t) { 175 36 : size_t idx = 0; 176 36 : if (!findKey(object.first, idx)) { 177 0 : return false; 178 : } 179 : 180 36 : if (values.at(idx).getType() != object.second) { 181 2 : return false; 182 : } 183 : } 184 : 185 7 : return true; 186 9 : } 187 : 188 160089 : const UniValue& UniValue::operator[](const std::string& key) const 189 : { 190 160089 : if (typ != VOBJ) 191 0 : return NullUniValue; 192 : 193 160089 : size_t index = 0; 194 160089 : if (!findKey(key, index)) 195 6842 : return NullUniValue; 196 : 197 153247 : return values.at(index); 198 160089 : } 199 : 200 2582124 : const UniValue& UniValue::operator[](size_t index) const 201 : { 202 2582124 : if (typ != VOBJ && typ != VARR) 203 6186 : return NullUniValue; 204 2575938 : if (index >= values.size()) 205 270605 : return NullUniValue; 206 : 207 2305333 : return values.at(index); 208 2582124 : } 209 : 210 34987058 : void UniValue::checkType(const VType& expected) const 211 : { 212 34987058 : if (typ != expected) { 213 318 : throw type_error{"JSON value of type " + std::string{uvTypeName(typ)} + " is not of expected type " + 214 159 : std::string{uvTypeName(expected)}}; 215 : } 216 34987058 : } 217 : 218 622 : const char *uvTypeName(UniValue::VType t) 219 : { 220 622 : switch (t) { 221 13 : case UniValue::VNULL: return "null"; 222 46 : case UniValue::VBOOL: return "bool"; 223 76 : case UniValue::VOBJ: return "object"; 224 18 : case UniValue::VARR: return "array"; 225 236 : case UniValue::VSTR: return "string"; 226 233 : case UniValue::VNUM: return "number"; 227 : } 228 : 229 : // not reached 230 0 : return nullptr; 231 622 : } 232 : 233 1610067 : const UniValue& UniValue::find_value(std::string_view key) const 234 : { 235 4758472 : for (unsigned int i = 0; i < keys.size(); ++i) { 236 4703828 : if (keys[i] == key) { 237 1555423 : return values.at(i); 238 : } 239 3148405 : } 240 54644 : return NullUniValue; 241 1610067 : } 242 :