• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

libbitcoin / libbitcoin-system / 41739337421

03 Nov 2026 11:27PM UTC coverage: 96.274% (-0.6%) from 96.843%
41739337421

push

github

web-flow
Merge pull request #2151 from evoskuil/master

Stop reading on reader failure, export instantiations only for windows libs.

11 of 11 new or added lines in 5 files covered. (100.0%)

302 existing lines in 67 files now uncovered.

26460 of 27484 relevant lines covered (96.27%)

4041533.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.62
/src/serial/json/object.cpp
1
/**
2
 * Copyright (c) 2011-2026 libbitcoin developers
3
 *
4
 * This file is part of libbitcoin.
5
 *
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU Affero General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * This program is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
 * GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public License
17
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
 */
19
#include <bitcoin/system/serial/json/value.hpp>
20

21
#include <bitcoin/system/define.hpp>
22

23
namespace libbitcoin {
24
namespace system {
25
namespace json {
26

27
BC_PUSH_WARNING(NO_ARRAY_INDEXING)
28

29
object::object() NOEXCEPT
3,304 ✔
30
  : members_{}, buckets_{}
3,304 ✔
31
{
32
}
3,304 ✔
33

34
object::object(const object& other) THROWS
4,611 ✔
35
  : members_(other.members_),
4,611 ✔
36
    buckets_(other.buckets_ ?
4,612 ✔
37
        std::make_unique<std::vector<size_t>>(*other.buckets_) : nullptr)
1 ✔
38
{
39
}
4,611 ✔
40

41
object::object(object&& other) NOEXCEPT
10,043 ✔
42
  : members_(std::move(other.members_)),
10,043 ✔
43
    buckets_(std::move(other.buckets_))
10,043 ✔
44
{
45
    other.members_.clear();
10,043 ✔
46
}
10,043 ✔
47

48
object::object(init_list list) THROWS
24 ✔
49
  : object()
24 ✔
50
{
51
    insert(list);
24 ✔
52
}
24 ✔
53

54
object::~object() NOEXCEPT
17,958 ✔
55
{
56
}
17,958 ✔
57

58
object& object::operator=(const object& other) THROWS
×
59
{
60
    if (this != &other)
×
61
        object(other).swap(*this);
×
62

63
    return *this;
×
64
}
65

66
object& object::operator=(object&& other) NOEXCEPT
×
67
{
68
    members_ = std::move(other.members_);
×
UNCOV
69
    buckets_ = std::move(other.buckets_);
×
70
    other.members_.clear();
×
71
    return *this;
×
72
}
73

74
object& object::operator=(init_list list) THROWS
×
75
{
76
    object(list).swap(*this);
×
77
    return *this;
×
78
}
79

80
void object::reserve(size_t count) THROWS
189 ✔
81
{
82
    members_.reserve(count);
189 ✔
83
}
189 ✔
84

85
value& object::at(std::string_view key) THROWS
6 ✔
86
{
87
    const auto position = locate(key);
6 ✔
88
    if (position == npos)
6 ✔
89
        throw_error(error::json_out_of_range);
×
90

91
    return members_[position].value_;
6 ✔
92
}
93

94
const value& object::at(std::string_view key) const THROWS
1,127 ✔
95
{
96
    const auto position = locate(key);
1,127 ✔
97
    if (position == npos)
1,127 ✔
98
        throw_error(error::json_out_of_range);
2 ✔
99

100
    return members_[position].value_;
1,125 ✔
101
}
102

103
value& object::operator[](std::string_view key) THROWS
309 ✔
104
{
105
    return emplace(key, nullptr).first->value_;
309 ✔
106
}
107

108
value* object::if_contains(std::string_view key) NOEXCEPT
×
109
{
110
    const auto position = locate(key);
×
111
    return position == npos ? nullptr : &members_[position].value_;
×
112
}
113

114
const value* object::if_contains(std::string_view key) const NOEXCEPT
339 ✔
115
{
116
    const auto position = locate(key);
339 ✔
117
    return position == npos ? nullptr : &members_[position].value_;
339 ✔
118
}
119

120
void object::clear() NOEXCEPT
1 ✔
121
{
122
    members_.clear();
1 ✔
123
    buckets_.reset();
1 ✔
124
}
1 ✔
125

126
void object::insert(init_list list) THROWS
25 ✔
127
{
128
    reserve(size() + list.size());
25 ✔
129
    for (const auto& pair: list)
67 ✔
130
        emplace(pair.first, pair.second.make_value());
42 ✔
131
}
25 ✔
132

133
object::iterator object::erase(const_iterator position) NOEXCEPT
4 ✔
134
{
135
    const auto offset = std::distance(cbegin(), position);
4 ✔
136
    const auto index = possible_narrow_and_sign_cast<size_t>(offset);
4 ✔
137
    if (index != sub1(members_.size()))
4 ✔
138
        members_[index] = std::move(members_.back());
3 ✔
139

140
    members_.pop_back();
4 ✔
141

142
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
143
    reindex();
4 ✔
144
    BC_POP_WARNING()
145

146
    return std::next(begin(), offset);
4 ✔
147
}
148

149
size_t object::erase(std::string_view key) NOEXCEPT
4 ✔
150
{
151
    const auto it = find(key);
4 ✔
152
    if (it == end())
4 ✔
153
        return zero;
154

155
    erase(it);
3 ✔
156
    return one;
3 ✔
157
}
158

159
object::iterator object::stable_erase(const_iterator position) NOEXCEPT
2 ✔
160
{
161
    const auto offset = std::distance(cbegin(), position);
2 ✔
162
    members_.erase(std::next(members_.cbegin(), offset));
4 ✔
163

164
    BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
165
    reindex();
2 ✔
166
    BC_POP_WARNING()
167

168
    return std::next(begin(), offset);
2 ✔
169
}
170

171
size_t object::stable_erase(std::string_view key) NOEXCEPT
3 ✔
172
{
173
    const auto it = find(key);
3 ✔
174
    if (it == end())
3 ✔
175
        return zero;
176

177
    stable_erase(it);
2 ✔
178
    return one;
2 ✔
179
}
180

181
void object::swap(object& other) NOEXCEPT
1 ✔
182
{
183
    members_.swap(other.members_);
1 ✔
184
    buckets_.swap(other.buckets_);
1 ✔
185
}
1 ✔
186

187
bool object::operator==(const object& other) const NOEXCEPT
82 ✔
188
{
189
    if (size() != other.size())
82 ✔
190
        return false;
191

192
    return std::all_of(cbegin(), cend(),
81 ✔
193
        [&other](const key_value_pair& member) NOEXCEPT
281 ✔
194
        {
195
            const auto found = other.if_contains(member.key());
281 ✔
196
            return !is_null(found) && (*found == member.value());
281 ✔
197
        });
81 ✔
198
}
199

200
// private
201
// ----------------------------------------------------------------------------
202

203
size_t object::locate(std::string_view key) const NOEXCEPT
4,583 ✔
204
{
205
    if (!buckets_)
4,583 ✔
206
    {
207
        for (size_t position{}; position < members_.size(); ++position)
11,035 ✔
208
            if (members_[position].key_ == key)
8,119 ✔
209
                return position;
210

211
        return npos;
212
    }
213

214
    const auto& buckets = *buckets_;
253 ✔
215
    const auto bucket = std::hash<std::string_view>{}(key) % buckets.size();
253 ✔
216
    for (auto position = buckets[bucket]; position != npos;
408 ✔
217
        position = members_[position].next_)
155 ✔
218
        if (members_[position].key_ == key)
244 ✔
219
            return position;
220

221
    return npos;
222
}
223

224
object::iterator object::append(key_value_pair&& member) THROWS
3,038 ✔
225
{
226
    members_.push_back(std::move(member));
3,038 ✔
227
    const auto position = sub1(members_.size());
3,038 ✔
228

229
    if (!buckets_)
3,038 ✔
230
    {
231
        if (members_.size() > indexed)
2,877 ✔
232
            reindex();
7 ✔
233
    }
234
    else if (members_.size() > buckets_->size())
161 ✔
235
    {
236
        reindex();
7 ✔
237
    }
238
    else
239
    {
240
        link(position);
154 ✔
241
    }
242

243
    return std::next(begin(), position);
3,038 ✔
244
}
245

246
void object::link(size_t position) NOEXCEPT
595 ✔
247
{
248
    auto& buckets = *buckets_;
595 ✔
249
    auto& member = members_[position];
595 ✔
250
    const auto bucket = std::hash<std::string_view>{}(member.key_) %
595 ✔
251
        buckets.size();
595 ✔
252

253
    member.next_ = buckets[bucket];
595 ✔
254
    buckets[bucket] = position;
595 ✔
255
}
595 ✔
256

257
void object::reindex() THROWS
20 ✔
258
{
259
    if (members_.size() <= indexed)
20 ✔
260
    {
261
        buckets_.reset();
4 ✔
262
        return;
4 ✔
263
    }
264

265
    const auto count = two * members_.size();
16 ✔
266
    if (!buckets_)
16 ✔
267
        buckets_ = std::make_unique<std::vector<size_t>>();
7 ✔
268

269
    buckets_->assign(count, npos);
16 ✔
270
    for (size_t position{}; position < members_.size(); ++position)
457 ✔
271
        link(position);
441 ✔
272
}
273

274
BC_POP_WARNING()
275

276
// key_value_pair
277
// ----------------------------------------------------------------------------
278

279
key_value_pair::key_value_pair(std::string_view key,
3,038 ✔
280
    json::value&& element) THROWS
3,038 ✔
281
  : key_(key), value_(std::move(element)), next_{}
3,038 ✔
282
{
283
}
3,038 ✔
284

285
key_value_pair::key_value_pair(string&& key, json::value&& element) NOEXCEPT
×
286
  : key_(std::move(key)), value_(std::move(element)), next_{}
×
287
{
288
}
×
289

290
void swap(object& left, object& right) NOEXCEPT
1 ✔
291
{
292
    left.swap(right);
1 ✔
293
}
1 ✔
294

295
} // namespace json
296
} // namespace system
297
} // namespace libbitcoin
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc