218 lines
5.4 KiB
C++
218 lines
5.4 KiB
C++
/*
|
|
* Copyright 2015 - 2022 gary@drinkingtea.net
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "bit.hpp"
|
|
#include "cstrops.hpp"
|
|
#include "iterator.hpp"
|
|
|
|
namespace ox::detail {
|
|
|
|
class BaseStringView {
|
|
public:
|
|
template<typename RefType = char&, typename PtrType = char*, bool reverse = false>
|
|
struct iterator: public Iterator<std::bidirectional_iterator_tag, char> {
|
|
private:
|
|
PtrType m_t = nullptr;
|
|
std::size_t m_offset = 0;
|
|
std::size_t m_max = 0;
|
|
|
|
public:
|
|
constexpr iterator() noexcept = default;
|
|
|
|
constexpr iterator(PtrType t, std::size_t offset, std::size_t max) noexcept {
|
|
m_t = t;
|
|
m_offset = offset;
|
|
m_max = max;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto offset() const noexcept {
|
|
return m_offset;
|
|
}
|
|
|
|
constexpr iterator operator+(std::size_t s) const noexcept {
|
|
if constexpr(reverse) {
|
|
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
|
} else {
|
|
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
|
}
|
|
}
|
|
|
|
constexpr auto operator-(const iterator &other) const noexcept {
|
|
if constexpr(reverse) {
|
|
return m_offset + other.m_offset;
|
|
} else {
|
|
return m_offset - other.m_offset;
|
|
}
|
|
}
|
|
|
|
constexpr iterator operator-(std::size_t s) const noexcept {
|
|
if constexpr(reverse) {
|
|
return iterator(m_t, min<std::size_t>(m_offset + s, m_max), m_max);
|
|
} else {
|
|
return iterator(m_t, max<std::size_t>(m_offset - s, 0), m_max);
|
|
}
|
|
}
|
|
|
|
constexpr iterator &operator+=(std::size_t s) noexcept {
|
|
if constexpr(reverse) {
|
|
m_offset = max<std::size_t>(m_offset - s, 0);
|
|
} else {
|
|
m_offset = min(m_offset + s, m_max);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
constexpr iterator &operator-=(std::size_t s) noexcept {
|
|
if constexpr(reverse) {
|
|
m_offset = min(m_offset + s, m_max);
|
|
} else {
|
|
m_offset = max<std::size_t>(m_offset - s, 0);
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
constexpr iterator &operator++() noexcept {
|
|
return operator+=(1);
|
|
}
|
|
|
|
constexpr iterator &operator--() noexcept {
|
|
return operator-=(1);
|
|
}
|
|
|
|
constexpr RefType operator*() const noexcept {
|
|
return m_t[m_offset];
|
|
}
|
|
|
|
constexpr RefType operator[](std::size_t s) const noexcept {
|
|
return m_t[s];
|
|
}
|
|
|
|
constexpr bool operator<(const iterator &other) const noexcept {
|
|
return m_offset < other.m_offset;
|
|
}
|
|
|
|
constexpr bool operator>(const iterator &other) const noexcept {
|
|
return m_offset > other.m_offset;
|
|
}
|
|
|
|
constexpr bool operator<=(const iterator &other) const noexcept {
|
|
return m_offset <= other.m_offset;
|
|
}
|
|
|
|
constexpr bool operator>=(const iterator &other) const noexcept {
|
|
return m_offset >= other.m_offset;
|
|
}
|
|
|
|
constexpr bool operator==(const iterator &other) const noexcept {
|
|
return m_t == other.m_t && m_offset == other.m_offset && m_max == other.m_max;
|
|
}
|
|
|
|
constexpr bool operator!=(const iterator &other) const noexcept {
|
|
return m_t != other.m_t || m_offset != other.m_offset || m_max != other.m_max;
|
|
}
|
|
|
|
};
|
|
|
|
private:
|
|
const char *m_str = nullptr;
|
|
std::size_t m_len = 0;
|
|
protected:
|
|
constexpr BaseStringView() noexcept = default;
|
|
|
|
constexpr BaseStringView(BaseStringView const&sv) noexcept = default;
|
|
|
|
constexpr explicit BaseStringView(std::nullptr_t) noexcept {}
|
|
|
|
constexpr explicit BaseStringView(const char *str) noexcept: m_str(str), m_len(str ? ox_strlen(str) : 0) {}
|
|
|
|
constexpr explicit BaseStringView(const char *str, std::size_t len) noexcept: m_str(str), m_len(len) {}
|
|
|
|
public:
|
|
[[nodiscard]]
|
|
constexpr iterator<const char&, const char*> begin() const noexcept {
|
|
return {m_str, 0, m_len};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr iterator<const char&, const char*> end() const noexcept {
|
|
return {m_str, m_len, m_len};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr iterator<const char&, const char*> cbegin() const noexcept {
|
|
return {m_str, 0, m_len};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr iterator<const char&, const char*> cend() const noexcept {
|
|
return {m_str, m_len, m_len};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr iterator<const char&, const char*, true> crbegin() const noexcept {
|
|
return {m_str, m_len - 1, m_len};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr iterator<const char&, const char*, true> crend() const noexcept {
|
|
return {m_str, MaxValue<std::size_t>, m_len};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr iterator<const char&, const char*, true> rbegin() const noexcept {
|
|
return {m_str, m_len - 1, m_len};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr iterator<const char&, const char*, true> rend() const noexcept {
|
|
return {m_str, MaxValue<std::size_t>, m_len};
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto bytes() const noexcept {
|
|
return m_len;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto len() const noexcept {
|
|
return m_len;
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto *data() const noexcept {
|
|
return &m_str[0];
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto &front() const noexcept {
|
|
return m_str[0];
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto &back() const noexcept {
|
|
return m_str[m_len - 1];
|
|
}
|
|
|
|
[[nodiscard]]
|
|
constexpr auto operator[](std::size_t i) const noexcept {
|
|
return m_str[i];
|
|
}
|
|
|
|
protected:
|
|
constexpr void set(const char *str, std::size_t len) noexcept {
|
|
m_str = str;
|
|
m_len = len;
|
|
}
|
|
|
|
};
|
|
|
|
}
|