fixes
This commit is contained in:
259
include/util/string_list.hpp
Normal file
259
include/util/string_list.hpp
Normal file
@@ -0,0 +1,259 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
#include <span>
|
||||
#include <cinttypes>
|
||||
|
||||
namespace ztu
|
||||
{
|
||||
|
||||
class string_list_iterator
|
||||
{
|
||||
public:
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using value_type = std::string_view;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using pointer = const value_type*;
|
||||
using reference = const value_type&;
|
||||
|
||||
string_list_iterator(
|
||||
std::string_view buffer,
|
||||
std::span<const std::uint32_t> lengths,
|
||||
std::size_t index,
|
||||
std::size_t char_offset)
|
||||
: m_buffer{ buffer }, m_lengths{ lengths }, m_index{ index }, m_char_offset{ char_offset } {}
|
||||
|
||||
value_type operator*() const
|
||||
{
|
||||
return m_buffer.substr(m_char_offset, m_lengths[m_index]);
|
||||
}
|
||||
|
||||
string_list_iterator& operator++()
|
||||
{
|
||||
++m_index;
|
||||
m_char_offset += m_lengths[m_index];
|
||||
return *this;
|
||||
}
|
||||
|
||||
string_list_iterator operator++(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
++(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
string_list_iterator& operator--()
|
||||
{
|
||||
--m_index;
|
||||
m_char_offset -= m_lengths[m_index];
|
||||
return *this;
|
||||
}
|
||||
|
||||
string_list_iterator operator--(int)
|
||||
{
|
||||
auto tmp = *this;
|
||||
--(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
string_list_iterator& operator+=(difference_type n)
|
||||
{
|
||||
const auto negative = n < difference_type{ 0 };
|
||||
const auto positive = n > difference_type{ 0 };
|
||||
const auto step = difference_type{ positive } - difference_type{ negative };
|
||||
n = negative ? -n : n;
|
||||
|
||||
while (n--)
|
||||
{
|
||||
m_char_offset += step * m_lengths[m_index];
|
||||
m_index += step;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
string_list_iterator& operator-=(const difference_type n)
|
||||
{
|
||||
return *this += -n;
|
||||
}
|
||||
|
||||
string_list_iterator operator+(const difference_type n) const
|
||||
{
|
||||
auto tmp = *this;
|
||||
return tmp += n;
|
||||
}
|
||||
|
||||
string_list_iterator operator-(const difference_type n) const
|
||||
{
|
||||
auto tmp = *this;
|
||||
return tmp -= n;
|
||||
}
|
||||
|
||||
difference_type operator-(const string_list_iterator& other) const
|
||||
{
|
||||
return static_cast<difference_type>(m_index) - static_cast<difference_type>(other.m_index);
|
||||
}
|
||||
|
||||
value_type operator[](const difference_type n) const
|
||||
{
|
||||
auto tmp = *this;
|
||||
tmp += n;
|
||||
return *tmp;
|
||||
}
|
||||
|
||||
bool operator==(const string_list_iterator& other) const {
|
||||
return m_index == other.m_index && m_char_offset == other.m_char_offset;
|
||||
}
|
||||
|
||||
bool operator!=(const string_list_iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool operator<(const string_list_iterator& other) const {
|
||||
return m_index < other.m_index;
|
||||
}
|
||||
|
||||
bool operator<=(const string_list_iterator& other) const {
|
||||
return m_index <= other.m_index;
|
||||
}
|
||||
|
||||
bool operator>(const string_list_iterator& other) const {
|
||||
return m_index > other.m_index;
|
||||
}
|
||||
|
||||
bool operator>=(const string_list_iterator& other) const {
|
||||
return m_index >= other.m_index;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string_view m_buffer;
|
||||
std::span<const std::uint32_t> m_lengths;
|
||||
std::size_t m_index;
|
||||
std::size_t m_char_offset;
|
||||
};
|
||||
|
||||
class string_list
|
||||
{
|
||||
using index_type = std::uint32_t;
|
||||
using iterator = string_list_iterator;
|
||||
|
||||
public:
|
||||
string_list() = default;
|
||||
|
||||
string_list(std::initializer_list<std::string_view> init)
|
||||
{
|
||||
for (const auto& str : init) {
|
||||
push_back(str);
|
||||
}
|
||||
}
|
||||
|
||||
void reserve(const std::size_t characters, const std::size_t lengths)
|
||||
{
|
||||
m_buffer.reserve(characters);
|
||||
m_lengths.reserve(lengths);
|
||||
}
|
||||
|
||||
std::size_t character_count() const
|
||||
{
|
||||
return m_buffer.size();
|
||||
}
|
||||
|
||||
void push_back(const std::string_view& str)
|
||||
{
|
||||
m_buffer.reserve(m_buffer.size() + str.length() + 1);
|
||||
m_buffer.insert(m_buffer.end(), str.begin(), str.end());
|
||||
m_buffer.push_back('\0');
|
||||
m_lengths.push_back(static_cast<index_type>(str.size()));
|
||||
}
|
||||
|
||||
void push_back(const string_list& list)
|
||||
{
|
||||
m_buffer.insert(m_buffer.end(), list.m_buffer.begin(), list.m_buffer.end());
|
||||
m_lengths.insert(m_lengths.end(), list.m_lengths.begin(), list.m_lengths.end());
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
{
|
||||
m_buffer.resize(m_buffer.size() - m_lengths.back());
|
||||
m_lengths.pop_back();
|
||||
}
|
||||
|
||||
[[nodiscard]] std::string_view operator[](index_type index) const
|
||||
{
|
||||
auto offset = std::size_t{};
|
||||
for (index_type i{}; i != index; ++i)
|
||||
{
|
||||
offset += m_lengths[i];
|
||||
}
|
||||
|
||||
return { &m_buffer[offset], m_lengths[index] };
|
||||
}
|
||||
|
||||
[[nodiscard]] index_type size() const
|
||||
{
|
||||
return m_lengths.size();
|
||||
}
|
||||
|
||||
[[nodiscard]] bool empty() const
|
||||
{
|
||||
return m_lengths.empty();
|
||||
}
|
||||
|
||||
void clear()
|
||||
{
|
||||
m_buffer.clear();
|
||||
m_lengths.clear();
|
||||
}
|
||||
|
||||
void reserve(index_type new_cap)
|
||||
{
|
||||
m_buffer.reserve(new_cap);
|
||||
m_lengths.reserve(new_cap);
|
||||
}
|
||||
|
||||
[[nodiscard]] index_type capacity() const
|
||||
{
|
||||
return m_buffer.capacity();
|
||||
}
|
||||
|
||||
[[nodiscard]] iterator begin() const
|
||||
{
|
||||
return iterator{
|
||||
std::string_view{ m_buffer.data(), m_buffer.size() },
|
||||
m_lengths,
|
||||
0, 0
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] iterator end() const
|
||||
{
|
||||
return iterator{
|
||||
std::string_view{ m_buffer.data(), m_buffer.size() },
|
||||
m_lengths,
|
||||
m_lengths.size(),
|
||||
m_buffer.size()
|
||||
};
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<char>& buffer() const
|
||||
{
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
[[nodiscard]] const std::vector<index_type>& string_lengths() const
|
||||
{
|
||||
return m_lengths;
|
||||
}
|
||||
|
||||
void swap(string_list& other) noexcept
|
||||
{
|
||||
m_buffer.swap(other.m_buffer);
|
||||
m_lengths.swap(other.m_lengths);
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char> m_buffer{};
|
||||
std::vector<index_type> m_lengths{};
|
||||
};
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user