/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 <regex> |
8 | | #include <string> |
9 | | |
10 | | namespace util { |
11 | | void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute) |
12 | 0 | { |
13 | 0 | if (search.empty()) return; |
14 | 0 | in_out = std::regex_replace(in_out, std::regex(search), substitute); |
15 | 0 | } |
16 | | |
17 | | LineReader::LineReader(std::span<const std::byte> buffer, size_t max_line_length) |
18 | 24.9k | : start(buffer.begin()), end(buffer.end()), max_line_length(max_line_length), it(buffer.begin()) {} |
19 | | |
20 | | std::optional<std::string> LineReader::ReadLine() |
21 | 1.45M | { |
22 | 1.45M | if (it == end) { |
23 | 1.75k | return std::nullopt; |
24 | 1.75k | } |
25 | | |
26 | 1.45M | auto line_start = it; |
27 | 1.45M | size_t count = 0; |
28 | 20.8M | while (it != end) { |
29 | | // Read a character from the incoming buffer and increment the iterator |
30 | 20.8M | auto c = static_cast<char>(*it); |
31 | 20.8M | ++it; |
32 | 20.8M | ++count; |
33 | | // If the character we just consumed was \n, the line is terminated. |
34 | | // The \n itself does not count against max_line_length. |
35 | 20.8M | if (c == '\n') { |
36 | 1.44M | const std::string_view untrimmed_line(reinterpret_cast<const char*>(std::to_address(line_start)), count); |
37 | 1.44M | const std::string_view line = TrimStringView(untrimmed_line); // delete leading and trailing whitespace including \r and \n |
38 | 1.44M | return std::string(line); |
39 | 1.44M | } |
40 | | // If the character we just consumed gives us a line length greater |
41 | | // than max_line_length, and we are not at the end of the line (or buffer) yet, |
42 | | // that means the line we are currently reading is too long, and we throw. |
43 | 19.4M | if (count > max_line_length) { |
44 | | // Reset iterator |
45 | 0 | it = line_start; |
46 | 0 | throw std::runtime_error("max_line_length exceeded by LineReader"); |
47 | 0 | } |
48 | 19.4M | } |
49 | | // End of buffer reached without finding a \n or exceeding max_line_length. |
50 | | // Reset the iterator so the rest of the buffer can be read granularly |
51 | | // with ReadLength() and return null to indicate a line was not found. |
52 | 6.31k | it = line_start; |
53 | 6.31k | return std::nullopt; |
54 | 1.45M | } |
55 | | |
56 | | // Ignores max_line_length but won't overflow |
57 | | std::string LineReader::ReadLength(size_t len) |
58 | 0 | { |
59 | 0 | if (len == 0) return ""; |
60 | 0 | if (Remaining() < len) throw std::runtime_error("Not enough data in buffer"); |
61 | 0 | std::string out(reinterpret_cast<const char*>(std::to_address(it)), len); |
62 | 0 | it += len; |
63 | 0 | return out; |
64 | 0 | } |
65 | | |
66 | | size_t LineReader::Remaining() const |
67 | 0 | { |
68 | 0 | return std::distance(it, end); |
69 | 0 | } |
70 | | |
71 | | size_t LineReader::Consumed() const |
72 | 1.42M | { |
73 | 1.42M | return std::distance(start, it); |
74 | 1.42M | } |
75 | | } // namespace util |