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

boostorg / url / #611

20 Feb 2026 02:42AM UTC coverage: 99.123% (-0.09%) from 99.217%
#611

push

travis-ci

alandefreitas
feat: constexpr URL parsing for C++20

fix #890

9949 of 10037 relevant lines covered (99.12%)

2919.58 hits per line

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

98.28
include/boost/url/impl/params_ref.hpp
1
//
2
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3
// Copyright (c) 2022 Alan de Freitas (alandefreitas@gmail.com)
4
//
5
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
//
8
// Official repository: https://github.com/boostorg/url
9
//
10

11
#ifndef BOOST_URL_IMPL_PARAMS_REF_HPP
12
#define BOOST_URL_IMPL_PARAMS_REF_HPP
13

14
#include <boost/url/params_view.hpp>
15
#include <boost/url/url_base.hpp>
16
#include <boost/url/detail/any_params_iter.hpp>
17
#include <boost/url/detail/except.hpp>
18
#include <boost/url/grammar/ci_string.hpp>
19
#include <boost/url/grammar/recycled.hpp>
20
#include <boost/assert.hpp>
21
#include <utility>
22

23
namespace boost {
24
namespace urls {
25

26
template<class FwdIt>
27
void
28
params_ref::
16✔
29
assign(FwdIt first, FwdIt last)
30
{
31
/*  If you get a compile error here, it
32
    means that the iterators you passed
33
    do not meet the requirements stated
34
    in the documentation.
35
*/
36
    static_assert(
37
        std::is_convertible<
38
            typename std::iterator_traits<
39
                FwdIt>::reference,
40
            param_view>::value,
41
        "Type requirements not met");
42

43
    assign(first, last,
16✔
44
        typename std::iterator_traits<
45
            FwdIt>::iterator_category{});
46
}
16✔
47

48
template<class FwdIt>
49
auto
50
params_ref::
8✔
51
append(FwdIt first, FwdIt last) ->
52
    iterator
53
{
54
/*  If you get a compile error here, it
55
    means that the iterators you passed
56
    do not meet the requirements stated
57
    in the documentation.
58
*/
59
    static_assert(
60
        std::is_convertible<
61
            typename std::iterator_traits<
62
                FwdIt>::reference,
63
            param_view>::value,
64
        "Type requirements not met");
65

66
    return insert(
8✔
67
        end(), first, last);
8✔
68
}
69

70
template<class FwdIt>
71
auto
72
params_ref::
40✔
73
insert(
74
    iterator before,
75
    FwdIt first,
76
    FwdIt last) ->
77
        iterator
78
{
79
/*  If you get a compile error here, it
80
    means that the iterators you passed
81
    do not meet the requirements stated
82
    in the documentation.
83
*/
84
    static_assert(
85
        std::is_convertible<
86
            typename std::iterator_traits<
87
                FwdIt>::reference,
88
            param_view>::value,
89
        "Type requirements not met");
90

91
    return insert(
80✔
92
        before,
93
        first,
94
        last,
95
        typename std::iterator_traits<
96
            FwdIt>::iterator_category{});
80✔
97
}
98

99
template<class FwdIt>
100
auto
101
params_ref::
8✔
102
replace(
103
    iterator from,
104
    iterator to,
105
    FwdIt first,
106
    FwdIt last) ->
107
        iterator
108
{
109
/*  If you get a compile error here, it
110
    means that the iterators you passed
111
    do not meet the requirements stated
112
    in the documentation.
113
*/
114
    static_assert(
115
        std::is_convertible<
116
            typename std::iterator_traits<
117
                FwdIt>::reference,
118
            param_view>::value,
119
        "Type requirements not met");
120

121
    return iterator(
122
        u_->edit_params(
16✔
123
            from.it_, to.it_,
124
            detail::make_params_iter(
125
                first, last, opt_.space_as_plus)),
8✔
126
        opt_);
16✔
127
}
128

129
//------------------------------------------------
130
//
131
// implementation
132
//
133
//------------------------------------------------
134

135
template<class FwdIt>
136
void
137
params_ref::
16✔
138
assign(FwdIt first, FwdIt last,
139
    std::forward_iterator_tag)
140
{
141
    u_->edit_params(
16✔
142
        begin().it_,
16✔
143
        end().it_,
32✔
144
        detail::make_params_iter(
145
            first, last, opt_.space_as_plus));
16✔
146
}
16✔
147

148
template<class FwdIt>
149
auto
150
params_ref::
40✔
151
insert(
152
    iterator before,
153
    FwdIt first,
154
    FwdIt last,
155
    std::forward_iterator_tag) ->
156
        iterator
157
{
158
    return iterator(
159
        u_->edit_params(
80✔
160
            before.it_,
161
            before.it_,
162
            detail::make_params_iter(
163
                first, last, opt_.space_as_plus)),
40✔
164
        opt_);
80✔
165
}
166

167
//------------------------------------------------
168
//
169
// Special Members
170
//
171
//------------------------------------------------
172

173
inline
174
params_ref::
201✔
175
params_ref(
176
    url_base& u,
177
    encoding_opts opt) noexcept
201✔
178
    : params_base(u.impl_, opt)
201✔
179
    , u_(&u)
201✔
180
{
181
}
201✔
182

183
inline
184
params_ref::
2✔
185
params_ref(
186
    params_ref const& other,
187
    encoding_opts opt) noexcept
2✔
188
    : params_base(other.u_->impl_, opt)
2✔
189
    , u_(other.u_)
2✔
190
{
191
}
2✔
192

193
inline
194
auto
195
params_ref::
2✔
196
operator=(params_ref const& other) ->
197
    params_ref&
198
{
199
    if (!ref_.alias_of(other.ref_))
2✔
200
        assign(other.begin(), other.end());
2✔
201
    return *this;
2✔
202
}
203

204
inline
205
auto
206
params_ref::
2✔
207
operator=(std::initializer_list<
208
    param_view> init) ->
209
        params_ref&
210
{
211
    assign(init);
2✔
212
    return *this;
2✔
213
}
214

215
inline
216
params_ref::
126✔
217
operator
218
params_view() const noexcept
219
{
220
    return { ref_, opt_ };
126✔
221
}
222

223
//------------------------------------------------
224
//
225
// Modifiers
226
//
227
//------------------------------------------------
228

229
inline
230
void
231
params_ref::
6✔
232
clear() noexcept
233
{
234
    u_->remove_query();
6✔
235
}
6✔
236

237
inline
238
void
239
params_ref::
10✔
240
assign(
241
    std::initializer_list<
242
        param_view> init)
243
{
244
    assign(init.begin(), init.end());
10✔
245
}
10✔
246

247
inline
248
auto
249
params_ref::
32✔
250
insert(
251
    iterator before,
252
    param_view const& p) ->
253
        iterator
254
{
255
    return {
256
        u_->edit_params(
32✔
257
            before.it_,
258
            before.it_,
259
            detail::single_param_iter(p, opt_.space_as_plus)),
64✔
260
        opt_};
64✔
261
}
262

263
inline
264
auto
265
params_ref::
32✔
266
insert(
267
    iterator before,
268
    std::initializer_list<
269
        param_view> init) ->
270
    iterator
271
{
272
    return insert(
32✔
273
        before,
274
        init.begin(),
275
        init.end());
32✔
276
}
277

278
inline
279
auto
280
params_ref::
24✔
281
append(
282
    param_view const& p) ->
283
        iterator
284
{
285
    return insert(end(), p);
24✔
286
}
287

288
inline
289
auto
290
params_ref::
12✔
291
append(
292
    std::initializer_list<
293
        param_view> init) ->
294
    iterator
295
{
296
    return insert(end(), init);
12✔
297
}
298

299
inline
300
std::size_t
301
params_ref::
4✔
302
erase(
303
    core::string_view key,
304
    ignore_case_param ic) noexcept
305
{
306
    // end() can't be fully cached,
307
    // since erase invalidates it.
308
    iterator it;
4✔
309
    {
310
        auto const end_ = end();
4✔
311
        it = find_last(end_, key, ic);
4✔
312
        if(it == end_)
4✔
313
            return 0;
×
314
    }
315
    std::size_t n = 0;
4✔
316
    for(;;)
317
    {
318
        ++n;
10✔
319
        // Use it->key instead of key,
320
        // to handle self-intersection
321
        auto prev = find_last(it, (*it).key, ic);
10✔
322
        if(prev == end())
10✔
323
            break;
4✔
324
        erase(it);
6✔
325
        it = prev;
6✔
326
    }
6✔
327
    erase(it);
4✔
328
    return n;
4✔
329
}
330

331
inline
332
auto
333
params_ref::
16✔
334
replace(
335
    iterator pos,
336
    param_view const& p) ->
337
        iterator
338
{
339
    return iterator(
340
        u_->edit_params(
16✔
341
            pos.it_,
342
            std::next(pos).it_,
16✔
343
            detail::single_param_iter(p, opt_.space_as_plus)),
32✔
344
        opt_);
32✔
345
}
346

347
inline
348
auto
349
params_ref::
4✔
350
replace(
351
    iterator from,
352
    iterator to,
353
    std::initializer_list<
354
        param_view> init) ->
355
    iterator
356
{
357
    return replace(
4✔
358
        from,
359
        to,
360
        init.begin(),
361
        init.end());
4✔
362
}
363

364
inline
365
auto
366
params_ref::
8✔
367
unset(
368
    iterator pos) noexcept ->
369
        iterator
370
{
371
    BOOST_ASSERT(pos.it_.nk > 0);
8✔
372
    core::string_view s;
8✔
373
    return iterator(
374
        u_->edit_params(
8✔
375
            pos.it_,
376
            pos.it_.next(),
8✔
377
            detail::param_value_iter(
8✔
378
                pos.it_.nk - 1, s, false)),
8✔
379
        opt_);
8✔
380
}
381

382
inline
383
auto
384
params_ref::
10✔
385
set(
386
    iterator pos,
387
    core::string_view value) ->
388
        iterator
389
{
390
    BOOST_ASSERT(pos.it_.nk > 0);
10✔
391
    return iterator(
392
        u_->edit_params(
10✔
393
            pos.it_,
394
            pos.it_.next(),
10✔
395
            detail::param_value_iter(
10✔
396
                pos.it_.nk - 1, value, true)),
10✔
397
        opt_);
20✔
398
}
399

400
inline
401
auto
402
params_ref::
2✔
403
set(
404
    core::string_view key,
405
    core::string_view value,
406
    ignore_case_param ic) ->
407
        iterator
408
{
409
    // VFALCO we can't cache end() here
410
    // because it is invalidated
411
    // every time we set or erase.
412
    auto it0 = find(key, ic);
2✔
413
    if(it0 == end())
2✔
414
        return append({key, value});
×
415
    it0 = set(it0, value);
2✔
416
    auto it = end();
2✔
417
    for(;;)
418
    {
419
        it = find_last(it, key, ic);
4✔
420
        if(it == it0)
4✔
421
            return it0;
2✔
422
        it = erase(it);
2✔
423
    }
424
}
425

426
inline
427
auto
428
params_ref::
18✔
429
erase(
430
    iterator pos) noexcept ->
431
    iterator
432
{
433
    return erase(
18✔
434
        pos,
435
        std::next(pos));
18✔
436
}
437

438
inline
439
auto
440
params_ref::
22✔
441
erase(
442
    iterator first,
443
    iterator last) noexcept ->
444
        iterator
445
{
446
    core::string_view s("", 0);
22✔
447
    return iterator(
448
        u_->edit_params(
22✔
449
            first.it_,
450
            last.it_,
451
            detail::query_string_iter(s)),
44✔
452
        opt_);
22✔
453
}
454

455
} // urls
456
} // boost
457

458
#endif
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc