Coverage Report

Created: 2025-06-10 13:21

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