From 38c92c63955f3ff988fad758cd19525384d3368f Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Thu, 15 Dec 2022 01:36:55 -0600 Subject: [PATCH] [nostalgia/studio] Add ClawViewer for unknown types (synced from 44f45e64e949bc3ab2d1513352ca214cfbf8bcb4) --- CMakeLists.txt | 2 +- src/ox/model/modelvalue.hpp | 94 +++++++++++-------- src/ox/model/typenamecatcher.hpp | 2 +- src/ox/model/typestore.hpp | 8 +- src/ox/oc/test/tests.cpp | 38 +++++--- src/ox/std/memops.hpp | 4 + src/ox/std/memory.hpp | 3 + src/ox/std/stringview.hpp | 151 +++++++++++++++++++++++++++++++ 8 files changed, 245 insertions(+), 57 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a00e462a9..2d0a2ae29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/src/ox/model/modelvalue.hpp b/src/ox/model/modelvalue.hpp index 3b55cb557..3819ca6c2 100644 --- a/src/ox/model/modelvalue.hpp +++ b/src/ox/model/modelvalue.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #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> m_fieldsOrder; HashMap 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 + constexpr auto set(const std::size_t &i, T &&val) noexcept { + auto &f = *m_fieldsOrder[i]; + f = val; + } + + constexpr Result get(const String &k) const noexcept { + if (m_fields.contains(k)) { + return *m_fields.at(k).value; + } + return OxError(1); + } + + template + constexpr Error set(const String &k, T &&val) noexcept { + oxRequire(t, m_fields.at(k)); + *t = ox::forward(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->name = f.fieldName; @@ -498,8 +518,7 @@ class ModelUnion { friend ModelValue; Vector> m_fieldsOrder; HashMap 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 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 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->name = f.fieldName; @@ -744,7 +766,7 @@ constexpr std::size_t alignOf(const ModelValue &t) noexcept { } constexpr Error model(auto *h, CommonPtrWith auto *obj) noexcept { - h->template setTypeInfo(obj->m_typeName.c_str(), obj->m_typeVersion, {}, static_cast(obj->m_fieldsOrder.size())); + h->template setTypeInfo(obj->typeName().c_str(), obj->typeVersion(), {}, static_cast(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 auto *obj) noexcept { } constexpr Error model(auto *h, CommonPtrWith auto *obj) noexcept { - h->template setTypeInfo(obj->m_typeName.c_str(), obj->m_typeVersion, {}, static_cast(obj->m_fieldsOrder.size())); + h->template setTypeInfo(obj->typeName().c_str(), obj->typeVersion(), {}, static_cast(obj->m_fieldsOrder.size())); for (auto &f : obj->m_fieldsOrder) { oxReturnError(h->field(f->name.c_str(), &f->value)); } diff --git a/src/ox/model/typenamecatcher.hpp b/src/ox/model/typenamecatcher.hpp index 5c65dc8f4..553ad1ec3 100644 --- a/src/ox/model/typenamecatcher.hpp +++ b/src/ox/model/typenamecatcher.hpp @@ -25,7 +25,7 @@ struct TypeNameCatcher { constexpr TypeNameCatcher() noexcept = default; template - constexpr void setTypeInfo(const char *n = T::TypeName, const Vector& = {}, int v = 0) noexcept { + constexpr void setTypeInfo(const char *n = T::TypeName, int v = T::TypeVersion, const Vector& = {}, int = 0) noexcept { this->name = n; this->version = v; } diff --git a/src/ox/model/typestore.hpp b/src/ox/model/typestore.hpp index 899bea5b3..6bb404eba 100644 --- a/src/ox/model/typestore.hpp +++ b/src/ox/model/typestore.hpp @@ -29,7 +29,7 @@ class TypeStore { constexpr virtual ~TypeStore() noexcept = default; constexpr Result get(const auto &name, int typeVersion, - const Vector &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 getLoad(const auto &typeName, auto typeVersion, - const Vector &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 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> loadDescriptor(ox::CRStringView name, int version, - const Vector &typeParams) noexcept { + const ox::TypeParamPack &typeParams) noexcept { const auto typeId = buildTypeId(name, version, typeParams); return loadDescriptor(typeId); } diff --git a/src/ox/oc/test/tests.cpp b/src/ox/oc/test/tests.cpp index 4bd28b526..e4914b473 100644 --- a/src/ox/oc/test/tests.cpp +++ b/src/ox/oc/test/tests.cpp @@ -14,6 +14,14 @@ #include #include +template +union U { + T t; + int i; +}; + +U u; + union TestUnion { static constexpr auto TypeName = "TestUnion"; static constexpr auto TypeVersion = 1; @@ -204,26 +212,26 @@ const std::map tests = { ox::ModelObject testOut; oxReturnError(testOut.setType(type.value)); oxAssert(ox::readOC(dataBuff.data(), dataBuff.size(), &testOut), "Data read failed"); - oxAssert(testOut["Int"].get() == testIn.Int, "testOut.Int failed"); - oxAssert(testOut["Bool"].get() == testIn.Bool, "testOut.Bool failed"); - oxAssert(testOut["String"].get() == testIn.String, "testOut.String failed"); - auto &testOutStruct = testOut["Struct"].get(); - auto &testOutUnion = testOut["Union"].get(); - auto &testOutList = testOut["List"].get(); - auto testOutStructCopy = testOut["Struct"].get(); - auto testOutUnionCopy = testOut["Union"].get(); - auto testOutListCopy = testOut["List"].get(); + oxAssert(testOut.get("Int").unwrap()->get() == testIn.Int, "testOut.Int failed"); + oxAssert(testOut.get("Bool").unwrap()->get() == testIn.Bool, "testOut.Bool failed"); + oxAssert(testOut.get("String").unwrap()->get() == testIn.String, "testOut.String failed"); + auto &testOutStruct = testOut.get("Struct").unwrap()->get(); + auto &testOutUnion = testOut.get("Union").unwrap()->get(); + auto &testOutList = testOut.get("List").unwrap()->get(); + auto testOutStructCopy = testOut.get("Struct").unwrap()->get(); + auto testOutUnionCopy = testOut.get("Union").unwrap()->get(); + auto testOutListCopy = testOut.get("List").unwrap()->get(); oxAssert(testOutStruct.typeName() == TestStructNest::TypeName, "ModelObject TypeName failed"); oxAssert(testOutStruct.typeVersion() == TestStructNest::TypeVersion, "ModelObject TypeVersion failed"); - oxAssert(testOutStruct["Bool"].get() == testIn.Struct.Bool, "testOut.Struct.Bool failed"); - oxAssert(testOutStruct["String"].get() == testIn.Struct.String.c_str(), "testOut.Struct.String failed"); - oxAssert(testOut["unionIdx"].get() == testIn.unionIdx, "testOut.unionIdx failed"); + oxAssert(testOutStruct.get("Bool").unwrap()->get() == testIn.Struct.Bool, "testOut.Struct.Bool failed"); + oxAssert(testOutStruct.get("String").unwrap()->get() == testIn.Struct.String.c_str(), "testOut.Struct.String failed"); + oxAssert(testOut.get("unionIdx").unwrap()->get() == testIn.unionIdx, "testOut.unionIdx failed"); oxAssert(testOutUnion.unionIdx() == testIn.unionIdx, "testOut.Union idx wrong"); - oxAssert(testOutUnion["Int"].get() == testIn.Union.Int, "testOut.Union.Int failed"); + oxAssert(testOutUnion.get("Int").unwrap()->get() == testIn.Union.Int, "testOut.Union.Int failed"); oxAssert(testOutList[0].get() == testIn.List[0], "testOut.List[0] failed"); oxAssert(testOutList[1].get() == testIn.List[1], "testOut.Struct.List[1] failed"); - oxAssert(testOutStructCopy["Bool"].get() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed"); - oxAssert(testOutStructCopy["String"].get() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed"); + oxAssert(testOutStructCopy.get("Bool").unwrap()->get() == testIn.Struct.Bool, "testOut.Struct.Bool (copy) failed"); + oxAssert(testOutStructCopy.get("String").unwrap()->get() == testIn.Struct.String.c_str(), "testOut.Struct.String (copy) failed"); oxAssert(testOutListCopy[0].get() == testIn.List[0], "testOut.Struct.List[0] (copy) failed"); oxAssert(testOutListCopy[1].get() == testIn.List[1], "testOut.Struct.List[1] (copy) failed"); return OxError(0); diff --git a/src/ox/std/memops.hpp b/src/ox/std/memops.hpp index 820f3288d..77ea1e061 100644 --- a/src/ox/std/memops.hpp +++ b/src/ox/std/memops.hpp @@ -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 void *memsetElements(T *ptr, T val, std::size_t elements) noexcept { return memset(ptr, val, elements * sizeof(T)); diff --git a/src/ox/std/memory.hpp b/src/ox/std/memory.hpp index 78440edc6..58a06929b 100644 --- a/src/ox/std/memory.hpp +++ b/src/ox/std/memory.hpp @@ -247,6 +247,9 @@ class UniquePtr { }; +template +using UPtr = UniquePtr; + template constexpr bool operator==(const UniquePtr &p1, const UniquePtr &p2) noexcept { return p1.get() == p2.get(); diff --git a/src/ox/std/stringview.hpp b/src/ox/std/stringview.hpp index 5b1e824f2..72e2b5f1f 100644 --- a/src/ox/std/stringview.hpp +++ b/src/ox/std/stringview.hpp @@ -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 class BasicString; class StringView { + public: + template + struct iterator: public Iterator { + 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(m_offset - s, 0), m_max); + } else { + return iterator(m_t, min(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(m_offset + s, m_max), m_max); + } else { + return iterator(m_t, max(m_offset - s, 0), m_max); + } + } + + constexpr iterator &operator+=(std::size_t s) noexcept { + if constexpr(reverse) { + m_offset = max(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(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 begin() const noexcept { + return {m_str, 0, m_len}; + } + + [[nodiscard]] + constexpr iterator end() const noexcept { + return {m_str, m_len, m_len}; + } + + [[nodiscard]] + constexpr iterator cbegin() const noexcept { + return {m_str, 0, m_len}; + } + + [[nodiscard]] + constexpr iterator cend() const noexcept { + return {m_str, m_len, m_len}; + } + + [[nodiscard]] + constexpr iterator crbegin() const noexcept { + return {m_str, m_len - 1, m_len}; + } + + [[nodiscard]] + constexpr iterator crend() const noexcept { + return {m_str, MaxValue, m_len}; + } + + [[nodiscard]] + constexpr iterator rbegin() const noexcept { + return {m_str, m_len - 1, m_len}; + } + + [[nodiscard]] + constexpr iterator rend() const noexcept { + return {m_str, MaxValue, 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]; }