#include <util/string.h>
#include <iterator>
#include <memory>
#include <regex>
#include <stdexcept>
#include <string>
namespace util {
void ReplaceAll(std::string& in_out, const std::string& search, const std::string& substitute)
{
if (search.empty()) return;
in_out = std::regex_replace(in_out, std::regex(search), substitute);
}
LineReader::LineReader(std::span<const std::byte> buffer, size_t max_line_length)
: start(buffer.begin()), end(buffer.end()), max_line_length(max_line_length), it(buffer.begin()) {}
std::optional<std::string> LineReader::ReadLine()
{
if (it == end) {
return std::nullopt;
}
auto line_start = it;
size_t count = 0;
while (it != end) {
auto c = static_cast<char>(*it);
++it;
++count;
if (c == '\n') {
const std::string_view untrimmed_line(reinterpret_cast<const char*>(std::to_address(line_start)), count);
const std::string_view line = TrimStringView(untrimmed_line); return std::string(line);
}
if (count > max_line_length) {
it = line_start;
throw std::runtime_error("max_line_length exceeded by LineReader");
}
}
it = line_start;
return std::nullopt;
}
std::string LineReader::ReadLength(size_t len)
{
if (len == 0) return "";
if (Remaining() < len) throw std::runtime_error("Not enough data in buffer");
std::string out(reinterpret_cast<const char*>(std::to_address(it)), len);
it += len;
return out;
}
size_t LineReader::Remaining() const
{
return std::distance(it, end);
}
size_t LineReader::Consumed() const
{
return std::distance(start, it);
}
}