Coverage Report

Created: 2026-05-30 09:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/common/url.cpp
Line
Count
Source
1
// Copyright (c) 2015-present The Bitcoin Core developers
2
// Distributed under the MIT software license, see the accompanying
3
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5
#include <common/url.h>
6
7
#include <charconv>
8
#include <string>
9
#include <string_view>
10
#include <system_error>
11
12
std::string UrlDecode(std::string_view url_encoded)
13
14.8k
{
14
14.8k
    std::string res;
15
14.8k
    res.reserve(url_encoded.size());
16
17
216k
    for (size_t i = 0; i < url_encoded.size(); ++i) {
18
201k
        char c = url_encoded[i];
19
        // Special handling for percent which should be followed by two hex digits
20
        // representing an octet values, see RFC 3986, Section 2.1 Percent-Encoding
21
201k
        if (c == '%' && i + 2 < url_encoded.size()) {
22
410
            unsigned int decoded_value{0};
23
410
            auto [p, ec] = std::from_chars(url_encoded.data() + i + 1, url_encoded.data() + i + 3, decoded_value, 16);
24
25
            // Only if there is no error and the pointer is set to the end of
26
            // the string, we can be sure both characters were valid hex
27
410
            if (ec == std::errc{} && p == url_encoded.data() + i + 3) {
28
391
                res += static_cast<char>(decoded_value);
29
                // Next two characters are part of the percent encoding
30
391
                i += 2;
31
391
                continue;
32
391
            }
33
            // In case of invalid percent encoding, add the '%' and continue
34
410
        }
35
200k
        res += c;
36
200k
    }
37
38
14.8k
    return res;
39
14.8k
}
40
41
std::string UrlEncode(std::string_view str)
42
168
{
43
168
    std::string res;
44
168
    res.reserve(str.size() * 3); // worst case: every char needs encoding
45
46
1.62k
    for (char ch : str) {
47
1.62k
        auto c = static_cast<unsigned char>(ch);
48
        // Unreserved characters per RFC 3986, Section 2.3
49
1.62k
        if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
50
1.62k
            (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.' || c == '~') {
51
1.32k
            res += ch;
52
1.32k
        } else {
53
            // Percent-encode all other characters
54
295
            res += '%';
55
295
            constexpr char hex_chars[] = "0123456789ABCDEF";
56
295
            res += hex_chars[(c >> 4) & 0xF];
57
295
            res += hex_chars[c & 0xF];
58
295
        }
59
1.62k
    }
60
168
    return res;
61
168
}