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