[nostalgia/studio] Add ClawViewer for unknown types
This commit is contained in:
2
deps/ox/CMakeLists.txt
vendored
2
deps/ox/CMakeLists.txt
vendored
@ -56,7 +56,7 @@ if(NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wformat=2")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wmissing-field-initializers")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnull-dereference")
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnull-dereference")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Woverloaded-virtual")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wpedantic")
|
||||
|
94
deps/ox/src/ox/model/modelvalue.hpp
vendored
94
deps/ox/src/ox/model/modelvalue.hpp
vendored
@ -13,6 +13,7 @@
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/utility.hpp>
|
||||
#include <ox/std/vector.hpp>
|
||||
|
||||
#include "def.hpp"
|
||||
@ -279,6 +280,11 @@ class ModelValueVector {
|
||||
return m_vec.begin();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto begin() const noexcept {
|
||||
return m_vec.cbegin();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto cbegin() const noexcept {
|
||||
return m_vec.cbegin();
|
||||
@ -299,6 +305,11 @@ class ModelValueVector {
|
||||
return m_vec.end();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto end() const noexcept {
|
||||
return m_vec.cend();
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
auto cend() const noexcept {
|
||||
return m_vec.cend();
|
||||
@ -321,18 +332,17 @@ consteval bool isVector(const ModelValueVector*) noexcept {
|
||||
}
|
||||
|
||||
class ModelObject {
|
||||
protected:
|
||||
public:
|
||||
struct Field {
|
||||
String name;
|
||||
ModelValue value;
|
||||
};
|
||||
protected:
|
||||
oxModelFriend(ModelObject);
|
||||
friend ModelValue;
|
||||
Vector<UniquePtr<Field>> m_fieldsOrder;
|
||||
HashMap<String, ModelValue*> m_fields;
|
||||
const DescriptorType *m_type = nullptr;
|
||||
String m_typeName;
|
||||
int m_typeVersion = 0;
|
||||
|
||||
public:
|
||||
constexpr ModelObject() noexcept = default;
|
||||
@ -343,16 +353,12 @@ class ModelObject {
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_type = other.m_type;
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
}
|
||||
|
||||
constexpr ModelObject(ModelObject &&other) noexcept {
|
||||
m_fields = std::move(other.m_fields);
|
||||
m_type = other.m_type;
|
||||
m_fieldsOrder = std::move(other.m_fieldsOrder);
|
||||
m_typeName = std::move(other.m_typeName);
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -424,8 +430,6 @@ class ModelObject {
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_type = other.m_type;
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -436,17 +440,35 @@ class ModelObject {
|
||||
m_type = other.m_type;
|
||||
m_fields = std::move(other.m_fields);
|
||||
m_fieldsOrder = std::move(other.m_fieldsOrder);
|
||||
m_typeName = std::move(other.m_typeName);
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const std::size_t &i) noexcept {
|
||||
return *m_fieldsOrder[i];
|
||||
template<typename T>
|
||||
constexpr auto set(const std::size_t &i, T &&val) noexcept {
|
||||
auto &f = *m_fieldsOrder[i];
|
||||
f = val;
|
||||
}
|
||||
|
||||
constexpr Result<const ModelValue*> get(const String &k) const noexcept {
|
||||
if (m_fields.contains(k)) {
|
||||
return *m_fields.at(k).value;
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error set(const String &k, T &&val) noexcept {
|
||||
oxRequire(t, m_fields.at(k));
|
||||
*t = ox::forward<T>(val);
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
return *m_fields[k];
|
||||
auto [v, err] = m_fields.at(k);
|
||||
if (err) [[unlikely]] {
|
||||
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
||||
}
|
||||
return **v;
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const std::size_t i) noexcept {
|
||||
@ -454,13 +476,13 @@ class ModelObject {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr StringView typeName() const noexcept {
|
||||
return m_typeName;
|
||||
constexpr CRString typeName() const noexcept {
|
||||
return m_type->typeName;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int typeVersion() const noexcept {
|
||||
return m_typeVersion;
|
||||
return m_type->typeVersion;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -473,8 +495,6 @@ class ModelObject {
|
||||
return OxError(1, "Cannot load a non-struct type to ModelObject");
|
||||
}
|
||||
m_type = type;
|
||||
m_typeName = type->typeName;
|
||||
m_typeVersion = type->typeVersion;
|
||||
for (const auto &f : type->fieldList) {
|
||||
auto field = make_unique<Field>();
|
||||
field->name = f.fieldName;
|
||||
@ -498,8 +518,7 @@ class ModelUnion {
|
||||
friend ModelValue;
|
||||
Vector<UniquePtr<Field>> m_fieldsOrder;
|
||||
HashMap<String, Field*> m_fields;
|
||||
String m_typeName;
|
||||
int m_typeVersion = 0;
|
||||
const DescriptorType *m_type = nullptr;
|
||||
int m_unionIdx = -1;
|
||||
|
||||
private:
|
||||
@ -512,16 +531,12 @@ class ModelUnion {
|
||||
m_fields[field->name] = field.get();
|
||||
++i;
|
||||
}
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
m_unionIdx = other.m_unionIdx;
|
||||
}
|
||||
|
||||
constexpr ModelUnion(ModelUnion &&other) noexcept {
|
||||
m_fieldsOrder = std::move(other.m_fieldsOrder);
|
||||
m_fields = std::move(other.m_fields);
|
||||
m_typeName = std::move(other.m_typeName);
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
m_unionIdx = other.m_unionIdx;
|
||||
}
|
||||
|
||||
@ -536,7 +551,11 @@ class ModelUnion {
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const String &k) noexcept {
|
||||
return m_fields[k]->value;
|
||||
const auto [v, err] = m_fields.at(k);
|
||||
if (err) [[unlikely]] {
|
||||
oxPanic(err, ox::sfmt("field {} does not exist in type {}", k, buildTypeId(*m_type)).c_str());
|
||||
}
|
||||
return (*v)->value;
|
||||
}
|
||||
|
||||
constexpr auto &operator[](const std::size_t i) noexcept {
|
||||
@ -558,13 +577,17 @@ class ModelUnion {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ModelValue &get(std::size_t i) noexcept {
|
||||
return m_fieldsOrder[i]->value;
|
||||
constexpr Result<const ModelValue*> get(std::size_t i) const noexcept {
|
||||
if (i < m_fieldsOrder.size()) {
|
||||
return &m_fieldsOrder[i]->value;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr ModelValue &get(const String &k) noexcept {
|
||||
return (*m_fields.at(k).value)->value;
|
||||
constexpr Result<const ModelValue*> get(const String &k) const noexcept {
|
||||
oxRequire(t, m_fields.at(k));
|
||||
return &(*t)->value;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -580,12 +603,12 @@ class ModelUnion {
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const String &typeName() const noexcept {
|
||||
return m_typeName;
|
||||
return m_type->typeName;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int typeVersion() const noexcept {
|
||||
return m_typeVersion;
|
||||
return m_type->typeVersion;
|
||||
}
|
||||
|
||||
constexpr Error setType(const DescriptorType *type) noexcept {
|
||||
@ -594,8 +617,7 @@ class ModelUnion {
|
||||
}
|
||||
m_fields.clear();
|
||||
m_fieldsOrder.clear();
|
||||
m_typeName = type->typeName;
|
||||
m_typeVersion = type->typeVersion;
|
||||
m_type = type;
|
||||
for (auto i = 0; const auto &f : type->fieldList) {
|
||||
auto field = make_unique<Field>();
|
||||
field->name = f.fieldName;
|
||||
@ -744,7 +766,7 @@ constexpr std::size_t alignOf(const ModelValue &t) noexcept {
|
||||
}
|
||||
|
||||
constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
|
||||
h->template setTypeInfo<ModelObject>(obj->m_typeName.c_str(), obj->m_typeVersion, {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
h->template setTypeInfo<ModelObject>(obj->typeName().c_str(), obj->typeVersion(), {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
oxReturnError(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
@ -752,7 +774,7 @@ constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
|
||||
}
|
||||
|
||||
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
|
||||
h->template setTypeInfo<ModelUnion>(obj->m_typeName.c_str(), obj->m_typeVersion, {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
h->template setTypeInfo<ModelUnion>(obj->typeName().c_str(), obj->typeVersion(), {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
oxReturnError(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
|
2
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
2
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
@ -25,7 +25,7 @@ struct TypeNameCatcher {
|
||||
constexpr TypeNameCatcher() noexcept = default;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *n = T::TypeName, const Vector<String>& = {}, int v = 0) noexcept {
|
||||
constexpr void setTypeInfo(const char *n = T::TypeName, int v = T::TypeVersion, const Vector<String>& = {}, int = 0) noexcept {
|
||||
this->name = n;
|
||||
this->version = v;
|
||||
}
|
||||
|
8
deps/ox/src/ox/model/typestore.hpp
vendored
8
deps/ox/src/ox/model/typestore.hpp
vendored
@ -29,7 +29,7 @@ class TypeStore {
|
||||
constexpr virtual ~TypeStore() noexcept = default;
|
||||
|
||||
constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion,
|
||||
const Vector<String> &typeParams) const noexcept {
|
||||
const TypeParamPack &typeParams) const noexcept {
|
||||
const auto typeId = buildTypeId(name, typeVersion, typeParams);
|
||||
oxRequire(out, m_cache.at(typeId));
|
||||
return out->get();
|
||||
@ -71,7 +71,7 @@ class TypeStore {
|
||||
}
|
||||
|
||||
constexpr Result<const DescriptorType*> getLoad(const auto &typeName, auto typeVersion,
|
||||
const Vector<String> &typeParams = {}) noexcept {
|
||||
const TypeParamPack &typeParams = {}) noexcept {
|
||||
return getLoad(buildTypeId(typeName, typeVersion, typeParams));
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@ class TypeStore {
|
||||
const auto &keys = m_cache.keys();
|
||||
ox::Vector<DescriptorType*> descs;
|
||||
for (const auto &k : keys) {
|
||||
descs.emplace_back(m_cache.at(k).value->get());
|
||||
descs.emplace_back(m_cache.at(k).unwrap()->get());
|
||||
}
|
||||
return descs;
|
||||
}
|
||||
@ -106,7 +106,7 @@ class TypeStore {
|
||||
}
|
||||
|
||||
Result<UniquePtr<DescriptorType>> loadDescriptor(ox::CRStringView name, int version,
|
||||
const Vector<String> &typeParams) noexcept {
|
||||
const ox::TypeParamPack &typeParams) noexcept {
|
||||
const auto typeId = buildTypeId(name, version, typeParams);
|
||||
return loadDescriptor(typeId);
|
||||
}
|
||||
|
38
deps/ox/src/ox/oc/test/tests.cpp
vendored
38
deps/ox/src/ox/oc/test/tests.cpp
vendored
@ -14,6 +14,14 @@
|
||||
#include <ox/oc/oc.hpp>
|
||||
#include <ox/std/std.hpp>
|
||||
|
||||
template<typename T>
|
||||
union U {
|
||||
T t;
|
||||
int i;
|
||||
};
|
||||
|
||||
U<short> u;
|
||||
|
||||
union TestUnion {
|
||||
static constexpr auto TypeName = "TestUnion";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
@ -204,26 +212,26 @@ const std::map<std::string_view, ox::Error(*)()> tests = {
|
||||
ox::ModelObject testOut;
|
||||
oxReturnError(testOut.setType(type.value));
|
||||
oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed");
|
||||
oxAssert(testOut["Int"].get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut["Bool"].get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut["String"].get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut["Struct"].get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut["Union"].get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut["List"].get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut["Struct"].get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut["Union"].get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut["List"].get<ox::ModelValueVector>();
|
||||
oxAssert(testOut.get("Int").unwrap()->get<int>() == testIn.Int, "testOut.Int failed");
|
||||
oxAssert(testOut.get("Bool").unwrap()->get<bool>() == testIn.Bool, "testOut.Bool failed");
|
||||
oxAssert(testOut.get("String").unwrap()->get<ox::String>() == testIn.String, "testOut.String failed");
|
||||
auto &testOutStruct = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto &testOutUnion = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto &testOutList = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
auto testOutStructCopy = testOut.get("Struct").unwrap()->get<ox::ModelObject>();
|
||||
auto testOutUnionCopy = testOut.get("Union").unwrap()->get<ox::ModelUnion>();
|
||||
auto testOutListCopy = testOut.get("List").unwrap()->get<ox::ModelValueVector>();
|
||||
oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed");
|
||||
oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed");
|
||||
oxAssert(testOutStruct["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct["String"].get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
|
||||
oxAssert(testOut["unionIdx"].get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutStruct.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool failed");
|
||||
oxAssert(testOutStruct.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String failed");
|
||||
oxAssert(testOut.get("unionIdx").unwrap()->get<int>() == testIn.unionIdx, "testOut.unionIdx failed");
|
||||
oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong");
|
||||
oxAssert(testOutUnion["Int"].get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutUnion.get("Int").unwrap()->get<uint32_t>() == testIn.Union.Int, "testOut.Union.Int failed");
|
||||
oxAssert(testOutList[0].get<uint32_t>() == testIn.List[0], "testOut.List[0] failed");
|
||||
oxAssert(testOutList[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] failed");
|
||||
oxAssert(testOutStructCopy["Bool"].get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy["String"].get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
|
||||
oxAssert(testOutStructCopy.get("Bool").unwrap()->get<bool>() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed");
|
||||
oxAssert(testOutStructCopy.get("String").unwrap()->get<ox::String>() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed");
|
||||
oxAssert(testOutListCopy[0].get<uint32_t>() == testIn.List[0], "testOut.Struct.List[0] (copy) failed");
|
||||
oxAssert(testOutListCopy[1].get<uint32_t>() == testIn.List[1], "testOut.Struct.List[1] (copy) failed");
|
||||
return OxError(0);
|
||||
|
4
deps/ox/src/ox/std/memops.hpp
vendored
4
deps/ox/src/ox/std/memops.hpp
vendored
@ -68,6 +68,10 @@ constexpr void *ox_memset(void *ptr, int val, std::size_t size) noexcept {
|
||||
|
||||
namespace ox {
|
||||
|
||||
constexpr void *memcpy(void *dest, const void *src, std::size_t size) noexcept {
|
||||
return ox_memcpy(dest, src, size);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void *memsetElements(T *ptr, T val, std::size_t elements) noexcept {
|
||||
return memset(ptr, val, elements * sizeof(T));
|
||||
|
3
deps/ox/src/ox/std/memory.hpp
vendored
3
deps/ox/src/ox/std/memory.hpp
vendored
@ -247,6 +247,9 @@ class UniquePtr {
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using UPtr = UniquePtr<T>;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool operator==(const UniquePtr<T> &p1, const UniquePtr<T> &p2) noexcept {
|
||||
return p1.get() == p2.get();
|
||||
|
151
deps/ox/src/ox/std/stringview.hpp
vendored
151
deps/ox/src/ox/std/stringview.hpp
vendored
@ -8,8 +8,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "iterator.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "types.hpp"
|
||||
#include "bit.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -20,6 +22,111 @@ template<std::size_t buffLen>
|
||||
class BasicString;
|
||||
|
||||
class StringView {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
@ -41,6 +148,46 @@ class StringView {
|
||||
|
||||
constexpr StringView(const char *str, std::size_t len) noexcept: m_str(str), m_len(len) {}
|
||||
|
||||
[[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;
|
||||
@ -66,6 +213,10 @@ class StringView {
|
||||
return m_str[m_len - 1];
|
||||
}
|
||||
|
||||
constexpr auto substr(std::size_t pos) const noexcept {
|
||||
return StringView(m_str + pos, m_len - pos);
|
||||
}
|
||||
|
||||
constexpr auto operator[](std::size_t i) const noexcept {
|
||||
return m_str[i];
|
||||
}
|
||||
|
Reference in New Issue
Block a user