Coverage Report

Created: 2026-07-29 23:27

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/tmp/bitcoin/src/util/string.cpp
Line
Count
Source
1
// Copyright (c) 2019-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 <util/string.h>
6
7
#include <iterator>
8
#include <memory>
9
#include <regex>
10
#include <stdexcept>
11
#include <string>
12
13
namespace util {
14
void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute)
15
255
{
16
255
    if (search.empty()) return;
17
253
    in_out = std::regex_replace(in_out, std::regex(search), substitute);
18
253
}
19
20
LineReader::LineReader(std::string_view str, size_t max_line_length)
21
231k
    : m_str{str}, m_max_line_length{max_line_length}, m_it{str.begin()} {}
22
23
std::optional<std::string_view> LineReader::ReadLine()
24
1.84M
{
25
1.84M
    if (m_it == m_str.end()) {
26
241
        return std::nullopt;
27
241
    }
28
29
1.84M
    const auto line_start = m_it;
30
65.8M
    while (m_it != m_str.end()) {
31
        // Read a character from the incoming buffer and increment the iterator
32
65.8M
        const bool new_line{*m_it == '\n'};
33
65.8M
        ++m_it;
34
        // If the character we just consumed was \n, the line is terminated.
35
        // The \n itself does not count against max_line_length.
36
65.8M
        if (new_line) {
37
1.84M
            std::string_view line{line_start, m_it - 1};
38
1.84M
            if (!line.empty() && line.back() == '\r')
39
1.84M
                line.remove_suffix(1);
40
1.84M
            return line;
41
1.84M
        }
42
        // If the character we just consumed gives us a line length greater
43
        // than max_line_length, and we are not at the end of the line (or buffer) yet,
44
        // that means the line we are currently reading is too long, and we throw.
45
63.9M
        if (static_cast<size_t>(std::distance(line_start, m_it)) > m_max_line_length) {
46
            // Reset iterator
47
6
            m_it = line_start;
48
6
            throw std::runtime_error("max_line_length exceeded by LineReader");
49
6
        }
50
63.9M
    }
51
    // End of buffer reached without finding a \n or exceeding max_line_length.
52
    // Reset the iterator so the rest of the buffer can be read granularly
53
    // with ReadLength() and return null to indicate a line was not found.
54
51
    m_it = line_start;
55
51
    return std::nullopt;
56
1.84M
}
57
58
// Ignores max_line_length but won't overflow
59
std::string_view LineReader::ReadLength(size_t len)
60
186k
{
61
186k
    if (len == 0) return {};
62
186k
    if (Remaining() < len) throw std::runtime_error("Not enough data in buffer");
63
186k
    std::string_view out(std::to_address(m_it), len);
64
186k
    m_it += len;
65
186k
    return out;
66
186k
}
67
68
size_t LineReader::Remaining() const
69
419k
{
70
419k
    return std::distance(m_it, m_str.end());
71
419k
}
72
73
size_t LineReader::Consumed() const
74
1.79M
{
75
1.79M
    return std::distance(m_str.begin(), m_it);
76
1.79M
}
77
} // namespace util