/root/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 | 0 | { |
16 | 0 | if (search.empty()) return; Branch (16:9): [True: 0, False: 0]
|
17 | 0 | in_out = std::regex_replace(in_out, std::regex(search), substitute); |
18 | 0 | } |
19 | | |
20 | | LineReader::LineReader(std::string_view str, size_t max_line_length) |
21 | 0 | : m_str{str}, m_max_line_length{max_line_length}, m_it{str.begin()} {} |
22 | | |
23 | | std::optional<std::string_view> LineReader::ReadLine() |
24 | 0 | { |
25 | 0 | if (m_it == m_str.end()) { Branch (25:9): [True: 0, False: 0]
|
26 | 0 | return std::nullopt; |
27 | 0 | } |
28 | | |
29 | 0 | const auto line_start = m_it; |
30 | 0 | while (m_it != m_str.end()) { Branch (30:12): [True: 0, False: 0]
|
31 | | // Read a character from the incoming buffer and increment the iterator |
32 | 0 | const bool new_line{*m_it == '\n'}; |
33 | 0 | ++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 | 0 | if (new_line) { Branch (36:13): [True: 0, False: 0]
|
37 | 0 | std::string_view line{line_start, m_it - 1}; |
38 | 0 | if (!line.empty() && line.back() == '\r') Branch (38:17): [True: 0, False: 0]
Branch (38:34): [True: 0, False: 0]
|
39 | 0 | line.remove_suffix(1); |
40 | 0 | return line; |
41 | 0 | } |
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 | 0 | if (static_cast<size_t>(std::distance(line_start, m_it)) > m_max_line_length) { Branch (45:13): [True: 0, False: 0]
|
46 | | // Reset iterator |
47 | 0 | m_it = line_start; |
48 | 0 | throw std::runtime_error("max_line_length exceeded by LineReader"); |
49 | 0 | } |
50 | 0 | } |
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 | 0 | m_it = line_start; |
55 | 0 | return std::nullopt; |
56 | 0 | } |
57 | | |
58 | | // Ignores max_line_length but won't overflow |
59 | | std::string_view LineReader::ReadLength(size_t len) |
60 | 0 | { |
61 | 0 | if (len == 0) return {}; Branch (61:9): [True: 0, False: 0]
|
62 | 0 | if (Remaining() < len) throw std::runtime_error("Not enough data in buffer"); Branch (62:9): [True: 0, False: 0]
|
63 | 0 | std::string_view out(std::to_address(m_it), len); |
64 | 0 | m_it += len; |
65 | 0 | return out; |
66 | 0 | } |
67 | | |
68 | | size_t LineReader::Remaining() const |
69 | 0 | { |
70 | 0 | return std::distance(m_it, m_str.end()); |
71 | 0 | } |
72 | | |
73 | | size_t LineReader::Consumed() const |
74 | 0 | { |
75 | 0 | return std::distance(m_str.begin(), m_it); |
76 | 0 | } |
77 | | } // namespace util |