Branch data Line data Source code
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 : 255 : void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute)
15 : : {
16 [ + + ]: 255 : if (search.empty()) return;
17 [ + - ]: 253 : in_out = std::regex_replace(in_out, std::regex(search), substitute);
18 : : }
19 : :
20 : 371741 : LineReader::LineReader(std::string_view str, size_t max_line_length)
21 : 371741 : : m_str{str}, m_max_line_length{max_line_length}, m_it{str.begin()} {}
22 : :
23 : 2967644 : std::optional<std::string_view> LineReader::ReadLine()
24 : : {
25 [ + + ]: 2967644 : if (m_it == m_str.end()) {
26 : 527 : return std::nullopt;
27 : : }
28 : :
29 : : const auto line_start = m_it;
30 [ + + ]: 104282078 : while (m_it != m_str.end()) {
31 : : // Read a character from the incoming buffer and increment the iterator
32 : 104282027 : const bool new_line{*m_it == '\n'};
33 : 104282027 : ++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 [ + + ]: 104282027 : if (new_line) {
37 [ + + ]: 2967060 : std::string_view line{line_start, m_it - 1};
38 [ + + + + ]: 2967060 : if (!line.empty() && line.back() == '\r')
39 : 2966164 : line.remove_suffix(1);
40 : 2967060 : return line;
41 : : }
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 [ + + ]: 101314967 : 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 : : }
50 : : }
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 : : }
57 : :
58 : : // Ignores max_line_length but won't overflow
59 : 221021 : std::string_view LineReader::ReadLength(size_t len)
60 : : {
61 [ + + ]: 221021 : if (len == 0) return {};
62 [ + + + - ]: 221007 : if (Remaining() < len) throw std::runtime_error("Not enough data in buffer");
63 : 221006 : std::string_view out(std::to_address(m_it), len);
64 : 221006 : m_it += len;
65 : 221006 : return out;
66 : : }
67 : :
68 : 593094 : size_t LineReader::Remaining() const
69 : : {
70 : 593094 : return std::distance(m_it, m_str.end());
71 : : }
72 : :
73 : 2807220 : size_t LineReader::Consumed() const
74 : : {
75 : 2807220 : return std::distance(m_str.begin(), m_it);
76 : : }
77 : : } // namespace util
|