Bitcoin Core 32.99.0
P2P Digital Currency
string.cpp
Go to the documentation of this file.
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 <stdexcept>
10#include <string>
11#include <string_view>
12
13namespace util {
14void ReplaceAll(std::string& in_out, std::string_view search, std::string_view substitute)
15{
16 if (search.empty()) return;
17 auto pos{in_out.find(search)};
18 if (pos == std::string::npos) return;
19
20 // Build separately because repeated std::string::replace() calls move the remaining suffix when sizes differ
21 std::string result;
22 result.reserve(in_out.size());
23 std::string::size_type start{0};
24 for (; pos != std::string::npos; pos = in_out.find(search, start)) {
25 result.append(in_out, start, pos - start).append(substitute);
26 start = pos + search.size();
27 }
28 result.append(in_out, start);
29 in_out.swap(result);
30}
31
32LineReader::LineReader(std::string_view str, size_t max_line_length)
33 : m_str{str}, m_max_line_length{max_line_length}, m_it{str.begin()} {}
34
35std::optional<std::string_view> LineReader::ReadLine()
36{
37 if (m_it == m_str.end()) {
38 return std::nullopt;
39 }
40
41 const auto line_start = m_it;
42 while (m_it != m_str.end()) {
43 // Read a character from the incoming buffer and increment the iterator
44 const bool new_line{*m_it == '\n'};
45 ++m_it;
46 // If the character we just consumed was \n, the line is terminated.
47 // The \n itself does not count against max_line_length.
48 if (new_line) {
49 std::string_view line{line_start, m_it - 1};
50 if (!line.empty() && line.back() == '\r')
51 line.remove_suffix(1);
52 return line;
53 }
54 // If the character we just consumed gives us a line length greater
55 // than max_line_length, and we are not at the end of the line (or buffer) yet,
56 // that means the line we are currently reading is too long, and we throw.
57 if (static_cast<size_t>(std::distance(line_start, m_it)) > m_max_line_length) {
58 // Reset iterator
59 m_it = line_start;
60 throw std::runtime_error("max_line_length exceeded by LineReader");
61 }
62 }
63 // End of buffer reached without finding a \n or exceeding max_line_length.
64 // Reset the iterator so the rest of the buffer can be read granularly
65 // with ReadLength() and return null to indicate a line was not found.
66 m_it = line_start;
67 return std::nullopt;
68}
69
70// Ignores max_line_length but won't overflow
71std::string_view LineReader::ReadLength(size_t len)
72{
73 if (len == 0) return {};
74 if (Remaining() < len) throw std::runtime_error("Not enough data in buffer");
75 std::string_view out(std::to_address(m_it), len);
76 m_it += len;
77 return out;
78}
79
81{
82 return std::distance(m_it, m_str.end());
83}
84
86{
87 return std::distance(m_str.begin(), m_it);
88}
89} // namespace util
const size_t m_max_line_length
Definition: string.h:272
size_t Consumed() const
Returns number of bytes already read from buffer.
Definition: string.cpp:85
std::optional< std::string_view > ReadLine() LIFETIMEBOUND
Returns a string from current iterator position up to (but not including) next and advances iterator...
Definition: string.cpp:35
size_t Remaining() const
Returns remaining size of bytes in buffer.
Definition: string.cpp:80
const std::string_view m_str
Definition: string.h:271
LineReader(std::string_view str LIFETIMEBOUND, size_t max_line_length)
Definition: string.cpp:32
std::string_view ReadLength(size_t len) LIFETIMEBOUND
Returns string from current iterator position of specified length if possible and advances iterator o...
Definition: string.cpp:71
std::string_view::iterator m_it
Definition: string.h:273
void ReplaceAll(std::string &in_out, std::string_view search, std::string_view substitute)
Replace every non-overlapping occurrence of search with substitute, treating both literally; the repl...
Definition: string.cpp:14