Bitcoin Core 31.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 <regex>
10#include <stdexcept>
11#include <string>
12
13namespace util {
14void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute)
15{
16 if (search.empty()) return;
17 in_out = std::regex_replace(in_out, std::regex(search), substitute);
18}
19
20LineReader::LineReader(std::string_view str, size_t max_line_length)
21 : m_str{str}, m_max_line_length{max_line_length}, m_it{str.begin()} {}
22
23std::optional<std::string_view> LineReader::ReadLine()
24{
25 if (m_it == m_str.end()) {
26 return std::nullopt;
27 }
28
29 const auto line_start = m_it;
30 while (m_it != m_str.end()) {
31 // Read a character from the incoming buffer and increment the iterator
32 const bool new_line{*m_it == '\n'};
33 ++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 if (new_line) {
37 std::string_view line{line_start, m_it - 1};
38 if (!line.empty() && line.back() == '\r')
39 line.remove_suffix(1);
40 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 if (static_cast<size_t>(std::distance(line_start, m_it)) > m_max_line_length) {
46 // Reset iterator
47 m_it = line_start;
48 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 m_it = line_start;
55 return std::nullopt;
56}
57
58// Ignores max_line_length but won't overflow
59std::string_view LineReader::ReadLength(size_t len)
60{
61 if (len == 0) return {};
62 if (Remaining() < len) throw std::runtime_error("Not enough data in buffer");
63 std::string_view out(std::to_address(m_it), len);
64 m_it += len;
65 return out;
66}
67
69{
70 return std::distance(m_it, m_str.end());
71}
72
74{
75 return std::distance(m_str.begin(), m_it);
76}
77} // namespace util
const size_t m_max_line_length
Definition: string.h:271
size_t Consumed() const
Returns number of bytes already read from buffer.
Definition: string.cpp:73
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:23
size_t Remaining() const
Returns remaining size of bytes in buffer.
Definition: string.cpp:68
const std::string_view m_str
Definition: string.h:270
LineReader(std::string_view str, size_t max_line_length)
Definition: string.cpp:20
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:59
std::string_view::iterator m_it
Definition: string.h:272
void ReplaceAll(std::string &in_out, const std::string &search, const std::string &substitute)
Definition: string.cpp:14