Coverage Report

Created: 2026-07-14 18:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/bitcoin/src/univalue/lib/univalue.cpp
Line
Count
Source
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
void UniValue::clear()
18
1.92M
{
19
1.92M
    typ = VNULL;
20
1.92M
    val.clear();
21
1.92M
    keys.clear();
22
1.92M
    values.clear();
23
1.92M
}
24
25
void UniValue::setNull()
26
0
{
27
0
    clear();
28
0
}
29
30
void UniValue::setBool(bool val_)
31
751k
{
32
751k
    clear();
33
751k
    typ = VBOOL;
34
751k
    if (val_)
  Branch (34:9): [True: 745k, False: 5.92k]
35
745k
        val = "1";
36
751k
}
37
38
static bool validNumStr(const std::string& s)
39
2.91k
{
40
2.91k
    std::string tokenVal;
41
2.91k
    unsigned int consumed;
42
2.91k
    enum jtokentype tt = getJsonToken(tokenVal, consumed, s.data(), s.data() + s.size());
43
2.91k
    return (tt == JTOK_NUMBER);
44
2.91k
}
45
46
void UniValue::setNumStr(std::string str)
47
2.91k
{
48
2.91k
    if (!validNumStr(str)) {
  Branch (48:9): [True: 0, False: 2.91k]
49
0
        throw std::runtime_error{"The string '" + str + "' is not a valid JSON number"};
50
0
    }
51
52
2.91k
    clear();
53
2.91k
    typ = VNUM;
54
2.91k
    val = std::move(str);
55
2.91k
}
56
57
void UniValue::setInt(uint64_t val_)
58
216
{
59
216
    std::ostringstream oss;
60
61
216
    oss << val_;
62
63
216
    return setNumStr(oss.str());
64
216
}
65
66
void UniValue::setInt(int64_t val_)
67
2.64k
{
68
2.64k
    std::ostringstream oss;
69
70
2.64k
    oss << val_;
71
72
2.64k
    return setNumStr(oss.str());
73
2.64k
}
74
75
void UniValue::setFloat(double val_)
76
54
{
77
54
    std::ostringstream oss;
78
79
54
    oss << std::setprecision(16) << val_;
80
81
54
    return setNumStr(oss.str());
82
54
}
83
84
void UniValue::setStr(std::string str)
85
487k
{
86
487k
    clear();
87
487k
    typ = VSTR;
88
487k
    val = std::move(str);
89
487k
}
90
91
void UniValue::setArray()
92
0
{
93
0
    clear();
94
0
    typ = VARR;
95
0
}
96
97
void UniValue::setObject()
98
336k
{
99
336k
    clear();
100
336k
    typ = VOBJ;
101
336k
}
102
103
void UniValue::push_back(UniValue val)
104
0
{
105
0
    checkType(VARR);
106
107
0
    values.push_back(std::move(val));
108
0
}
109
110
void UniValue::push_backV(const std::vector<UniValue>& vec)
111
0
{
112
0
    checkType(VARR);
113
114
0
    values.insert(values.end(), vec.begin(), vec.end());
115
0
}
116
117
void UniValue::pushKVEnd(std::string key, UniValue val)
118
1.02M
{
119
1.02M
    checkType(VOBJ);
120
121
1.02M
    keys.push_back(std::move(key));
122
1.02M
    values.push_back(std::move(val));
123
1.02M
}
124
125
void UniValue::pushKV(std::string key, UniValue val)
126
1.02M
{
127
1.02M
    checkType(VOBJ);
128
129
1.02M
    size_t idx;
130
1.02M
    if (findKey(key, idx))
  Branch (130:9): [True: 0, False: 1.02M]
131
0
        values[idx] = std::move(val);
132
1.02M
    else
133
1.02M
        pushKVEnd(std::move(key), std::move(val));
134
1.02M
}
135
136
void UniValue::pushKVs(UniValue obj)
137
0
{
138
0
    checkType(VOBJ);
139
0
    obj.checkType(VOBJ);
140
141
0
    for (size_t i = 0; i < obj.keys.size(); i++)
  Branch (141:24): [True: 0, False: 0]
142
0
        pushKVEnd(std::move(obj.keys.at(i)), std::move(obj.values.at(i)));
143
0
}
144
145
void UniValue::getObjMap(std::map<std::string,UniValue>& kv) const
146
0
{
147
0
    if (typ != VOBJ)
  Branch (147:9): [True: 0, False: 0]
148
0
        return;
149
150
0
    kv.clear();
151
0
    for (size_t i = 0; i < keys.size(); i++)
  Branch (151:24): [True: 0, False: 0]
152
0
        kv[keys[i]] = values[i];
153
0
}
154
155
bool UniValue::findKey(const std::string& key, size_t& retIdx) const
156
1.36M
{
157
3.06M
    for (size_t i = 0; i < keys.size(); i++) {
  Branch (157:24): [True: 2.03M, False: 1.02M]
158
2.03M
        if (keys[i] == key) {
  Branch (158:13): [True: 337k, False: 1.69M]
159
337k
            retIdx = i;
160
337k
            return true;
161
337k
        }
162
2.03M
    }
163
164
1.02M
    return false;
165
1.36M
}
166
167
bool UniValue::checkObject(const std::map<std::string,UniValue::VType>& t) const
168
0
{
169
0
    if (typ != VOBJ) {
  Branch (169:9): [True: 0, False: 0]
170
0
        return false;
171
0
    }
172
173
0
    for (const auto& object: t) {
  Branch (173:28): [True: 0, False: 0]
174
0
        size_t idx = 0;
175
0
        if (!findKey(object.first, idx)) {
  Branch (175:13): [True: 0, False: 0]
176
0
            return false;
177
0
        }
178
179
0
        if (values.at(idx).getType() != object.second) {
  Branch (179:13): [True: 0, False: 0]
180
0
            return false;
181
0
        }
182
0
    }
183
184
0
    return true;
185
0
}
186
187
const UniValue& UniValue::operator[](const std::string& key) const
188
0
{
189
0
    if (typ != VOBJ)
  Branch (189:9): [True: 0, False: 0]
190
0
        return NullUniValue;
191
192
0
    size_t index = 0;
193
0
    if (!findKey(key, index))
  Branch (193:9): [True: 0, False: 0]
194
0
        return NullUniValue;
195
196
0
    return values.at(index);
197
0
}
198
199
const UniValue& UniValue::operator[](size_t index) const
200
1.03M
{
201
1.03M
    if (typ != VOBJ && typ != VARR)
  Branch (201:9): [True: 1.03M, False: 0]
  Branch (201:24): [True: 0, False: 1.03M]
202
0
        return NullUniValue;
203
1.03M
    if (index >= values.size())
  Branch (203:9): [True: 780k, False: 257k]
204
780k
        return NullUniValue;
205
206
257k
    return values.at(index);
207
1.03M
}
208
209
void UniValue::checkType(const VType& expected) const
210
3.66M
{
211
3.66M
    if (typ != expected) {
  Branch (211:9): [True: 0, False: 3.66M]
212
0
        throw type_error{"JSON value of type " + std::string{uvTypeName(typ)} + " is not of expected type " +
213
0
                                 std::string{uvTypeName(expected)}};
214
0
    }
215
3.66M
}
216
217
const char *uvTypeName(UniValue::VType t)
218
0
{
219
0
    switch (t) {
  Branch (219:13): [True: 0, False: 0]
220
0
    case UniValue::VNULL: return "null";
  Branch (220:5): [True: 0, False: 0]
221
0
    case UniValue::VBOOL: return "bool";
  Branch (221:5): [True: 0, False: 0]
222
0
    case UniValue::VOBJ: return "object";
  Branch (222:5): [True: 0, False: 0]
223
0
    case UniValue::VARR: return "array";
  Branch (223:5): [True: 0, False: 0]
224
0
    case UniValue::VSTR: return "string";
  Branch (224:5): [True: 0, False: 0]
225
0
    case UniValue::VNUM: return "number";
  Branch (225:5): [True: 0, False: 0]
226
0
    }
227
228
    // not reached
229
0
    return nullptr;
230
0
}
231
232
const UniValue& UniValue::find_value(std::string_view key) const
233
1.35M
{
234
3.38M
    for (unsigned int i = 0; i < keys.size(); ++i) {
  Branch (234:30): [True: 3.38M, False: 18.4E]
235
3.38M
        if (keys[i] == key) {
  Branch (235:13): [True: 1.35M, False: 2.03M]
236
1.35M
            return values.at(i);
237
1.35M
        }
238
3.38M
    }
239
18.4E
    return NullUniValue;
240
1.35M
}
241
242
void UniValue::reserve(size_t new_cap)
243
0
{
244
0
    values.reserve(new_cap);
245
0
    if (typ == VOBJ) {
  Branch (245:9): [True: 0, False: 0]
246
0
        keys.reserve(new_cap);
247
0
    }
248
0
}