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