Coverage Report

Created: 2026-08-14 20:23

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
275k
    : m_str{str}, m_max_line_length{max_line_length}, m_it{str.begin()} {}
22
23
std::optional<std::string_view> LineReader::ReadLine()
24
2.19M
{
25
2.19M
    if (m_it == m_str.end()) {
26
237
        return std::nullopt;
27
237
    }
28
29
2.19M
    const auto line_start = m_it;
30
77.9M
    while (m_it != m_str.end()) {
31
        // Read a character from the incoming buffer and increment the iterator
32
77.9M
        const bool new_line{*m_it == '\n'};
33
77.9M
        ++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
77.9M
        if (new_line) {
37
2.19M
            std::string_view line{line_start, m_it - 1};
38
2.19M
            if (!line.empty() && line.back() == '\r')
39
2.19M
                line.remove_suffix(1);
40
2.19M
            return line;
41
2.19M
        }
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
75.7M
        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
75.7M
    }
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
2.19M
}
57
58
// Ignores max_line_length but won't overflow
59
std::string_view LineReader::ReadLength(size_t len)
60
187k
{
61
187k
    if (len == 0) return {};
62
187k
    if (Remaining() < len) throw std::runtime_error("Not enough data in buffer");
63
187k
    std::string_view out(std::to_address(m_it), len);
64
187k
    m_it += len;
65
187k
    return out;
66
187k
}
67
68
size_t LineReader::Remaining() const
69
463k
{
70
463k
    return std::distance(m_it, m_str.end());
71
463k
}
72
73
size_t LineReader::Consumed() const
74
2.10M
{
75
2.10M
    return std::distance(m_str.begin(), m_it);
76
2.10M
}
77
} // namespace util