[ox] Add StringView, Writer system, Preloader system
This commit is contained in:
parent
98f35140fe
commit
cbb496c59f
1
deps/ox/src/ox/CMakeLists.txt
vendored
1
deps/ox/src/ox/CMakeLists.txt
vendored
@ -7,4 +7,5 @@ add_subdirectory(event)
|
||||
add_subdirectory(fs)
|
||||
add_subdirectory(mc)
|
||||
add_subdirectory(model)
|
||||
add_subdirectory(preloader)
|
||||
add_subdirectory(std)
|
||||
|
9
deps/ox/src/ox/claw/read.cpp
vendored
9
deps/ox/src/ox/claw/read.cpp
vendored
@ -15,10 +15,11 @@ namespace ox {
|
||||
Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcept {
|
||||
const auto s1End = ox_strchr(buff, ';', buffLen);
|
||||
if (!s1End) {
|
||||
oxAssert(false, "fail");
|
||||
return OxError(1, "Could not read Claw header");
|
||||
}
|
||||
const auto s1Size = s1End - buff;
|
||||
String fmt(buff, s1Size);
|
||||
const String fmt(buff, s1Size);
|
||||
buff += s1Size + 1;
|
||||
buffLen -= s1Size + 1;
|
||||
|
||||
@ -27,7 +28,7 @@ Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcep
|
||||
return OxError(2, "Could not read Claw header");
|
||||
}
|
||||
const auto s2Size = s2End - buff;
|
||||
String typeName(buff, s2Size);
|
||||
const String typeName(buff, s2Size);
|
||||
buff += s2Size + 1;
|
||||
buffLen -= s2Size + 1;
|
||||
|
||||
@ -36,7 +37,7 @@ Result<ClawHeader> readClawHeader(const char *buff, std::size_t buffLen) noexcep
|
||||
return OxError(3, "Could not read Claw header");
|
||||
}
|
||||
const auto s3Size = s3End - buff;
|
||||
String versionStr(buff, s3Size);
|
||||
const String versionStr(buff, s3Size);
|
||||
buff += s3Size + 1;
|
||||
buffLen -= s3Size + 1;
|
||||
|
||||
@ -74,7 +75,7 @@ Result<Buffer> stripClawHeader(const ox::Buffer &buff) noexcept {
|
||||
|
||||
Result<ModelObject> readClaw(TypeStore *ts, const Buffer &buff) noexcept {
|
||||
oxRequire(header, readClawHeader(buff));
|
||||
oxRequire(t, ts->template getLoad(header.typeName, header.typeVersion));
|
||||
oxRequire(t, ts->template getLoad(header.typeName, header.typeVersion, header.typeParams));
|
||||
ModelObject obj;
|
||||
oxReturnError(obj.setType(t));
|
||||
switch (header.fmt) {
|
||||
|
1
deps/ox/src/ox/claw/read.hpp
vendored
1
deps/ox/src/ox/claw/read.hpp
vendored
@ -25,6 +25,7 @@ constexpr auto Error_ClawTypeVersionMismatch = 201;
|
||||
struct ClawHeader {
|
||||
String typeName;
|
||||
int typeVersion = -1;
|
||||
TypeParamPack typeParams;
|
||||
ClawFormat fmt = ClawFormat::None;
|
||||
const char *data = nullptr;
|
||||
std::size_t dataSize = 0;
|
||||
|
2
deps/ox/src/ox/claw/test/tests.cpp
vendored
2
deps/ox/src/ox/claw/test/tests.cpp
vendored
@ -96,7 +96,7 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) {
|
||||
oxReturnError(io->field("Int7", &obj->Int7));
|
||||
oxReturnError(io->field("Int8", &obj->Int8));
|
||||
int unionIdx = 0;
|
||||
if constexpr(ox_strcmp(T::opType(), ox::OpType::Reflect) != 0) {
|
||||
if constexpr(T::opType() != ox::OpType::Reflect) {
|
||||
unionIdx = obj->unionIdx;
|
||||
}
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, unionIdx}));
|
||||
|
13
deps/ox/src/ox/claw/write.hpp
vendored
13
deps/ox/src/ox/claw/write.hpp
vendored
@ -24,10 +24,12 @@ namespace detail {
|
||||
struct TypeInfoCatcher {
|
||||
|
||||
const char *name = nullptr;
|
||||
int version = 0;
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int = T::TypeVersion) noexcept {
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int v = T::TypeVersion, const Vector<String>& = {}, int = 0) noexcept {
|
||||
this->name = name;
|
||||
this->version = v;
|
||||
}
|
||||
|
||||
constexpr Error field(...) noexcept {
|
||||
@ -57,6 +59,13 @@ constexpr const char *getTypeName(T *t) noexcept {
|
||||
return tnc.name;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr int getTypeVersion(T *t) noexcept {
|
||||
TypeInfoCatcher tnc;
|
||||
oxIgnoreError(model(&tnc, t));
|
||||
return tnc.version;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Result<String> writeClawHeader(T *t, ClawFormat fmt) noexcept {
|
||||
String out;
|
||||
@ -72,7 +81,7 @@ Result<String> writeClawHeader(T *t, ClawFormat fmt) noexcept {
|
||||
}
|
||||
out += detail::getTypeName(t);
|
||||
out += ";";
|
||||
const auto tn = detail::type_version<T>::value;
|
||||
const auto tn = detail::getTypeVersion(t);
|
||||
if (tn > -1) {
|
||||
out += tn;
|
||||
}
|
||||
|
@ -28,10 +28,10 @@ FileAddress::FileAddress(uint64_t inode) noexcept {
|
||||
m_type = FileAddressType::Inode;
|
||||
}
|
||||
|
||||
FileAddress::FileAddress(const ox::String &path) noexcept {
|
||||
FileAddress::FileAddress(ox::CRStringView path) noexcept {
|
||||
auto pathSize = path.bytes();
|
||||
m_data.path = new char[pathSize];
|
||||
memcpy(m_data.path, path.c_str(), pathSize);
|
||||
memcpy(m_data.path, path.data(), pathSize);
|
||||
m_type = FileAddressType::Path;
|
||||
}
|
||||
|
||||
@ -98,7 +98,7 @@ FileAddress &FileAddress::operator=(FileAddress &&other) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool FileAddress::operator==(const ox::String &path) const noexcept {
|
||||
bool FileAddress::operator==(CRStringView path) const noexcept {
|
||||
auto [p, err] = getPath();
|
||||
if (err) {
|
||||
return false;
|
||||
|
15
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
15
deps/ox/src/ox/fs/filesystem/filelocation.hpp
vendored
@ -57,7 +57,11 @@ class FileAddress {
|
||||
|
||||
FileAddress(uint64_t inode) noexcept;
|
||||
|
||||
FileAddress(const ox::String &path) noexcept;
|
||||
FileAddress(CRStringView path) noexcept;
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
FileAddress(const ox::BasicString<SmallStrSz> &path) noexcept: FileAddress(StringView(path)) {
|
||||
}
|
||||
|
||||
FileAddress(char *path) noexcept;
|
||||
|
||||
@ -69,7 +73,7 @@ class FileAddress {
|
||||
|
||||
FileAddress &operator=(FileAddress &&other) noexcept;
|
||||
|
||||
bool operator==(const ox::String &path) const noexcept;
|
||||
bool operator==(CRStringView path) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr FileAddressType type() const noexcept {
|
||||
@ -82,6 +86,7 @@ class FileAddress {
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr Result<uint64_t> getInode() const noexcept {
|
||||
switch (m_type) {
|
||||
case FileAddressType::Inode:
|
||||
@ -141,16 +146,16 @@ constexpr Error model(T *io, CommonPtrWith<FileAddress::Data> auto *obj) noexcep
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, CommonPtrWith<FileAddress> auto *fa) noexcept {
|
||||
io->template setTypeInfo<FileAddress>();
|
||||
if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) {
|
||||
if constexpr(T::opType() == OpType::Reflect) {
|
||||
int8_t type = 0;
|
||||
oxReturnError(io->field("type", &type));
|
||||
oxReturnError(io->field("data", UnionView(&fa->m_data, 0)));
|
||||
} else if constexpr(ox_strcmp(T::opType(), OpType::Read) == 0) {
|
||||
} else if constexpr(T::opType() == OpType::Read) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(io->field("type", &type));
|
||||
fa->m_type = static_cast<FileAddressType>(type);
|
||||
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
} else if constexpr(ox_strcmp(T::opType(), OpType::Write) == 0) {
|
||||
} else if constexpr(T::opType() == OpType::Write) {
|
||||
auto type = static_cast<int8_t>(fa->m_type);
|
||||
oxReturnError(io->field("type", &type));
|
||||
oxReturnError(io->field("data", UnionView(&fa->m_data, static_cast<int>(fa->m_type))));
|
||||
|
4
deps/ox/src/ox/fs/tool.cpp
vendored
4
deps/ox/src/ox/fs/tool.cpp
vendored
@ -62,8 +62,8 @@ static ox::Error runRead(ox::FileSystem *fs, int argc, const char **argv) noexce
|
||||
}
|
||||
|
||||
static ox::Error run(int argc, const char **argv) noexcept {
|
||||
if (argc < 2) {
|
||||
oxErr("Subcommand and OxFS file arguments are required\n");
|
||||
if (argc < 3) {
|
||||
oxErr("OxFS file and subcommand arguments are required\n");
|
||||
return OxError(1);
|
||||
}
|
||||
const auto fsPath = argv[1];
|
||||
|
10
deps/ox/src/ox/mc/read.hpp
vendored
10
deps/ox/src/ox/mc/read.hpp
vendored
@ -100,7 +100,7 @@ class MetalClawReaderTemplate {
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion,
|
||||
int fields = ModelFieldCount_v<T>) noexcept;
|
||||
const Vector<String>& = {}, int fields = ModelFieldCount_v<T>) noexcept;
|
||||
|
||||
/**
|
||||
* Returns a MetalClawReader to parse a child object.
|
||||
@ -225,7 +225,7 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char *name, a
|
||||
if (valLen >= len) {
|
||||
auto reader = child("");
|
||||
auto handler = HandlerMaker(&reader);
|
||||
handler.setTypeInfo("List", 0, static_cast<int>(len));
|
||||
handler.setTypeInfo("List", 0, {}, static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
oxReturnError(handler.field("", &val[i]));
|
||||
}
|
||||
@ -254,7 +254,7 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, HashMa
|
||||
// read the list
|
||||
auto reader = child("");
|
||||
auto handler = HandlerMaker(&reader);
|
||||
handler.setTypeInfo("List", 0, static_cast<int>(len));
|
||||
handler.setTypeInfo("List", 0, {}, static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
const auto keyLen = handler.stringLength(nullptr);
|
||||
auto wkey = ox_malloca(keyLen + 1, char, 0);
|
||||
@ -500,7 +500,7 @@ constexpr Error MetalClawReaderTemplate<HandlerMaker>::field(const char*, CB cb)
|
||||
// read the list
|
||||
auto reader = child("");
|
||||
auto handler = HandlerMaker(&reader);
|
||||
handler.setTypeInfo("List", 0, static_cast<int>(len));
|
||||
handler.setTypeInfo("List", 0, {}, static_cast<int>(len));
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
T val;
|
||||
oxReturnError(handler.field("", &val));
|
||||
@ -527,7 +527,7 @@ constexpr StringLength MetalClawReaderTemplate<HandlerMaker>::stringLength(const
|
||||
|
||||
template<auto HandlerMaker>
|
||||
template<typename T>
|
||||
constexpr void MetalClawReaderTemplate<HandlerMaker>::setTypeInfo(const char*, int, int fields) noexcept {
|
||||
constexpr void MetalClawReaderTemplate<HandlerMaker>::setTypeInfo(const char*, int, const Vector<String>&, int fields) noexcept {
|
||||
m_fields = fields;
|
||||
m_buffIt = static_cast<std::size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
||||
m_fieldPresence.setFields(fields);
|
||||
|
14
deps/ox/src/ox/mc/test/tests.cpp
vendored
14
deps/ox/src/ox/mc/test/tests.cpp
vendored
@ -89,7 +89,7 @@ constexpr ox::Error model(T *io, ox::CommonPtrWith<TestStruct> auto *obj) noexce
|
||||
oxReturnError(io->field("Int7", &obj->Int7));
|
||||
oxReturnError(io->field("Int8", &obj->Int8));
|
||||
oxReturnError(io->field("unionIdx", &obj->unionIdx));
|
||||
if (ox_strcmp(io->opType(), ox::OpType::Reflect) == 0) {
|
||||
if constexpr(T::opType() == ox::OpType::Reflect) {
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0}));
|
||||
} else {
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
|
||||
@ -309,10 +309,10 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
testIn.Union.Int = 93;
|
||||
oxAssert(ox::writeMC(dataBuff.data(), dataBuff.size(), &testIn), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(typeErr, "Descriptor write failed");
|
||||
ox::ModelObject testOut;
|
||||
oxReturnError(testOut.setType(type.value));
|
||||
oxReturnError(testOut.setType(type));
|
||||
oxAssert(ox::readMC(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");
|
||||
@ -361,9 +361,9 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
testIn.Struct.BString = "Test String 2";
|
||||
oxAssert(ox::writeMC(dataBuff, dataBuffLen, &testIn), "Data generation failed");
|
||||
ox::TypeStore typeStore;
|
||||
auto type = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
oxReturnError(ox::walkModel<ox::MetalClawReader>(type.value, dataBuff, dataBuffLen,
|
||||
const auto [type, typeErr] = ox::buildTypeDef(&typeStore, &testIn);
|
||||
oxAssert(typeErr, "Descriptor write failed");
|
||||
oxReturnError(ox::walkModel<ox::MetalClawReader>(type, dataBuff, dataBuffLen,
|
||||
[](const ox::Vector<ox::FieldName>&, const ox::Vector<ox::String>&, const ox::DescriptorField &f, ox::MetalClawReader *rdr) -> ox::Error {
|
||||
//std::cout << f.fieldName.c_str() << '\n';
|
||||
auto fieldName = f.fieldName.c_str();
|
||||
|
16
deps/ox/src/ox/mc/write.hpp
vendored
16
deps/ox/src/ox/mc/write.hpp
vendored
@ -104,7 +104,7 @@ class MetalClawWriter {
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion,
|
||||
int fields = ModelFieldCount_v<T>) noexcept;
|
||||
const Vector<String>& = {}, int fields = ModelFieldCount_v<T>) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t size() const noexcept;
|
||||
@ -135,10 +135,10 @@ class MetalClawWriter {
|
||||
};
|
||||
|
||||
constexpr MetalClawWriter::MetalClawWriter(uint8_t *buff, std::size_t buffLen, int unionIdx) noexcept:
|
||||
m_fieldPresence(buff, buffLen),
|
||||
m_unionIdx(unionIdx),
|
||||
m_buffLen(buffLen),
|
||||
m_buff(buff) {
|
||||
m_fieldPresence(buff, buffLen),
|
||||
m_unionIdx(unionIdx),
|
||||
m_buffLen(buffLen),
|
||||
m_buff(buff) {
|
||||
}
|
||||
|
||||
constexpr MetalClawWriter::~MetalClawWriter() noexcept {
|
||||
@ -330,7 +330,7 @@ constexpr Error MetalClawWriter::field(const char*, T *val, std::size_t len) noe
|
||||
|
||||
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||
ModelHandlerInterface handler{&writer};
|
||||
handler.setTypeInfo<T>("List", 0, len);
|
||||
handler.setTypeInfo<T>("List", 0, {}, len);
|
||||
|
||||
// write the array
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
@ -363,7 +363,7 @@ constexpr Error MetalClawWriter::field(const char*, const HashMap<String, T> *va
|
||||
MetalClawWriter writer(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||
ModelHandlerInterface handler{&writer};
|
||||
// double len for both key and value
|
||||
handler.setTypeInfo("Map", 0, len * 2);
|
||||
handler.setTypeInfo("Map", 0, {}, len * 2);
|
||||
// write the array
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
const auto &key = keys[i];
|
||||
@ -388,7 +388,7 @@ constexpr Error MetalClawWriter::field(const char *name, HashMap<String, T> *val
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void MetalClawWriter::setTypeInfo(const char*, int, int fields) noexcept {
|
||||
constexpr void MetalClawWriter::setTypeInfo(const char*, int, const Vector<String>&, int fields) noexcept {
|
||||
m_fields = fields;
|
||||
m_fieldPresence.setFields(fields);
|
||||
m_buffIt = static_cast<std::size_t>(m_fieldPresence.getMaxLen());
|
||||
|
5
deps/ox/src/ox/model/CMakeLists.txt
vendored
5
deps/ox/src/ox/model/CMakeLists.txt
vendored
@ -2,6 +2,7 @@ add_library(
|
||||
OxModel
|
||||
desctypes.cpp
|
||||
descwrite.cpp
|
||||
modelvalue.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
@ -42,3 +43,7 @@ install(TARGETS OxModel
|
||||
LIBRARY DESTINATION lib/ox
|
||||
ARCHIVE DESTINATION lib/ox
|
||||
)
|
||||
|
||||
if(OX_RUN_TESTS)
|
||||
add_subdirectory(test)
|
||||
endif()
|
118
deps/ox/src/ox/model/desctypes.hpp
vendored
118
deps/ox/src/ox/model/desctypes.hpp
vendored
@ -10,6 +10,7 @@
|
||||
|
||||
#include <ox/std/bit.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/fmt.hpp>
|
||||
#include <ox/std/hashmap.hpp>
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
@ -23,6 +24,22 @@ namespace ox {
|
||||
|
||||
using FieldName = String;
|
||||
|
||||
using TypeParamPack = Vector<String>;
|
||||
|
||||
static constexpr auto buildTypeId(CRStringView name, int version,
|
||||
const TypeParamPack &typeParams) noexcept {
|
||||
String tp;
|
||||
if (typeParams.size()) {
|
||||
tp = "<";
|
||||
for (const auto &p : typeParams) {
|
||||
tp += p + ",";
|
||||
}
|
||||
tp = tp.substr(0, tp.len() - 1);
|
||||
tp += ">";
|
||||
}
|
||||
return ox::sfmt("{}{};{}", name, tp, version);
|
||||
}
|
||||
|
||||
enum class PrimitiveType: uint8_t {
|
||||
UnsignedInteger = 0,
|
||||
SignedInteger = 1,
|
||||
@ -33,45 +50,82 @@ enum class PrimitiveType: uint8_t {
|
||||
Union = 6,
|
||||
};
|
||||
|
||||
struct Subscript {
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.Subscript";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
enum class SubscriptType: uint32_t {
|
||||
None = 0,
|
||||
Ptr = 1,
|
||||
PtrArray = 2,
|
||||
InlineArray = 3,
|
||||
Vector = 4,
|
||||
};
|
||||
SubscriptType subscriptType = SubscriptType::None;
|
||||
uint64_t length = 0;
|
||||
uint64_t smallSzLen = 0;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, CommonPtrWith<Subscript> auto *type) noexcept {
|
||||
io->template setTypeInfo<Subscript>();
|
||||
if constexpr(T::opType() == OpType::Reflect) {
|
||||
uint32_t st = 0;
|
||||
oxReturnError(io->field("subscriptType", &st));
|
||||
} else {
|
||||
auto pt = type ? static_cast<uint32_t>(type->subscriptType) : 0;
|
||||
oxReturnError(io->field("subscriptType", &pt));
|
||||
type->subscriptType = static_cast<Subscript::SubscriptType>(pt);
|
||||
}
|
||||
oxReturnError(io->field("length", &type->length));
|
||||
oxReturnError(io->field("smallSzLen", &type->smallSzLen));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
using SubscriptStack = Vector<Subscript, 3>;
|
||||
|
||||
struct DescriptorField {
|
||||
// order of fields matters
|
||||
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.DescriptorField";
|
||||
static constexpr auto TypeVersion = 2;
|
||||
static constexpr auto TypeVersion = 3;
|
||||
|
||||
// do not serialize type
|
||||
const struct DescriptorType *type = nullptr;
|
||||
String fieldName;
|
||||
int subscriptLevels = 0;
|
||||
String typeName; // gives reference to type for lookup if type is null
|
||||
int typeVersion = 0;
|
||||
bool list = false;
|
||||
SubscriptStack subscriptStack;
|
||||
String typeId; // gives reference to type for lookup if type is null
|
||||
|
||||
constexpr DescriptorField() noexcept = default;
|
||||
|
||||
constexpr DescriptorField(const DescriptorType *pType, String pFieldName,
|
||||
int pSubscriptLevels, String pTypeName, int pTypeVersion) noexcept:
|
||||
int pSubscriptLevels,
|
||||
SubscriptStack pSubscriptType,
|
||||
String pTypeId) noexcept:
|
||||
type(pType),
|
||||
fieldName(std::move(pFieldName)),
|
||||
subscriptLevels(pSubscriptLevels),
|
||||
typeName(std::move(pTypeName)),
|
||||
typeVersion(pTypeVersion) {
|
||||
subscriptStack(std::move(pSubscriptType)),
|
||||
typeId(std::move(pTypeId)) {
|
||||
}
|
||||
|
||||
constexpr DescriptorField(const DescriptorField &other) noexcept:
|
||||
type(other.type),
|
||||
fieldName(other.fieldName),
|
||||
subscriptLevels(other.subscriptLevels),
|
||||
typeName(other.typeName) {
|
||||
subscriptStack(other.subscriptStack),
|
||||
typeId(other.typeId) {
|
||||
}
|
||||
|
||||
constexpr DescriptorField(DescriptorField &&other) noexcept:
|
||||
type(other.type),
|
||||
fieldName(other.fieldName),
|
||||
fieldName(std::move(other.fieldName)),
|
||||
subscriptLevels(other.subscriptLevels),
|
||||
typeName(std::move(other.typeName)) {
|
||||
subscriptStack(std::move(other.subscriptStack)),
|
||||
typeId(std::move(other.typeId)) {
|
||||
other.type = {};
|
||||
other.subscriptLevels = {};
|
||||
other.subscriptStack = {};
|
||||
}
|
||||
|
||||
constexpr ~DescriptorField() noexcept = default;
|
||||
@ -86,13 +140,14 @@ using FieldList = Vector<DescriptorField>;
|
||||
|
||||
struct DescriptorType {
|
||||
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.DescriptorType";
|
||||
static constexpr auto TypeVersion = 2;
|
||||
static constexpr auto TypeName = "net.drinkingtea.ox.TypeDescriptor";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
|
||||
String typeName;
|
||||
int typeVersion = 0;
|
||||
PrimitiveType primitiveType = PrimitiveType::UnsignedInteger;
|
||||
// fieldList only applies to structs
|
||||
TypeParamPack typeParams;
|
||||
// fieldList only applies to structs and unions
|
||||
FieldList fieldList;
|
||||
// - number of bytes for integer and float types
|
||||
// - number of fields for structs and lists
|
||||
@ -101,31 +156,26 @@ struct DescriptorType {
|
||||
|
||||
constexpr DescriptorType() noexcept = default;
|
||||
|
||||
constexpr explicit DescriptorType(String tn, int typeVersion) noexcept:
|
||||
typeName(std::move(tn)), typeVersion(typeVersion) {
|
||||
}
|
||||
|
||||
constexpr DescriptorType(String tn, PrimitiveType t, int b) noexcept:
|
||||
constexpr explicit DescriptorType(String tn, int typeVersion, PrimitiveType t, TypeParamPack pTypeParams) noexcept:
|
||||
typeName(std::move(tn)),
|
||||
typeVersion(typeVersion),
|
||||
primitiveType(t),
|
||||
length(b) {
|
||||
}
|
||||
|
||||
constexpr DescriptorType(String tn, PrimitiveType t, FieldList fl) noexcept:
|
||||
typeName(std::move(tn)),
|
||||
primitiveType(t),
|
||||
fieldList(std::move(fl)) {
|
||||
typeParams(std::move(pTypeParams)) {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto buildTypeId(const DescriptorType &t) noexcept {
|
||||
return buildTypeId(t.typeName, t.typeVersion, t.typeParams);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept {
|
||||
io->template setTypeInfo<DescriptorType>();
|
||||
oxReturnError(io->field("typeName", &type->typeName));
|
||||
oxReturnError(io->field("typeVersion", &type->typeVersion));
|
||||
if constexpr(ox_strcmp(T::opType(), OpType::Reflect) == 0) {
|
||||
if constexpr(T::opType() == OpType::Reflect) {
|
||||
uint8_t pt = 0;
|
||||
oxReturnError(io->field("primitiveType", &pt));
|
||||
} else {
|
||||
@ -133,6 +183,7 @@ constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept
|
||||
oxReturnError(io->field("primitiveType", &pt));
|
||||
type->primitiveType = static_cast<PrimitiveType>(pt);
|
||||
}
|
||||
oxReturnError(io->field("typeParams", &type->typeParams));
|
||||
oxReturnError(io->field("fieldList", &type->fieldList));
|
||||
oxReturnError(io->field("length", &type->length));
|
||||
oxReturnError(io->field("preloadable", &type->preloadable));
|
||||
@ -142,9 +193,10 @@ constexpr Error model(T *io, CommonPtrWith<DescriptorType> auto *type) noexcept
|
||||
template<typename T>
|
||||
constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcept {
|
||||
io->template setTypeInfo<DescriptorField>();
|
||||
oxReturnError(io->field("typeName", &field->typeName));
|
||||
oxReturnError(io->field("typeId", &field->typeId));
|
||||
oxReturnError(io->field("fieldName", &field->fieldName));
|
||||
oxReturnError(io->field("subscriptLevels", &field->subscriptLevels));
|
||||
oxReturnError(io->field("subscriptStack", &field->subscriptStack));
|
||||
// defaultValue is unused now, but leave placeholder for backwards compatibility
|
||||
int defaultValue = 0;
|
||||
oxReturnError(io->field("defaultValue", &defaultValue));
|
||||
@ -154,20 +206,30 @@ constexpr Error model(T *io, CommonPtrWith<DescriptorField> auto *field) noexcep
|
||||
template<typename ReaderBase>
|
||||
class TypeDescReader;
|
||||
|
||||
#if 0 // unused right now
|
||||
template<typename T>
|
||||
constexpr Error model(TypeDescReader<T> *io, CommonPtrWith<DescriptorField> auto *field) noexcept {
|
||||
io->template setTypeInfo<DescriptorField>(DescriptorField::TypeName, DescriptorField::TypeVersion, 4);
|
||||
io->template setTypeInfo<DescriptorField>();
|
||||
oxReturnError(io->field("typeName", &field->typeName));
|
||||
oxReturnError(io->field("typeVersion", &field->typeVersion));
|
||||
auto &typeStore = io->typeStore();
|
||||
auto &[type, err] = typeStore->at(field->typeName).value;
|
||||
oxReturnError(err);
|
||||
field->type = type.get();
|
||||
oxReturnError(io->field("fieldName", &field->fieldName));
|
||||
oxReturnError(io->field("subscriptLevels", &field->subscriptLevels));
|
||||
if constexpr(T::opType() != ox::OpType::Reflect) {
|
||||
auto subscriptStack = static_cast<uint32_t>(field->subscriptStack);
|
||||
oxReturnError(io->field("subscriptStack", &subscriptStack));
|
||||
field->subscriptStack = static_cast<DescriptorField::SubscriptType>(subscriptStack);
|
||||
} else {
|
||||
oxReturnError(io->field("subscriptStack", &field->subscriptStack));
|
||||
}
|
||||
// defaultValue is unused now, but placeholder for backwards compatibility
|
||||
int defaultValue = 0;
|
||||
oxReturnError(io->field("defaultValue", &defaultValue));
|
||||
return OxError(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
153
deps/ox/src/ox/model/descwrite.hpp
vendored
153
deps/ox/src/ox/model/descwrite.hpp
vendored
@ -38,6 +38,45 @@ constexpr int indirectionLevels_v<T*> = 1 + indirectionLevels_v<T>;
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr int indirectionLevels_v<T[sz]> = 1 + indirectionLevels_v<T>;
|
||||
|
||||
template<typename T, std::size_t SmallVecSz>
|
||||
constexpr int indirectionLevels_v<::ox::Vector<T, SmallVecSz>> = 1 + indirectionLevels_v<typename T::value_type>;
|
||||
|
||||
template<typename T>
|
||||
constexpr auto buildSubscriptStack(const T*, SubscriptStack*) noexcept {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr auto buildSubscriptStack(const T**, SubscriptStack *s) noexcept {
|
||||
s->push_back({.subscriptType = Subscript::SubscriptType::Ptr});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr auto buildSubscriptStack(const UniquePtr<T>*, SubscriptStack *s) noexcept {
|
||||
s->push_back({.subscriptType = Subscript::SubscriptType::Ptr});
|
||||
}
|
||||
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr auto buildSubscriptStack(const Array<T, sz>*, SubscriptStack *s) noexcept {
|
||||
s->push_back({.subscriptType = Subscript::SubscriptType::InlineArray, .length = sz});
|
||||
buildSubscriptStack(static_cast<T*>(nullptr), s);
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVecSz>
|
||||
constexpr auto buildSubscriptStack(const Vector<T, SmallVecSz>*, SubscriptStack *s) noexcept {
|
||||
s->push_back({
|
||||
.subscriptType = Subscript::SubscriptType::Vector,
|
||||
.smallSzLen = SmallVecSz,
|
||||
});
|
||||
buildSubscriptStack(static_cast<T*>(nullptr), s);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr auto buildSubscriptStack(const T*) {
|
||||
SubscriptStack s;
|
||||
buildSubscriptStack(static_cast<const T*>(nullptr), &s);
|
||||
return s;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TypeDescWriter {
|
||||
@ -52,21 +91,23 @@ class TypeDescWriter {
|
||||
constexpr ~TypeDescWriter() noexcept = default;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName,
|
||||
constexpr void setTypeInfo(CRStringView name = T::TypeName,
|
||||
int version = T::TypeVersion,
|
||||
int fields = ModelFieldCount_v<T>) noexcept;
|
||||
const TypeParamPack &typeParams = {},
|
||||
int fields = ModelFieldCount_v<T>) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, const T *val, std::size_t valLen) noexcept;
|
||||
constexpr Error field(CRStringView name, const T *val, std::size_t valLen,
|
||||
const SubscriptStack &subscriptStack = {}) noexcept;
|
||||
|
||||
template<typename T, bool force>
|
||||
constexpr Error field(CRStringView name, UnionView<T, force> val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, T val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, const T *val) noexcept;
|
||||
constexpr Error field(CRStringView name, const T *val) noexcept;
|
||||
|
||||
template<typename ...Args>
|
||||
constexpr Error fieldCString(const char *name, Args&&...) noexcept;
|
||||
constexpr Error fieldCString(CRStringView name, Args&&...) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr DescriptorType *definition() noexcept {
|
||||
@ -105,8 +146,12 @@ class TypeDescWriter {
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(SerStr val) const noexcept;
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *type(const String *val) const noexcept;
|
||||
constexpr const DescriptorType *type(const BasicString<SmallStrSz>*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(types::BasicString, 1, PT, 0, {sfmt("{}", SmallStrSz)});
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
[[nodiscard]]
|
||||
@ -125,71 +170,77 @@ class TypeDescWriter {
|
||||
constexpr const DescriptorType *type(UnionView<U> val) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const DescriptorType *getType(const String &tn, int typeVersion, PrimitiveType t, int b) const noexcept;
|
||||
constexpr const DescriptorType *getType(CRStringView tn, int typeVersion, PrimitiveType t, int b,
|
||||
const TypeParamPack &typeParams = {}) const noexcept;
|
||||
|
||||
};
|
||||
|
||||
constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeStore(typeStore) {
|
||||
}
|
||||
constexpr TypeDescWriter::TypeDescWriter(TypeStore *typeStore) noexcept: m_typeStore(typeStore) {}
|
||||
|
||||
template<typename T>
|
||||
constexpr void TypeDescWriter::setTypeInfo(const char *typeName, int typeVersion, int) noexcept {
|
||||
m_type = m_typeStore->getInit(typeName, typeVersion);
|
||||
constexpr void TypeDescWriter::setTypeInfo(CRStringView typeName, int typeVersion,
|
||||
const TypeParamPack &typeParams, int) noexcept {
|
||||
PrimitiveType pt;
|
||||
if constexpr(is_union_v<T>) {
|
||||
m_type->primitiveType = PrimitiveType::Union;
|
||||
pt = PrimitiveType::Union;
|
||||
} else if constexpr(isBasicString_v<T> || isBString_v<T>) {
|
||||
pt = PrimitiveType::String;
|
||||
} else {
|
||||
m_type->primitiveType = PrimitiveType::Struct;
|
||||
pt = PrimitiveType::Struct;
|
||||
}
|
||||
m_type->preloadable = detail::preloadable<T>::value;
|
||||
m_type = m_typeStore->getInit(typeName, typeVersion, pt, typeParams);
|
||||
m_type->preloadable = preloadable<T>::value;
|
||||
}
|
||||
|
||||
// array handler
|
||||
template<typename T>
|
||||
constexpr Error TypeDescWriter::field(const char *name, const T *val, std::size_t) noexcept {
|
||||
constexpr Error TypeDescWriter::field(CRStringView name, const T*, std::size_t, const SubscriptStack &subscriptStack) noexcept {
|
||||
if (m_type) {
|
||||
constexpr typename remove_pointer<decltype(val)>::type *p = nullptr;
|
||||
constexpr typename remove_pointer<T>::type *p = nullptr;
|
||||
const auto t = type(p);
|
||||
oxAssert(t != nullptr, "field(const char *name, T *val, std::size_t): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, name, detail::indirectionLevels_v<T> + 1, t->typeName, t->typeVersion);
|
||||
m_type->fieldList.emplace_back(t, name, detail::indirectionLevels_v<T> + 1, subscriptStack, buildTypeId(*t));
|
||||
return OxError(0);
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T, bool force>
|
||||
constexpr Error TypeDescWriter::field(CRStringView name, UnionView<T, force> val) noexcept {
|
||||
if (m_type) {
|
||||
const auto t = type(val);
|
||||
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, name, 0, SubscriptStack{}, t->typeName);
|
||||
return OxError(0);
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error TypeDescWriter::field(const char *name, T val) noexcept {
|
||||
if (m_type) {
|
||||
if constexpr(isVector_v<typename ox::remove_pointer<T>::type> || isArray_v<typename ox::remove_pointer<T>::type>) {
|
||||
return field(name, val->data(), val->size());
|
||||
} else {
|
||||
const auto t = type(val);
|
||||
oxAssert(t != nullptr, "field(const char *name, T val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, name, 0, t->typeName, t->typeVersion);
|
||||
return OxError(0);
|
||||
}
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error TypeDescWriter::field(const char *name, const T *val) noexcept {
|
||||
constexpr Error TypeDescWriter::field(CRStringView name, const T *val) noexcept {
|
||||
if (m_type) {
|
||||
if constexpr(isVector_v<T> || isArray_v<T>) {
|
||||
return field(name, val->data(), val->size());
|
||||
return field(name, val->data(), 0, detail::buildSubscriptStack(val));
|
||||
} else if constexpr(isSmartPtr_v<T>) {
|
||||
return field(name, val->get(), 0, detail::buildSubscriptStack(val));
|
||||
} else if constexpr(is_pointer_v<T>) {
|
||||
return field(name, val, 0, detail::buildSubscriptStack(val));
|
||||
} else {
|
||||
const auto t = type(val);
|
||||
oxAssert(t != nullptr, "field(const char *name, T *val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, name, 0, t->typeName, t->typeVersion);
|
||||
return OxError(0);
|
||||
m_type->fieldList.emplace_back(t, name, 0, SubscriptStack{}, buildTypeId(*t));
|
||||
return {};
|
||||
}
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename ...Args>
|
||||
constexpr Error TypeDescWriter::fieldCString(const char *name, Args&&...) noexcept {
|
||||
String s;
|
||||
return field(name, &s);
|
||||
constexpr Error TypeDescWriter::fieldCString(CRStringView name, Args&&...) noexcept {
|
||||
constexpr auto s = "";
|
||||
const auto t = type(s);
|
||||
m_type->fieldList.emplace_back(t, name, 0, SubscriptStack{}, t->typeName);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -286,29 +337,25 @@ constexpr const DescriptorType *TypeDescWriter::type(SerStr) const noexcept {
|
||||
return getType(types::String, 0, PT, 0);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const String*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(types::String, 0, PT, 0);
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr const DescriptorType *TypeDescWriter::type(const BString<sz>*) const noexcept {
|
||||
constexpr auto PT = PrimitiveType::String;
|
||||
return getType(types::String, 0, PT, 0);
|
||||
return getType(types::BString, 0, PT, 0);
|
||||
}
|
||||
|
||||
constexpr const DescriptorType *TypeDescWriter::getType(const String &tn, int typeVersion, PrimitiveType pt, int b) const noexcept {
|
||||
auto t = m_typeStore->get(tn, typeVersion);
|
||||
constexpr const DescriptorType *TypeDescWriter::getType(CRStringView tn, int typeVersion, PrimitiveType pt, int b,
|
||||
const TypeParamPack &typeParams) const noexcept {
|
||||
auto t = m_typeStore->get(tn, typeVersion, typeParams);
|
||||
if (!t.error) {
|
||||
auto type = t.value;
|
||||
oxAssert(type != nullptr, "TypeDescWriter::getType returning null DescriptorType");
|
||||
return type;
|
||||
} else {
|
||||
auto dt = ox::make_unique<DescriptorType>(tn, typeVersion);
|
||||
dt->primitiveType = pt;
|
||||
auto dt = ox::make_unique<DescriptorType>(tn, typeVersion, pt, typeParams);
|
||||
dt->length = b;
|
||||
const auto out = dt.get();
|
||||
m_typeStore->set(tn, typeVersion, std::move(dt));
|
||||
const auto typeId = buildTypeId(tn, typeVersion, typeParams);
|
||||
m_typeStore->set(typeId, std::move(dt));
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
11
deps/ox/src/ox/model/fieldcounter.hpp
vendored
11
deps/ox/src/ox/model/fieldcounter.hpp
vendored
@ -8,6 +8,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/assert.hpp>
|
||||
#include <ox/std/bit.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
|
||||
@ -23,23 +24,23 @@ class FieldCounter {
|
||||
int fields = 0;
|
||||
|
||||
template<typename U = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char * = "", int = 0, int = 0) {
|
||||
constexpr void setTypeInfo(CRStringView = "", int = 0, const Vector<String>& = {}, int = 0) {
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr ox::Error field(const char *, U) noexcept {
|
||||
constexpr ox::Error field(CRStringView, U) noexcept {
|
||||
++fields;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
constexpr ox::Error field(const char *, U, std::size_t) noexcept {
|
||||
constexpr ox::Error field(CRStringView, U, std::size_t) noexcept {
|
||||
++fields;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename U, typename Handler>
|
||||
constexpr Error field(const char *, Handler) {
|
||||
constexpr Error field(CRStringView, Handler) {
|
||||
++fields;
|
||||
return OxError(0);
|
||||
}
|
||||
@ -49,7 +50,7 @@ class FieldCounter {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
static constexpr auto opType() {
|
||||
static constexpr auto opType() noexcept {
|
||||
return OpType::Reflect;
|
||||
}
|
||||
};
|
||||
|
18
deps/ox/src/ox/model/metadata.hpp
vendored
18
deps/ox/src/ox/model/metadata.hpp
vendored
@ -21,25 +21,29 @@
|
||||
#include "optype.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace ox::detail {
|
||||
namespace ox {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<bool>
|
||||
struct BoolWrapper {
|
||||
};
|
||||
|
||||
template<typename T, typename = BoolWrapper<true>>
|
||||
template<int>
|
||||
struct IntWrapper {
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename = detail::BoolWrapper<true>>
|
||||
struct preloadable: false_type {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct preloadable<T, BoolWrapper<T::Preloadable>> {
|
||||
struct preloadable<T, detail::BoolWrapper<T::Preloadable>> {
|
||||
static constexpr bool value = T::Preloadable;
|
||||
};
|
||||
|
||||
template<int>
|
||||
struct IntWrapper {
|
||||
};
|
||||
|
||||
// cannot be done until C++20
|
||||
//struct PseudoString {
|
||||
// constexpr PseudoString(const char* = "") noexcept {}
|
||||
|
45
deps/ox/src/ox/model/modelhandleradaptor.hpp
vendored
45
deps/ox/src/ox/model/modelhandleradaptor.hpp
vendored
@ -25,8 +25,8 @@ class ModelHandlerInterface {
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *name = T::TypeName, int version = T::TypeVersion,
|
||||
int fields = ModelFieldCount_v<T>) noexcept {
|
||||
m_handler->setTypeInfo(name, version, fields);
|
||||
const Vector<String> &typeParams = {}, int fields = ModelFieldCount_v<T>) noexcept {
|
||||
m_handler->setTypeInfo(name, version, typeParams, fields);
|
||||
}
|
||||
|
||||
template<std::size_t len>
|
||||
@ -63,7 +63,7 @@ class ModelHandlerInterface {
|
||||
return m_handler->fieldCString(name, val, buffLen);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, CommonPtrWith<ModelValue> auto *v) noexcept {
|
||||
constexpr Error fieldModelValue(const char *name, CommonPtrWith<ModelValue> auto *v) noexcept {
|
||||
switch (v->type()) {
|
||||
case ModelValue::Type::Undefined:
|
||||
break;
|
||||
@ -92,14 +92,17 @@ class ModelHandlerInterface {
|
||||
case ModelValue::Type::Union:
|
||||
{
|
||||
auto &u = v->template get<ModelUnion>();
|
||||
if constexpr(ox_strcmp(Handler::opType(), OpType::Read) == 0) {
|
||||
if constexpr(Handler::opType() == OpType::Read) {
|
||||
u.setActiveField(m_handler->whichFieldPresent(name, u));
|
||||
return m_handler->field(name, UnionView<ModelUnion, true>(&u, u.unionIdx()));
|
||||
} else {
|
||||
return m_handler->field(name, UnionView<const ModelUnion, true>(&u, u.unionIdx()));
|
||||
}
|
||||
return m_handler->field(name, UnionView<ModelUnion, true>(&u, u.unionIdx()));
|
||||
}
|
||||
case ModelValue::Type::Vector:
|
||||
return m_handler->field(name, &v->template get<ModelValueVector>());
|
||||
}
|
||||
oxErrf("invalid type: {}: {}\n", name, static_cast<int>(v->type()));
|
||||
oxPanic(OxError(1), "invalid type");
|
||||
return OxError(1, "invalid type");
|
||||
}
|
||||
@ -110,12 +113,22 @@ class ModelHandlerInterface {
|
||||
return m_handler->template field<T, Callback>(name, cb);
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, const auto *v) noexcept {
|
||||
return m_handler->field(name, v);
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, const T *v) noexcept {
|
||||
if constexpr(ox::is_same_v<T, ModelValue>) {
|
||||
return fieldModelValue(name, v);
|
||||
} else {
|
||||
return m_handler->field(name, v);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Error field(const char *name, auto *v) noexcept {
|
||||
return m_handler->field(name, v);
|
||||
template<typename T>
|
||||
constexpr Error field(const char *name, T *v) noexcept {
|
||||
if constexpr(ox::is_same_v<T, ModelValue>) {
|
||||
return fieldModelValue(name, v);
|
||||
} else {
|
||||
return m_handler->field(name, v);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename U, bool force = false>
|
||||
@ -156,4 +169,18 @@ class ModelHandlerInterface {
|
||||
|
||||
};
|
||||
|
||||
template<typename Handler>
|
||||
class ModelHandlerBase {
|
||||
private:
|
||||
ModelHandlerInterface<Handler> m_interface;
|
||||
public:
|
||||
constexpr ModelHandlerBase() noexcept: m_interface(static_cast<Handler*>(this)) {}
|
||||
constexpr ModelHandlerBase(const ModelHandlerBase&) noexcept: m_interface(static_cast<Handler*>(this)) {}
|
||||
constexpr ModelHandlerBase(ModelHandlerBase&&) noexcept: m_interface(static_cast<Handler*>(this)) {}
|
||||
[[nodiscard]]
|
||||
constexpr auto interface() noexcept {
|
||||
return &m_interface;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
9
deps/ox/src/ox/model/modelops.hpp
vendored
9
deps/ox/src/ox/model/modelops.hpp
vendored
@ -76,7 +76,8 @@ class MemberList {
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = ModelFieldCount_v<T>) noexcept {
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = ModelTypeVersion_v<T>,
|
||||
const Vector<String>& = {}, int = ModelFieldCount_v<T>) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -135,7 +136,7 @@ class Copier {
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, int = ModelFieldCount_v<T>) noexcept {
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, const Vector<String>& = {}, int = ModelFieldCount_v<T>) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -196,7 +197,7 @@ class Mover {
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, int = ModelFieldCount_v<T>) noexcept {
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, const Vector<String>& = {}, int = ModelFieldCount_v<T>) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@ -272,7 +273,7 @@ class Equals {
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) noexcept {
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, const Vector<String>& = {}, int = T::Fields) noexcept {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
|
14
deps/ox/src/ox/model/modelvalue.cpp
vendored
14
deps/ox/src/ox/model/modelvalue.cpp
vendored
@ -7,3 +7,17 @@
|
||||
*/
|
||||
|
||||
#include "modelvalue.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
static_assert([]() -> ox::Error {
|
||||
ox::ModelValue v;
|
||||
oxReturnError(v.setType<int32_t>());
|
||||
if (v.type() != ModelValue::Type::SignedInteger32) {
|
||||
return OxError(1, "type is wrong");
|
||||
}
|
||||
//oxReturnError(v.set<int32_t>(5));
|
||||
return {};
|
||||
}() == OxError(0));
|
||||
|
||||
}
|
||||
|
195
deps/ox/src/ox/model/modelvalue.hpp
vendored
195
deps/ox/src/ox/model/modelvalue.hpp
vendored
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/serialize.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/trace.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
@ -60,20 +61,20 @@ class ModelValue {
|
||||
int32_t i32;
|
||||
uint32_t ui32;
|
||||
int64_t i64;
|
||||
uint64_t ui64;
|
||||
String *str = nullptr;
|
||||
uint64_t ui64 = 0;
|
||||
String *str;
|
||||
ModelObject *obj;
|
||||
ModelUnion *uni;
|
||||
ModelValueVector *vec;
|
||||
} m_data;
|
||||
|
||||
template<typename T>
|
||||
consteval static Type getType() noexcept {
|
||||
static consteval Type getType() noexcept {
|
||||
using U = typename ox::remove_reference<T>::type;
|
||||
if constexpr(is_bool_v<U>) {
|
||||
return Type::Bool;
|
||||
} else if constexpr(is_integer_v<U>) {
|
||||
if (!is_signed_v<U> && sizeof(U) == 1) {
|
||||
if constexpr(!is_signed_v<U> && sizeof(U) == 1) {
|
||||
return Type::UnsignedInteger8;
|
||||
} else if constexpr(!is_signed_v<U> && sizeof(U) == 2) {
|
||||
return Type::UnsignedInteger16;
|
||||
@ -94,7 +95,7 @@ class ModelValue {
|
||||
return Type::Union;
|
||||
} else if constexpr(is_same_v<U, ModelObject>) {
|
||||
return Type::Object;
|
||||
} else if constexpr(is_same_v<U, String>) {
|
||||
} else if constexpr(isBasicString_v<U> || isBString_v<U>) {
|
||||
return Type::String;
|
||||
} else if constexpr(is_same_v<U, ModelValueVector>) {
|
||||
return Type::Vector;
|
||||
@ -198,6 +199,129 @@ class ModelValue {
|
||||
|
||||
};
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t sizeOf(const ModelValueVector*) noexcept {
|
||||
VectorMemMap<PlatSpec> v;
|
||||
return sizeOf<PlatSpec>(&v);
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t sizeOf(const ModelUnion*) noexcept {
|
||||
VectorMemMap<PlatSpec> v;
|
||||
return sizeOf<PlatSpec>(&v);
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t sizeOf(const ModelValue *t) noexcept {
|
||||
std::size_t size = 0;
|
||||
switch (t->type()) {
|
||||
case ModelValue::Type::Bool:
|
||||
size = sizeof(t->get<bool>());
|
||||
break;
|
||||
case ModelValue::Type::Undefined:
|
||||
size = 1;
|
||||
break;
|
||||
case ModelValue::Type::UnsignedInteger8:
|
||||
size = sizeof(t->get<uint8_t>());
|
||||
break;
|
||||
case ModelValue::Type::UnsignedInteger16:
|
||||
size = sizeof(t->get<uint16_t>());
|
||||
break;
|
||||
case ModelValue::Type::UnsignedInteger32:
|
||||
size = sizeof(t->get<uint32_t>());
|
||||
break;
|
||||
case ModelValue::Type::UnsignedInteger64:
|
||||
size = sizeof(t->get<uint64_t>());
|
||||
break;
|
||||
case ModelValue::Type::SignedInteger8:
|
||||
size = sizeof(t->get<int8_t>());
|
||||
break;
|
||||
case ModelValue::Type::SignedInteger16:
|
||||
size = sizeof(t->get<int16_t>());
|
||||
break;
|
||||
case ModelValue::Type::SignedInteger32:
|
||||
size = sizeof(t->get<int32_t>());
|
||||
break;
|
||||
case ModelValue::Type::SignedInteger64:
|
||||
size = sizeof(t->get<int64_t>());
|
||||
break;
|
||||
case ModelValue::Type::String:
|
||||
size = sizeOf<PlatSpec>(&t->get<ox::String>());
|
||||
break;
|
||||
case ModelValue::Type::Object:
|
||||
size = sizeOf<PlatSpec>(&t->get<ox::ModelObject>());
|
||||
break;
|
||||
case ModelValue::Type::Union:
|
||||
size = sizeOf<PlatSpec>(&t->get<ox::ModelUnion>());
|
||||
break;
|
||||
case ModelValue::Type::Vector:
|
||||
size = sizeOf<PlatSpec>(&t->get<ox::ModelValueVector>());
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t alignOf(const ModelValueVector&) noexcept {
|
||||
VectorMemMap<PlatSpec> v;
|
||||
return alignOf<PlatSpec>(v);
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t alignOf(const ModelValue &t) noexcept {
|
||||
std::size_t size = 0;
|
||||
switch (t.type()) {
|
||||
case ModelValue::Type::Bool:
|
||||
size = PlatSpec::alignOf(t.get<bool>());
|
||||
break;
|
||||
case ModelValue::Type::Undefined:
|
||||
size = 1;
|
||||
break;
|
||||
case ModelValue::Type::UnsignedInteger8:
|
||||
size = PlatSpec::alignOf(t.get<uint8_t>());
|
||||
break;
|
||||
case ModelValue::Type::UnsignedInteger16:
|
||||
size = PlatSpec::alignOf(t.get<uint16_t>());
|
||||
break;
|
||||
case ModelValue::Type::UnsignedInteger32:
|
||||
size = PlatSpec::alignOf(t.get<uint32_t>());
|
||||
break;
|
||||
case ModelValue::Type::UnsignedInteger64:
|
||||
size = PlatSpec::alignOf(t.get<uint64_t>());
|
||||
break;
|
||||
case ModelValue::Type::SignedInteger8:
|
||||
size = PlatSpec::alignOf(t.get<int8_t>());
|
||||
break;
|
||||
case ModelValue::Type::SignedInteger16:
|
||||
size = PlatSpec::alignOf(t.get<int16_t>());
|
||||
break;
|
||||
case ModelValue::Type::SignedInteger32:
|
||||
size = PlatSpec::alignOf(t.get<int32_t>());
|
||||
break;
|
||||
case ModelValue::Type::SignedInteger64:
|
||||
size = PlatSpec::alignOf(t.get<int64_t>());
|
||||
break;
|
||||
case ModelValue::Type::String:
|
||||
size = PlatSpec::alignOf(t.get<ox::String>());
|
||||
break;
|
||||
case ModelValue::Type::Object:
|
||||
size = alignOf<PlatSpec>(t.get<ox::ModelObject>());
|
||||
break;
|
||||
case ModelValue::Type::Union:
|
||||
size = alignOf<PlatSpec>(t.get<ox::ModelUnion>());
|
||||
break;
|
||||
case ModelValue::Type::Vector:
|
||||
size = alignOf<PlatSpec>(t.get<ox::ModelValueVector>());
|
||||
break;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
class ModelValueVector {
|
||||
private:
|
||||
Vector<ModelValue> m_vec;
|
||||
@ -329,6 +453,7 @@ class 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;
|
||||
|
||||
@ -340,12 +465,14 @@ class ModelObject {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value});
|
||||
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;
|
||||
@ -419,6 +546,7 @@ class ModelObject {
|
||||
auto &field = m_fieldsOrder.emplace_back(new Field{f->name, f->value});
|
||||
m_fields[field->name] = &field->value;
|
||||
}
|
||||
m_type = other.m_type;
|
||||
m_typeName = other.m_typeName;
|
||||
m_typeVersion = other.m_typeVersion;
|
||||
return *this;
|
||||
@ -428,6 +556,7 @@ class ModelObject {
|
||||
if (&other == this) [[unlikely]] {
|
||||
return *this;
|
||||
}
|
||||
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);
|
||||
@ -448,7 +577,7 @@ class ModelObject {
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr const String &typeName() const noexcept {
|
||||
constexpr StringView typeName() const noexcept {
|
||||
return m_typeName;
|
||||
}
|
||||
|
||||
@ -457,10 +586,16 @@ class ModelObject {
|
||||
return m_typeVersion;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto type() const noexcept {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
constexpr Error setType(const DescriptorType *type) noexcept {
|
||||
if (type->primitiveType != PrimitiveType::Struct && type->primitiveType != PrimitiveType::Union) {
|
||||
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) {
|
||||
@ -609,7 +744,7 @@ class ModelUnion {
|
||||
};
|
||||
|
||||
constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
|
||||
h->setTypeInfo(obj->m_typeName.c_str(), obj->m_typeVersion, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
h->setTypeInfo(obj->m_typeName.c_str(), obj->m_typeVersion, {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
oxReturnError(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
@ -617,7 +752,7 @@ constexpr Error model(auto *h, CommonPtrWith<ModelObject> auto *obj) noexcept {
|
||||
}
|
||||
|
||||
constexpr Error model(auto *h, CommonPtrWith<ModelUnion> auto *obj) noexcept {
|
||||
h->setTypeInfo(obj->m_typeName.c_str(), obj->m_typeVersion, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
h->setTypeInfo(obj->m_typeName.c_str(), obj->m_typeVersion, {}, static_cast<int>(obj->m_fieldsOrder.size()));
|
||||
for (auto &f : obj->m_fieldsOrder) {
|
||||
oxReturnError(h->field(f->name.c_str(), &f->value));
|
||||
}
|
||||
@ -718,7 +853,9 @@ constexpr Error ModelValue::setType(const DescriptorType *type, int subscriptLev
|
||||
return m_data.vec->setType(type, subscriptLevels - 1);
|
||||
} else if (type->typeName == types::Bool) {
|
||||
m_type = Type::Bool;
|
||||
} else if (type->typeName == types::String) {
|
||||
} else if (type->typeName == types::BasicString ||
|
||||
type->typeName == types::BString ||
|
||||
type->typeName == types::String) {
|
||||
m_type = Type::String;
|
||||
m_data.str = new String;
|
||||
} else if (type->typeName == types::Uint8) {
|
||||
@ -747,13 +884,47 @@ constexpr Error ModelValue::setType(const DescriptorType *type, int subscriptLev
|
||||
m_data.uni = u.release();
|
||||
oxReturnError(m_data.uni->setType(type));
|
||||
}
|
||||
oxAssert(m_type != Type::Undefined, "No type set");
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error ModelValue::setType() noexcept {
|
||||
constexpr auto type = getType<T>();
|
||||
return setType(type);
|
||||
freeResources();
|
||||
m_type = type;
|
||||
// 2022.09.04: Clang retardedly requires initializing the union values directly, rather than using getValue<type>()
|
||||
if constexpr(type == Type::Object) {
|
||||
m_data.obj = new ModelObject;
|
||||
oxReturnError(m_data.obj->setType(type));
|
||||
} else if constexpr(type == Type::Union) {
|
||||
oxRequireM(u, ModelUnion::make(type));
|
||||
m_data.uni = u.release();
|
||||
oxReturnError(m_data.uni->setType(type));
|
||||
} else if constexpr(type == Type::String) {
|
||||
m_data.str = new String;
|
||||
} else if constexpr(type == Type::Vector) {
|
||||
m_data.vec = new ModelValueVector;
|
||||
} else if constexpr(type == Type::Bool) {
|
||||
m_data.b = false;
|
||||
} else if constexpr(type == Type::SignedInteger8) {
|
||||
m_data.i8 = 0;
|
||||
} else if constexpr(type == Type::SignedInteger16) {
|
||||
m_data.i16 = 0;
|
||||
} else if constexpr(type == Type::SignedInteger32) {
|
||||
m_data.i32 = 0;
|
||||
} else if constexpr(type == Type::SignedInteger64) {
|
||||
m_data.i64 = 0;
|
||||
} else if constexpr(type == Type::UnsignedInteger8) {
|
||||
m_data.ui8 = 0;
|
||||
} else if constexpr(type == Type::UnsignedInteger16) {
|
||||
m_data.ui16 = 0;
|
||||
} else if constexpr(type == Type::UnsignedInteger32) {
|
||||
m_data.ui32 = 0;
|
||||
} else if constexpr(type == Type::UnsignedInteger64) {
|
||||
m_data.ui64 = 0;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
@ -763,6 +934,10 @@ constexpr Error ModelValue::set(const T &v) noexcept {
|
||||
return OxError(1, "type mismatch");
|
||||
}
|
||||
auto &value = getValue<type>(*this);
|
||||
if constexpr(type == Type::Vector || type == Type::Object ||
|
||||
type == Type::Union || type == Type::String) {
|
||||
safeDelete(&value);
|
||||
}
|
||||
value = v;
|
||||
return OxError(0);
|
||||
}
|
||||
|
17
deps/ox/src/ox/model/optype.hpp
vendored
17
deps/ox/src/ox/model/optype.hpp
vendored
@ -8,13 +8,14 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/assert.hpp>
|
||||
#include <ox/std/concepts.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/strops.hpp>
|
||||
#include <ox/std/stringview.hpp>
|
||||
|
||||
namespace ox {
|
||||
|
||||
enum class OpType {
|
||||
Read = 1,
|
||||
Write,
|
||||
Reflect,
|
||||
};
|
||||
|
||||
namespace ox::OpType {
|
||||
constexpr auto Read = "Read";
|
||||
constexpr auto Write = "Write";
|
||||
constexpr auto Reflect = "Reflect";
|
||||
}
|
||||
|
11
deps/ox/src/ox/model/test/CMakeLists.txt
vendored
Normal file
11
deps/ox/src/ox/model/test/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
add_executable(
|
||||
ModelTest
|
||||
tests.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
ModelTest
|
||||
OxModel
|
||||
)
|
||||
|
||||
add_test("[ox/model] ModelTest Writer" ModelTest ModelValue)
|
41
deps/ox/src/ox/model/test/tests.cpp
vendored
Normal file
41
deps/ox/src/ox/model/test/tests.cpp
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#undef NDEBUG
|
||||
|
||||
#include <map>
|
||||
#include <ox/model/model.hpp>
|
||||
#include <ox/std/std.hpp>
|
||||
|
||||
std::map<ox::String, ox::Error(*)()> tests = {
|
||||
{
|
||||
{
|
||||
"ModelValue",
|
||||
[] {
|
||||
ox::ModelValue v;
|
||||
oxReturnError(v.setType<int32_t>());
|
||||
//v.m_type = ox::ModelValue::getType<int32_t>();
|
||||
if (v.type() != ox::ModelValue::Type::SignedInteger32) {
|
||||
return OxError(1, "type is wrong");
|
||||
}
|
||||
oxReturnError(v.set<int32_t>(5));
|
||||
return ox::Error{};
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
if (argc > 0) {
|
||||
auto testName = args[1];
|
||||
if (tests.find(testName) != tests.end()) {
|
||||
oxAssert(tests[testName](), "Test failed...");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
10
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
10
deps/ox/src/ox/model/typenamecatcher.hpp
vendored
@ -8,9 +8,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/memory.hpp>
|
||||
|
||||
#include "fieldcounter.hpp"
|
||||
#include "optype.hpp"
|
||||
@ -25,7 +25,7 @@ struct TypeNameCatcher {
|
||||
constexpr TypeNameCatcher() noexcept = default;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *n = T::TypeName, int v = 0) noexcept {
|
||||
constexpr void setTypeInfo(const char *n = T::TypeName, const Vector<String>& = {}, int v = 0) noexcept {
|
||||
this->name = n;
|
||||
this->version = v;
|
||||
}
|
||||
@ -59,7 +59,7 @@ struct TypeInfoCatcher {
|
||||
constexpr TypeInfoCatcher() noexcept = default;
|
||||
|
||||
template<typename T = std::nullptr_t>
|
||||
constexpr void setTypeInfo(const char *n = T::TypeName, int v = T::TypeVersion, int = 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;
|
||||
}
|
||||
@ -87,7 +87,7 @@ struct TypeInfoCatcher {
|
||||
|
||||
template<typename T>
|
||||
constexpr int getModelTypeVersion() noexcept {
|
||||
auto a = std::allocator<T>();
|
||||
std::allocator<T> a;
|
||||
auto t = a.allocate(1);
|
||||
TypeInfoCatcher nc;
|
||||
oxIgnoreError(model(&nc, t));
|
||||
@ -111,7 +111,7 @@ consteval int requireModelTypeVersion() noexcept {
|
||||
|
||||
template<typename T, typename Str = const char*>
|
||||
constexpr Str getModelTypeName() noexcept {
|
||||
auto a = std::allocator<T>();
|
||||
std::allocator<T> a;
|
||||
auto t = a.allocate(1);
|
||||
TypeNameCatcher nc;
|
||||
oxIgnoreError(model(&nc, t));
|
||||
|
102
deps/ox/src/ox/model/types.hpp
vendored
102
deps/ox/src/ox/model/types.hpp
vendored
@ -22,6 +22,7 @@
|
||||
|
||||
#include <ox/std/array.hpp>
|
||||
#include <ox/std/bstring.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/strops.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/typetraits.hpp>
|
||||
@ -30,25 +31,77 @@
|
||||
namespace ox {
|
||||
|
||||
namespace types {
|
||||
constexpr auto String = "B.string";
|
||||
constexpr auto Bool = "B.bool";
|
||||
constexpr auto Uint8 = "B.uint8";
|
||||
constexpr auto Uint16 = "B.uint16";
|
||||
constexpr auto Uint32 = "B.uint32";
|
||||
constexpr auto Uint64 = "B.uint64";
|
||||
constexpr auto Int8 = "B.int8";
|
||||
constexpr auto Int16 = "B.int16";
|
||||
constexpr auto Int32 = "B.int32";
|
||||
constexpr auto Int64 = "B.int64";
|
||||
constexpr StringView BasicString = "net.drinkingtea.ox.BasicString";
|
||||
constexpr StringView BString = "net.drinkingtea.ox.BString";
|
||||
constexpr StringView String = "B.string";
|
||||
constexpr StringView Bool = "B.bool";
|
||||
constexpr StringView Uint8 = "B.uint8";
|
||||
constexpr StringView Uint16 = "B.uint16";
|
||||
constexpr StringView Uint32 = "B.uint32";
|
||||
constexpr StringView Uint64 = "B.uint64";
|
||||
constexpr StringView Int8 = "B.int8";
|
||||
constexpr StringView Int16 = "B.int16";
|
||||
constexpr StringView Int32 = "B.int32";
|
||||
constexpr StringView Int64 = "B.int64";
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
consteval bool isBasicString(const T*) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<std::size_t SmallVecSize>
|
||||
consteval bool isBasicString(const BasicString<SmallVecSize>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isBasicString_v = isBasicString(static_cast<const T*>(nullptr));
|
||||
|
||||
static_assert(isBasicString_v<ox::BasicString<0ul>>);
|
||||
static_assert(isBasicString_v<ox::BasicString<8ul>>);
|
||||
static_assert(isBasicString_v<ox::String>);
|
||||
|
||||
template<typename T>
|
||||
consteval bool isBString(const T*) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<std::size_t SmallVecSize>
|
||||
consteval bool isBString(const BasicString<SmallVecSize>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isBString_v = isBasicString(static_cast<const T*>(nullptr));
|
||||
|
||||
static_assert(isBasicString_v<ox::BasicString<0ul>>);
|
||||
static_assert(isBasicString_v<ox::BasicString<8ul>>);
|
||||
static_assert(isBasicString_v<ox::String>);
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isOxString_v = isBString_v<T> || isBasicString_v<T>;
|
||||
|
||||
template<typename T>
|
||||
consteval bool isOxVector(const T*) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVecSize>
|
||||
consteval bool isOxVector(const Vector<T, SmallVecSize>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isOxVector_v = isVector(static_cast<const T*>(nullptr));
|
||||
|
||||
template<typename T>
|
||||
consteval bool isVector(const T*) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
consteval bool isVector(const Vector<T>*) noexcept {
|
||||
template<typename T, std::size_t SmallVecSize>
|
||||
consteval bool isVector(const Vector<T, SmallVecSize>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -71,21 +124,36 @@ constexpr bool isVector_v = isVector(static_cast<const T*>(nullptr));
|
||||
|
||||
static_assert(isVector_v<ox::Vector<unsigned int, 0ul>>);
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isBareArray_v = false;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isBareArray_v<T[]> = true;
|
||||
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr bool isBareArray_v<T[sz]> = true;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isArray_v = false;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isArray_v<T[]> = false;
|
||||
constexpr bool isArray_v<T[]> = true;
|
||||
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr bool isArray_v<T[sz]> = false;
|
||||
constexpr bool isArray_v<T[sz]> = true;
|
||||
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr bool isArray_v<Array<T, sz>> = false;
|
||||
constexpr bool isArray_v<Array<T, sz>> = true;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isSmartPtr_v = false;
|
||||
|
||||
template<typename T>
|
||||
constexpr bool isSmartPtr_v<::ox::UniquePtr<T>> = true;
|
||||
|
||||
#if __has_include(<array>)
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr bool isArray_v<std::array<T, sz>> = false;
|
||||
template<typename T>
|
||||
constexpr bool isSmartPtr_v<::std::unique_ptr<T>> = true;
|
||||
#endif
|
||||
|
||||
|
||||
|
54
deps/ox/src/ox/model/typestore.hpp
vendored
54
deps/ox/src/ox/model/typestore.hpp
vendored
@ -8,12 +8,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/fmt.hpp>
|
||||
#include <ox/std/hashmap.hpp>
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/typetraits.hpp>
|
||||
|
||||
#include "ox/std/fmt.hpp"
|
||||
#include "typenamecatcher.hpp"
|
||||
#include "desctypes.hpp"
|
||||
|
||||
@ -23,45 +23,42 @@ class TypeStore {
|
||||
private:
|
||||
HashMap<String, UniquePtr<DescriptorType>> m_cache;
|
||||
|
||||
static constexpr auto buildTypeId(const auto &name, auto version) noexcept {
|
||||
return ox::sfmt("{};{}", name, version);
|
||||
}
|
||||
|
||||
public:
|
||||
constexpr TypeStore() noexcept = default;
|
||||
|
||||
constexpr virtual ~TypeStore() noexcept = default;
|
||||
|
||||
constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion) const noexcept {
|
||||
const auto typeId = buildTypeId(name, typeVersion);
|
||||
constexpr Result<const DescriptorType*> get(const auto &name, int typeVersion,
|
||||
const Vector<String> &typeParams) const noexcept {
|
||||
const auto typeId = buildTypeId(name, typeVersion, typeParams);
|
||||
oxRequire(out, m_cache.at(typeId));
|
||||
return out->get();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Result<const DescriptorType*> get() const noexcept {
|
||||
constexpr auto typeName = requireModelTypeName<T>();
|
||||
constexpr auto typeVersion = requireModelTypeVersion<T>();
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
constexpr auto typeName = ModelTypeName_v<T>;
|
||||
constexpr auto typeVersion = ModelTypeVersion_v<T>;
|
||||
const auto typeId = buildTypeId(typeName, typeVersion, {});
|
||||
oxRequire(out, m_cache.at(typeId));
|
||||
return out->get();
|
||||
}
|
||||
|
||||
constexpr DescriptorType *getInit(const auto &typeName, int typeVersion) noexcept {
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
constexpr DescriptorType *getInit(const auto &typeName, int typeVersion, PrimitiveType pt,
|
||||
const TypeParamPack &typeParams) noexcept {
|
||||
const auto typeId = buildTypeId(typeName, typeVersion, typeParams);
|
||||
auto &out = m_cache[typeId];
|
||||
out = ox::make_unique<DescriptorType>(typeName, typeVersion);
|
||||
out = ox::make_unique<DescriptorType>(typeName, typeVersion, pt, typeParams);
|
||||
return out.get();
|
||||
}
|
||||
|
||||
constexpr Result<const DescriptorType*> getLoad(const auto &typeName, auto typeVersion) noexcept {
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
constexpr Result<const DescriptorType*> getLoad(const auto &typeId) noexcept {
|
||||
auto [val, err] = m_cache.at(typeId);
|
||||
if (err) {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
oxRequireM(dt, loadDescriptor(typeName, typeVersion));
|
||||
oxRequireM(dt, loadDescriptor(typeId));
|
||||
for (auto &f : dt->fieldList) {
|
||||
oxReturnError(this->getLoad(f.typeName, f.typeVersion).moveTo(&f.type));
|
||||
oxReturnError(this->getLoad(f.typeId).moveTo(&f.type));
|
||||
}
|
||||
auto &out = m_cache[typeId];
|
||||
out = std::move(dt);
|
||||
@ -73,6 +70,11 @@ class TypeStore {
|
||||
return val->get();
|
||||
}
|
||||
|
||||
constexpr Result<const DescriptorType*> getLoad(const auto &typeName, auto typeVersion,
|
||||
const Vector<String> &typeParams = {}) noexcept {
|
||||
return getLoad(buildTypeId(typeName, typeVersion, typeParams));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Result<const DescriptorType*> getLoad() noexcept {
|
||||
constexpr auto typeName = requireModelTypeName<T>();
|
||||
@ -80,19 +82,17 @@ class TypeStore {
|
||||
return getLoad(typeName, typeVersion);
|
||||
}
|
||||
|
||||
constexpr void set(const auto &typeName, auto typeVersion, UniquePtr<DescriptorType> dt) noexcept {
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
constexpr void set(const auto &typeId, UniquePtr<DescriptorType> dt) noexcept {
|
||||
m_cache[typeId] = std::move(dt);
|
||||
}
|
||||
|
||||
constexpr void set(const auto &typeName, auto typeVersion, DescriptorType *dt) noexcept {
|
||||
const auto typeId = buildTypeId(typeName, typeVersion);
|
||||
m_cache[typeId] = UniquePtr<DescriptorType>(dt);
|
||||
constexpr void set(const auto &typeId, DescriptorType *dt) noexcept {
|
||||
m_cache[typeId] = UniquePtr<DescriptorType>(dt);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto typeList() const noexcept {
|
||||
auto keys = m_cache.keys();
|
||||
const auto &keys = m_cache.keys();
|
||||
ox::Vector<DescriptorType*> descs;
|
||||
for (const auto &k : keys) {
|
||||
descs.emplace_back(m_cache.at(k).value->get());
|
||||
@ -101,10 +101,16 @@ class TypeStore {
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(const ox::String&, int) noexcept {
|
||||
virtual Result<UniquePtr<DescriptorType>> loadDescriptor(ox::CRStringView) noexcept {
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
Result<UniquePtr<DescriptorType>> loadDescriptor(ox::CRStringView name, int version,
|
||||
const Vector<String> &typeParams) noexcept {
|
||||
const auto typeId = buildTypeId(name, version, typeParams);
|
||||
return loadDescriptor(typeId);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
5
deps/ox/src/ox/model/walk.hpp
vendored
5
deps/ox/src/ox/model/walk.hpp
vendored
@ -89,7 +89,7 @@ static constexpr Error parseField(const DescriptorField &field, Reader *rdr, Dat
|
||||
// add array handling
|
||||
oxRequire(arrayLen, rdr->arrayLength(field.fieldName.c_str(), true));
|
||||
auto child = rdr->child(field.fieldName.c_str());
|
||||
child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, arrayLen);
|
||||
child.setTypeInfo(field.type->typeName.c_str(), field.type->typeVersion, field.type->typeParams, arrayLen);
|
||||
DescriptorField f(field); // create mutable copy
|
||||
--f.subscriptLevels;
|
||||
String subscript;
|
||||
@ -135,8 +135,9 @@ constexpr Error model(Reader *rdr, DataWalker<Reader, FH> *walker) noexcept {
|
||||
oxRequire(type, walker->type());
|
||||
auto typeName = type->typeName.c_str();
|
||||
auto typeVersion = type->typeVersion;
|
||||
auto typeParams = type->typeParams;
|
||||
auto &fields = type->fieldList;
|
||||
rdr->setTypeInfo(typeName, typeVersion, fields.size());
|
||||
rdr->setTypeInfo(typeName, typeVersion, typeParams, fields.size());
|
||||
for (const auto &field : fields) {
|
||||
oxReturnError(parseField(field, rdr, walker));
|
||||
}
|
||||
|
4
deps/ox/src/ox/oc/read.hpp
vendored
4
deps/ox/src/ox/oc/read.hpp
vendored
@ -100,11 +100,11 @@ class OrganicClawReader {
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char*, int) noexcept {
|
||||
constexpr void setTypeInfo(const char*, int, const Vector<String>& = {}) noexcept {
|
||||
}
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char*, int, int) noexcept {
|
||||
constexpr void setTypeInfo(const char*, int, const Vector<String>& = {}, int = {}) noexcept {
|
||||
}
|
||||
|
||||
/**
|
||||
|
2
deps/ox/src/ox/oc/test/tests.cpp
vendored
2
deps/ox/src/ox/oc/test/tests.cpp
vendored
@ -94,7 +94,7 @@ constexpr ox::Error model(auto *io, ox::CommonPtrWith<TestStruct> auto *obj) noe
|
||||
oxReturnError(io->field("Int7", &obj->Int7));
|
||||
oxReturnError(io->field("Int8", &obj->Int8));
|
||||
oxReturnError(io->field("unionIdx", &obj->unionIdx));
|
||||
if (ox_strcmp(io->opType(), ox::OpType::Reflect) == 0) {
|
||||
if (io->opType() == ox::OpType::Reflect) {
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 0}));
|
||||
} else {
|
||||
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, obj->unionIdx}));
|
||||
|
3
deps/ox/src/ox/oc/write.hpp
vendored
3
deps/ox/src/ox/oc/write.hpp
vendored
@ -176,7 +176,8 @@ class OrganicClawWriter {
|
||||
Error field(const char*, T *val) noexcept;
|
||||
|
||||
template<typename T = void>
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion, int = ModelFieldCount_v<T>) noexcept {
|
||||
constexpr void setTypeInfo(const char* = T::TypeName, int = T::TypeVersion,
|
||||
const Vector<String>& = {}, int = ModelFieldCount_v<T>) noexcept {
|
||||
}
|
||||
|
||||
static constexpr auto opType() noexcept {
|
||||
|
24
deps/ox/src/ox/preloader/CMakeLists.txt
vendored
Normal file
24
deps/ox/src/ox/preloader/CMakeLists.txt
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
add_library(
|
||||
OxPreloader
|
||||
preload.cpp
|
||||
preloader.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
OxPreloader PUBLIC
|
||||
OxClaw
|
||||
OxModel
|
||||
OxStd
|
||||
)
|
||||
|
||||
install(
|
||||
FILES
|
||||
alignmentcatcher.hpp
|
||||
platspecs.hpp
|
||||
preload.hpp
|
||||
preloader.hpp
|
||||
unionsizecatcher.hpp
|
||||
DESTINATION
|
||||
include/nostalgia/preloader
|
||||
)
|
62
deps/ox/src/ox/preloader/alignmentcatcher.hpp
vendored
Normal file
62
deps/ox/src/ox/preloader/alignmentcatcher.hpp
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
#include <ox/model/optype.hpp>
|
||||
#include <ox/model/types.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename PlatSpec, typename T>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t alignOf(const T &t) noexcept;
|
||||
|
||||
template<typename PlatSpec, typename T>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t sizeOf(const T *t) noexcept;
|
||||
|
||||
template<typename PlatSpec>
|
||||
struct AlignmentCatcher: public ModelHandlerBase<AlignmentCatcher<PlatSpec>> {
|
||||
std::size_t biggestAlignment = 1;
|
||||
|
||||
template<typename ...T>
|
||||
constexpr void setTypeInfo(T&&...) const noexcept {
|
||||
}
|
||||
|
||||
template<typename T, bool force>
|
||||
constexpr ox::Error field(CRStringView name, const UnionView<T, force> val) noexcept {
|
||||
return field(name, val.get());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error field(CRStringView, const T *val) noexcept {
|
||||
if constexpr(ox::is_integer_v<T>) {
|
||||
biggestAlignment = ox::max(biggestAlignment, PlatSpec::alignOf(*val));
|
||||
} else {
|
||||
biggestAlignment = ox::max(biggestAlignment, alignOf<PlatSpec>(*val));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error field(CRStringView, const T *val, std::size_t cnt) noexcept {
|
||||
for (std::size_t i = 0; i < cnt; ++i) {
|
||||
oxReturnError(field(nullptr, &val[i]));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return ox::OpType::Reflect;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
126
deps/ox/src/ox/preloader/platspecs.hpp
vendored
Normal file
126
deps/ox/src/ox/preloader/platspecs.hpp
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/serialize.hpp>
|
||||
#include <ox/std/typetraits.hpp>
|
||||
|
||||
#include "alignmentcatcher.hpp"
|
||||
#include "sizecatcher.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
struct NativePlatSpec {
|
||||
using PtrType = uintptr_t;
|
||||
using size_t = std::size_t;
|
||||
|
||||
static constexpr auto PtrAlign = alignof(void*);
|
||||
static constexpr PtrType RomStart = 0x08000000;
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]]
|
||||
static constexpr auto alignOf(const T &v) noexcept {
|
||||
if constexpr(ox::is_integral_v<T>) {
|
||||
return alignof(T);
|
||||
} else if constexpr(ox::is_pointer_v<T>) {
|
||||
return PtrAlign;
|
||||
} else {
|
||||
AlignmentCatcher<NativePlatSpec> c;
|
||||
oxAssert(model(c.interface(), &v), "Could not get alignment for type");
|
||||
return c.biggestAlignment;
|
||||
}
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto correctEndianness(auto v) noexcept {
|
||||
return v;
|
||||
}
|
||||
};
|
||||
|
||||
struct GbaPlatSpec {
|
||||
using PtrType = uint32_t;
|
||||
using size_t = uint32_t;
|
||||
|
||||
static constexpr auto PtrAlign = 4;
|
||||
static constexpr PtrType RomStart = 0x08000000;
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const bool) noexcept {
|
||||
return 1;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const uint8_t) noexcept {
|
||||
return 1;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const uint16_t) noexcept {
|
||||
return 2;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const uint32_t) noexcept {
|
||||
return 4;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const uint64_t) noexcept {
|
||||
return 8;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const int8_t) noexcept {
|
||||
return 1;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const int16_t) noexcept {
|
||||
return 2;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const int32_t) noexcept {
|
||||
return 4;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const int64_t) noexcept {
|
||||
return 8;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(auto*) noexcept {
|
||||
return 4;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const auto*) noexcept {
|
||||
return 4;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr std::size_t alignOf(const auto &v) noexcept {
|
||||
AlignmentCatcher<GbaPlatSpec> c;
|
||||
oxAssert(model(c.interface(), &v), "Could not get alignment for type");
|
||||
return c.biggestAlignment;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto correctEndianness(auto v) noexcept {
|
||||
return ox::toLittleEndian(v);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PlatSpec, typename T>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t alignOf(const T &t) noexcept {
|
||||
return PlatSpec::alignOf(t);
|
||||
}
|
||||
|
||||
template<typename PlatSpec, typename T>
|
||||
constexpr auto alignOf_v = alignOf<PlatSpec>(static_cast<T*>(nullptr));
|
||||
|
||||
}
|
33
deps/ox/src/ox/preloader/preload.cpp
vendored
Normal file
33
deps/ox/src/ox/preloader/preload.cpp
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ox/claw/claw.hpp>
|
||||
|
||||
#include "preload.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
static ox::Error buildPreloadBuffer(ox::Buffer *buff, std::size_t buffStart, ox::FileSystem *fs,
|
||||
ox::TypeStore *ts, const char *path) noexcept {
|
||||
oxRequire(files, fs->ls(path));
|
||||
for (const auto &f : files) {
|
||||
oxRequire(stat, fs->stat(f));
|
||||
if (stat.fileType == ox::FileType::NormalFile) {
|
||||
oxRequire(fileBuff, fs->read(path));
|
||||
oxRequire(obj, ox::readClaw(ts, fileBuff));
|
||||
} else if (stat.fileType == ox::FileType::Directory) {
|
||||
const auto childPath = ox::sfmt("{}/{}", path, f);
|
||||
oxReturnError(buildPreloadBuffer(buff, buffStart, fs, ts, childPath.c_str()));
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Result<ox::Buffer> buildPreloadBuffer(std::size_t buffStart, ox::FileSystem *fs, ox::TypeStore *ts) noexcept {
|
||||
ox::Buffer buff;
|
||||
oxReturnError(buildPreloadBuffer(&buff, buffStart, fs, ts, "/"));
|
||||
return buff;
|
||||
}
|
||||
|
||||
}
|
21
deps/ox/src/ox/preloader/preload.hpp
vendored
Normal file
21
deps/ox/src/ox/preloader/preload.hpp
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/fs/fs.hpp>
|
||||
#include <ox/std/buffer.hpp>
|
||||
|
||||
namespace ox {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param buffStart where the preload buffer will start in ROM
|
||||
* @param fs an ox::FileSystem containing the contents to be preloaded
|
||||
* @return preload buffer or error
|
||||
*/
|
||||
[[maybe_unused]]
|
||||
ox::Result<ox::Buffer> buildPreloadBuffer(std::size_t buffStart, ox::FileSystem *fs) noexcept;
|
||||
|
||||
}
|
33
deps/ox/src/ox/preloader/preloader.cpp
vendored
Normal file
33
deps/ox/src/ox/preloader/preloader.cpp
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <ox/std/error.hpp>
|
||||
|
||||
#include "platspecs.hpp"
|
||||
#include "preloader.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
struct TestType {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.preloader.TestType";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
uint32_t field1 = 0;
|
||||
uint32_t *field2 = nullptr;
|
||||
ox::Vector<uint32_t> field3;
|
||||
};
|
||||
|
||||
oxModelBegin(TestType)
|
||||
oxModelField(field1)
|
||||
oxModelField(field2)
|
||||
oxModelField(field3)
|
||||
oxModelEnd()
|
||||
|
||||
constexpr ox::Error asdf() noexcept {
|
||||
const TestType t;
|
||||
return preload<NativePlatSpec>(&t).error;
|
||||
}
|
||||
|
||||
//static_assert(asdf().errCode == 0);
|
||||
|
||||
}
|
287
deps/ox/src/ox/preloader/preloader.hpp
vendored
Normal file
287
deps/ox/src/ox/preloader/preloader.hpp
vendored
Normal file
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/array.hpp>
|
||||
#include <ox/std/buffer.hpp>
|
||||
#include <ox/std/byteswap.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/memops.hpp>
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
#include <ox/std/typetraits.hpp>
|
||||
#include <ox/std/units.hpp>
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
|
||||
#include "preloader.hpp"
|
||||
#include "platspecs.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename PlatSpec>
|
||||
class Preloader: public ModelHandlerBase<Preloader<PlatSpec>> {
|
||||
private:
|
||||
class UnionIdxTracker {
|
||||
private:
|
||||
int m_unionIdx = -1;
|
||||
int m_it = 0;
|
||||
public:
|
||||
constexpr UnionIdxTracker() noexcept = default;
|
||||
constexpr explicit UnionIdxTracker(int idx) noexcept: m_unionIdx(idx) {}
|
||||
constexpr auto checkAndIterate() noexcept {
|
||||
return m_unionIdx == -1 || m_it++ == m_unionIdx;
|
||||
}
|
||||
};
|
||||
ox::Buffer m_buff;
|
||||
ox::BufferWriter m_writer;
|
||||
// list of all the places where ptrs were written to buffer
|
||||
struct PtrPair {
|
||||
std::size_t loc = 0;
|
||||
typename PlatSpec::PtrType value = 0;
|
||||
constexpr PtrPair() noexcept = default;
|
||||
constexpr PtrPair(std::size_t pLoc, typename PlatSpec::PtrType pValue) noexcept:
|
||||
loc(pLoc), value(pValue) {}
|
||||
};
|
||||
ox::Vector<PtrPair> m_ptrs;
|
||||
ox::Vector<UnionIdxTracker, 8> m_unionIdx = {{}};
|
||||
|
||||
constexpr Preloader() noexcept: m_writer(&m_buff) {}
|
||||
|
||||
Preloader(const Preloader &src) = delete;
|
||||
Preloader(Preloader &&src) = delete;
|
||||
const Preloader &operator=(const Preloader &src) = delete;
|
||||
const Preloader &operator=(Preloader &&src) = delete;
|
||||
|
||||
public:
|
||||
constexpr static ox::Result<ox::UniquePtr<Preloader>> make(ox::ios_base::seekdir anchor = ox::ios_base::cur,
|
||||
std::size_t sz = 0) noexcept;
|
||||
|
||||
constexpr void setTypeInfo(CRStringView, int, const ox::Vector<String>& = {}, int = 0) noexcept {}
|
||||
|
||||
template<typename U, bool force>
|
||||
constexpr ox::Error field(CRStringView, const ox::UnionView<U, force> val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error field(CRStringView, const T *val) noexcept;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr ox::Error field(CRStringView, const ox::BasicString<SmallStringSize> *val) noexcept;
|
||||
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr ox::Error field(CRStringView, const ox::Array<T, sz> *valArray) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error field(CRStringView, const T **val, std::size_t cnt) noexcept;
|
||||
|
||||
constexpr ox::Error offsetPtrs(std::size_t offset) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto &buff() const noexcept {
|
||||
return m_buff;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return ox::OpType::Write;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr ox::Error fieldVector(CRStringView name, const ox::ModelValueVector *val) noexcept;
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr ox::Error fieldVector(CRStringView, const ox::Vector<T, SmallVectorSize, Allocator> *val) noexcept;
|
||||
|
||||
constexpr ox::Error fieldVector(CRStringView, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept;
|
||||
|
||||
constexpr ox::Error pad(const auto *val) noexcept;
|
||||
|
||||
constexpr bool unionCheckAndIt() noexcept;
|
||||
};
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr ox::Result<ox::UniquePtr<Preloader<PlatSpec>>>
|
||||
Preloader<PlatSpec>::make(ox::ios_base::seekdir anchor, std::size_t sz) noexcept {
|
||||
auto p = ox::UniquePtr<Preloader>(new Preloader);
|
||||
if (const auto err = p->m_writer.seekp(0, anchor)) {
|
||||
return {std::move(p), err};
|
||||
}
|
||||
if (const auto err = p->m_writer.write(nullptr, sz)) {
|
||||
return {std::move(p), err};
|
||||
}
|
||||
if (const auto err = p->m_writer.seekp(p->m_writer.tellp() - sz)) {
|
||||
return {std::move(p), err};
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename U, bool force>
|
||||
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const ox::UnionView<U, force> val) noexcept {
|
||||
if (!unionCheckAndIt()) {
|
||||
return {};
|
||||
}
|
||||
oxReturnError(pad(val.get()));
|
||||
m_unionIdx.emplace_back(val.idx());
|
||||
const auto err = model(this->interface(), val.get());
|
||||
m_unionIdx.pop_back();
|
||||
return err;
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T>
|
||||
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView name, const T *val) noexcept {
|
||||
if (!unionCheckAndIt()) {
|
||||
return {};
|
||||
}
|
||||
oxReturnError(pad(val));
|
||||
if constexpr(ox::is_integral_v<T>) {
|
||||
return ox::serialize(&m_writer, PlatSpec::correctEndianness(*val));
|
||||
} else if constexpr(ox::is_pointer_v<T>) {
|
||||
return {};
|
||||
} else if constexpr(ox::isVector_v<T> || ox::is_same_v<T, ox::ModelValueVector>) {
|
||||
return fieldVector(name, val);
|
||||
} else {
|
||||
m_unionIdx.emplace_back(-1);
|
||||
const auto out = model(this->interface(), val);
|
||||
m_unionIdx.pop_back();
|
||||
return out;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const ox::BasicString<SmallStringSize> *val) noexcept {
|
||||
if (!unionCheckAndIt()) {
|
||||
return {};
|
||||
}
|
||||
using VecMap = ox::VectorMemMap<PlatSpec>;
|
||||
const auto sz = val->bytes();
|
||||
oxRequire(a, ox::allocate(&m_writer, sz));
|
||||
const VecMap vecVal{
|
||||
.smallVecSize = SmallStringSize,
|
||||
.size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)),
|
||||
.cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(sz)),
|
||||
.items = sz ? PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(a) + PlatSpec::RomStart) : 0,
|
||||
};
|
||||
oxReturnError(pad(&vecVal));
|
||||
const auto restore = m_writer.tellp();
|
||||
oxReturnError(m_writer.seekp(a));
|
||||
oxReturnError(m_writer.write(val->data(), sz));
|
||||
oxReturnError(m_writer.seekp(restore));
|
||||
oxReturnError(serialize(&m_writer, vecVal));
|
||||
m_ptrs.emplace_back(restore + offsetof(VecMap, items), vecVal.items);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T, std::size_t sz>
|
||||
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView name, const ox::Array<T, sz> *val) noexcept {
|
||||
if (!unionCheckAndIt()) {
|
||||
return {};
|
||||
}
|
||||
// serialize the Array elements
|
||||
if constexpr(sz) {
|
||||
m_unionIdx.emplace_back(-1);
|
||||
for (std::size_t i = 0; i < val->size(); ++i) {
|
||||
oxReturnError(this->interface()->field(name, &(*val)[i]));
|
||||
}
|
||||
m_unionIdx.pop_back();
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T>
|
||||
constexpr ox::Error Preloader<PlatSpec>::field(CRStringView, const T **val, std::size_t cnt) noexcept {
|
||||
if (!unionCheckAndIt()) {
|
||||
return {};
|
||||
}
|
||||
// serialize the array
|
||||
m_unionIdx.emplace_back(-1);
|
||||
for (std::size_t i = 0; i < cnt; ++i) {
|
||||
oxReturnError(this->interface()->field(nullptr, &val[i]));
|
||||
}
|
||||
m_unionIdx.pop_back();
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr ox::Error Preloader<PlatSpec>::offsetPtrs(std::size_t offset) noexcept {
|
||||
for (const auto &p : m_ptrs) {
|
||||
oxReturnError(m_writer.seekp(p.loc));
|
||||
oxReturnError(ox::serialize(&m_writer, PlatSpec::correctEndianness(p.value + offset)));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr ox::Error Preloader<PlatSpec>::fieldVector(CRStringView name, const ox::ModelValueVector *val) noexcept {
|
||||
// serialize the Vector
|
||||
ox::VectorMemMap<PlatSpec> vecVal{
|
||||
.size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(val->size())),
|
||||
.cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(val->size())),
|
||||
};
|
||||
return fieldVector(name, val, vecVal);
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr ox::Error Preloader<PlatSpec>::fieldVector(CRStringView name, const ox::Vector<T, SmallVectorSize, Allocator> *val) noexcept {
|
||||
// serialize the Vector
|
||||
ox::VectorMemMap<PlatSpec> vecVal{
|
||||
.smallVecSize = SmallVectorSize * sizeOf<PlatSpec>(static_cast<T*>(nullptr)),
|
||||
.size = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(val->size())),
|
||||
.cap = PlatSpec::correctEndianness(static_cast<typename PlatSpec::size_t>(val->size())),
|
||||
};
|
||||
return fieldVector(name, val, vecVal);
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr ox::Error Preloader<PlatSpec>::fieldVector(CRStringView, const auto *val, ox::VectorMemMap<PlatSpec> vecVal) noexcept {
|
||||
oxReturnError(pad(&vecVal));
|
||||
const auto vecValPt = m_writer.tellp();
|
||||
// serialize the Vector elements
|
||||
if (val->size()) {
|
||||
const auto sz = sizeOf<PlatSpec>(&(*val)[0]) * val->size();
|
||||
oxRequire(p, ox::allocate(&m_writer, sz));
|
||||
oxReturnError(m_writer.seekp(p));
|
||||
m_unionIdx.emplace_back(-1);
|
||||
for (std::size_t i = 0; i < val->size(); ++i) {
|
||||
oxReturnError(this->interface()->field(nullptr, &val->operator[](i)));
|
||||
}
|
||||
m_unionIdx.pop_back();
|
||||
vecVal.items = PlatSpec::correctEndianness(p + PlatSpec::RomStart);
|
||||
oxReturnError(m_writer.seekp(vecValPt));
|
||||
} else {
|
||||
vecVal.items = 0;
|
||||
}
|
||||
// serialize the Vector
|
||||
oxReturnError(serialize(&m_writer, vecVal));
|
||||
m_ptrs.emplace_back(vecValPt + offsetof(ox::VectorMemMap<PlatSpec>, items), vecVal.items);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr ox::Error Preloader<PlatSpec>::pad(const auto *val) noexcept {
|
||||
constexpr auto a = alignOf_v<PlatSpec, decltype(val)>;
|
||||
const auto padding = a - m_writer.tellp() % a;
|
||||
return m_writer.write(nullptr, padding);
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr bool Preloader<PlatSpec>::unionCheckAndIt() noexcept {
|
||||
auto &u = m_unionIdx.back().unwrap();
|
||||
return u.checkAndIterate();
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr ox::Result<ox::Buffer> preload(const auto *obj) noexcept {
|
||||
using Pl = Preloader<PlatSpec>;
|
||||
oxRequireM(preloader, Pl::make(ox::ios_base::end));
|
||||
oxReturnError(model(preloader->interface(), obj));
|
||||
return preloader->buff();
|
||||
}
|
||||
|
||||
}
|
109
deps/ox/src/ox/preloader/sizecatcher.hpp
vendored
Normal file
109
deps/ox/src/ox/preloader/sizecatcher.hpp
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
#include <ox/model/optype.hpp>
|
||||
#include <ox/model/types.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
|
||||
#include "unionsizecatcher.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename PlatSpec, typename T>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t alignOf(const T &t) noexcept;
|
||||
|
||||
template<typename PlatSpec, typename T>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t sizeOf(const T *t) noexcept;
|
||||
|
||||
template<typename PlatSpec>
|
||||
class SizeCatcher: public ModelHandlerBase<SizeCatcher<PlatSpec>> {
|
||||
private:
|
||||
std::size_t m_size = 0;
|
||||
|
||||
public:
|
||||
constexpr explicit SizeCatcher() noexcept = default;
|
||||
|
||||
template<typename ...T>
|
||||
constexpr void setTypeInfo(T&&...) const noexcept {
|
||||
}
|
||||
|
||||
template<typename T, bool force>
|
||||
constexpr ox::Error field(const char*, UnionView<T, force>) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error field(const char*, const T *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error field(const char*, const T **val, std::size_t cnt) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return ox::OpType::Reflect;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr void pad(const auto *val) noexcept;
|
||||
};
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T, bool force>
|
||||
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const UnionView<T, force> val) noexcept {
|
||||
pad(val.get());
|
||||
UnionSizeCatcher<PlatSpec> sc;
|
||||
oxReturnError(model(sc.interface(), val.get()));
|
||||
m_size += sc.size();
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T>
|
||||
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const T *val) noexcept {
|
||||
pad(val);
|
||||
m_size += sizeOf<PlatSpec>(val);
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T>
|
||||
constexpr ox::Error SizeCatcher<PlatSpec>::field(const char*, const T **val, std::size_t cnt) noexcept {
|
||||
for (std::size_t i = 0; i < cnt; ++i) {
|
||||
oxReturnError(field("", &val[i]));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr void SizeCatcher<PlatSpec>::pad(const auto *val) noexcept {
|
||||
const auto padding = m_size - m_size % alignOf<PlatSpec>(*val);
|
||||
m_size += padding;
|
||||
}
|
||||
|
||||
template<typename PlatSpec, typename T>
|
||||
[[nodiscard]]
|
||||
constexpr std::size_t sizeOf(const T *t) noexcept {
|
||||
if constexpr(ox::is_integral_v<T>) {
|
||||
return sizeof(T);
|
||||
} else if constexpr(ox::is_pointer_v<T>) {
|
||||
return sizeof(PlatSpec::PtrType);
|
||||
} else {
|
||||
SizeCatcher<PlatSpec> sc;
|
||||
const auto err = model(sc.interface(), t);
|
||||
oxAssert(err, "Could not get size of type");
|
||||
return sc.size();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
97
deps/ox/src/ox/preloader/unionsizecatcher.hpp
vendored
Normal file
97
deps/ox/src/ox/preloader/unionsizecatcher.hpp
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2016 - 2022 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/model/modelhandleradaptor.hpp>
|
||||
#include <ox/model/optype.hpp>
|
||||
#include <ox/model/types.hpp>
|
||||
#include <ox/std/error.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
#include <ox/std/types.hpp>
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename PlatSpec>
|
||||
class UnionSizeCatcher: public ModelHandlerBase<UnionSizeCatcher<PlatSpec>> {
|
||||
private:
|
||||
std::size_t m_size = 0;
|
||||
|
||||
public:
|
||||
template<typename ...T>
|
||||
constexpr void setTypeInfo(T&&...) const noexcept {
|
||||
}
|
||||
|
||||
template<typename T, bool force>
|
||||
constexpr ox::Error field(CRStringView, const UnionView<T, force> val) noexcept {
|
||||
UnionSizeCatcher<PlatSpec> sc;
|
||||
oxReturnError(model(sc.interface(), val.get()));
|
||||
m_size += sc.size();
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error field(CRStringView, const T *val) noexcept;
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error field(CRStringView, const T **val, std::size_t cnt) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return ox::OpType::Reflect;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename T, std::size_t SmallVecSize>
|
||||
constexpr ox::Error fieldStr(CRStringView, const ox::BasicString<SmallVecSize> *val) noexcept;
|
||||
|
||||
template<typename T, std::size_t SmallVecSize>
|
||||
constexpr ox::Error fieldVector(CRStringView, const ox::Vector<T, SmallVecSize> *val) noexcept;
|
||||
|
||||
constexpr void setSize(std::size_t sz) noexcept;
|
||||
};
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T>
|
||||
constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(CRStringView, const T *val) noexcept {
|
||||
setSize(sizeOf<PlatSpec>(val));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T>
|
||||
constexpr ox::Error UnionSizeCatcher<PlatSpec>::field(CRStringView, const T **val, std::size_t cnt) noexcept {
|
||||
for (std::size_t i = 0; i < cnt; ++i) {
|
||||
oxReturnError(field("", &val[i]));
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T, std::size_t SmallStrSize>
|
||||
constexpr ox::Error UnionSizeCatcher<PlatSpec>::fieldStr(CRStringView, const ox::BasicString<SmallStrSize>*) noexcept {
|
||||
ox::VectorMemMap<PlatSpec> v;
|
||||
setSize(sizeOf<PlatSpec>(v));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
template<typename T, std::size_t SmallVecSize>
|
||||
constexpr ox::Error UnionSizeCatcher<PlatSpec>::fieldVector(CRStringView, const ox::Vector<T, SmallVecSize>*) noexcept {
|
||||
ox::VectorMemMap<PlatSpec> v;
|
||||
setSize(sizeOf<PlatSpec>(v));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr void UnionSizeCatcher<PlatSpec>::setSize(std::size_t sz) noexcept {
|
||||
m_size = ox::max(m_size, sz);
|
||||
}
|
||||
|
||||
}
|
3
deps/ox/src/ox/std/CMakeLists.txt
vendored
3
deps/ox/src/ox/std/CMakeLists.txt
vendored
@ -90,10 +90,12 @@ install(
|
||||
new.hpp
|
||||
optional.hpp
|
||||
random.hpp
|
||||
serialize.hpp
|
||||
std.hpp
|
||||
stddef.hpp
|
||||
stacktrace.hpp
|
||||
string.hpp
|
||||
stringview.hpp
|
||||
strongint.hpp
|
||||
strops.hpp
|
||||
trace.hpp
|
||||
@ -102,6 +104,7 @@ install(
|
||||
typetraits.hpp
|
||||
units.hpp
|
||||
vector.hpp
|
||||
writer.hpp
|
||||
DESTINATION
|
||||
include/ox/std
|
||||
)
|
||||
|
10
deps/ox/src/ox/std/algorithm.hpp
vendored
10
deps/ox/src/ox/std/algorithm.hpp
vendored
@ -30,4 +30,14 @@ constexpr It find_if(It begin, It end, auto predicate) {
|
||||
return end;
|
||||
}
|
||||
|
||||
template<typename It, typename Size, typename OutIt>
|
||||
constexpr OutIt copy_n(It in, Size cnt, OutIt out) {
|
||||
for (Size i = 0; i < cnt; ++i) {
|
||||
*out = *in;
|
||||
++out;
|
||||
++in;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
20
deps/ox/src/ox/std/assert.hpp
vendored
20
deps/ox/src/ox/std/assert.hpp
vendored
@ -51,7 +51,7 @@ constexpr void assertFunc(const char *file, int line, bool pass, [[maybe_unused]
|
||||
|
||||
constexpr void assertFunc(const char *file, int line, const Error &err, const char*, const char *assertMsg) noexcept {
|
||||
if (err) {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
#if defined(OX_USE_STDLIB)
|
||||
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, assertMsg);
|
||||
if (err.msg) {
|
||||
@ -73,4 +73,22 @@ constexpr void assertFunc(const char *file, int line, const Error &err, const ch
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void expect(const char *file, int line, const auto &actual, const auto &expected) noexcept {
|
||||
if (actual != expected) {
|
||||
if (!std::is_constant_evaluated()) {
|
||||
#if defined(OX_USE_STDLIB)
|
||||
oxErrf("\n\033[31;1;1mASSERT FAILURE:\033[0m [{}:{}]: {}\n", file, line, "Value incorrect");
|
||||
oxErrf("expected: {}, actual: {}\n", detail::toStringView<true>(expected), detail::toStringView<true>(actual));
|
||||
printStackTrace(2);
|
||||
oxTracef("assert::expect", "Failed assert: {} == {} [{}:{}]", detail::toStringView<true>(actual), detail::toStringView<true>(expected), file, line);
|
||||
std::abort();
|
||||
#else
|
||||
constexprPanic(file, line, "Comparison failed");
|
||||
#endif
|
||||
} else {
|
||||
while (true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
3
deps/ox/src/ox/std/bit.hpp
vendored
3
deps/ox/src/ox/std/bit.hpp
vendored
@ -21,7 +21,8 @@
|
||||
namespace std {
|
||||
|
||||
template<typename To, typename From>
|
||||
constexpr typename ox::enable_if<sizeof(To) == sizeof(From), To>::type bit_cast(const From &src) noexcept {
|
||||
[[nodiscard]]
|
||||
constexpr To bit_cast(const From &src) noexcept requires(sizeof(To) == sizeof(From)) {
|
||||
return __builtin_bit_cast(To, src);
|
||||
}
|
||||
|
||||
|
16
deps/ox/src/ox/std/bstring.hpp
vendored
16
deps/ox/src/ox/std/bstring.hpp
vendored
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "memops.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "typetraits.hpp"
|
||||
|
||||
@ -23,6 +24,8 @@ class BString {
|
||||
public:
|
||||
constexpr BString() noexcept;
|
||||
|
||||
constexpr BString(StringView str) noexcept;
|
||||
|
||||
constexpr BString(const char *str) noexcept;
|
||||
|
||||
constexpr BString &operator=(const char *str) noexcept;
|
||||
@ -37,6 +40,8 @@ class BString {
|
||||
|
||||
constexpr BString &operator+=(Integer_c auto i) noexcept;
|
||||
|
||||
constexpr BString &operator+=(StringView s) noexcept;
|
||||
|
||||
constexpr BString operator+(const char *str) const noexcept;
|
||||
|
||||
constexpr BString operator+(char *str) const noexcept;
|
||||
@ -81,6 +86,11 @@ template<std::size_t size>
|
||||
constexpr BString<size>::BString() noexcept: m_buff{{0}} {
|
||||
}
|
||||
|
||||
template<std::size_t size>
|
||||
constexpr BString<size>::BString(StringView str) noexcept: m_buff{{0}} {
|
||||
*this = str;
|
||||
}
|
||||
|
||||
template<std::size_t size>
|
||||
constexpr BString<size>::BString(const char *str) noexcept: m_buff{{0}} {
|
||||
*this = str;
|
||||
@ -129,6 +139,12 @@ constexpr BString<size> &BString<size>::operator+=(Integer_c auto i) noexcept {
|
||||
return this->operator+=(str);
|
||||
}
|
||||
|
||||
template<std::size_t size>
|
||||
constexpr BString<size> &BString<size>::operator+=(StringView s) noexcept {
|
||||
std::size_t strLen = s.bytes();
|
||||
oxIgnoreError(append(s.data(), strLen));
|
||||
}
|
||||
|
||||
template<std::size_t size>
|
||||
constexpr BString<size> BString<size>::operator+(const char *str) const noexcept {
|
||||
auto out = *this;
|
||||
|
3
deps/ox/src/ox/std/buffer.cpp
vendored
3
deps/ox/src/ox/std/buffer.cpp
vendored
@ -13,4 +13,7 @@ namespace ox {
|
||||
|
||||
template class Vector<char>;
|
||||
|
||||
template class WriterT<BufferWriter>;
|
||||
template class WriterT<CharBuffWriter>;
|
||||
|
||||
}
|
||||
|
152
deps/ox/src/ox/std/buffer.hpp
vendored
152
deps/ox/src/ox/std/buffer.hpp
vendored
@ -10,6 +10,7 @@
|
||||
|
||||
#include "error.hpp"
|
||||
#include "vector.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -17,4 +18,155 @@ extern template class Vector<char>;
|
||||
|
||||
using Buffer = Vector<char>;
|
||||
|
||||
class BufferWriter {
|
||||
private:
|
||||
std::size_t m_it = 0;
|
||||
ox::Buffer &m_buff;
|
||||
|
||||
public:
|
||||
explicit constexpr BufferWriter(Buffer *buff) noexcept: m_it(buff->size()), m_buff(*buff) {
|
||||
}
|
||||
|
||||
explicit constexpr BufferWriter(Buffer *buff, std::size_t it) noexcept: m_it(it), m_buff(*buff) {
|
||||
}
|
||||
|
||||
constexpr ox::Error seekp(std::size_t p) noexcept {
|
||||
m_it = p;
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ox::Error seekp(ox::Signed<std::size_t> off, ox::ios_base::seekdir dir) noexcept {
|
||||
ox::Signed<std::size_t> base = 0;
|
||||
switch (dir) {
|
||||
case ox::ios_base::beg:
|
||||
base = 0;
|
||||
break;
|
||||
case ox::ios_base::end:
|
||||
base = static_cast<ox::Signed<std::size_t>>(m_buff.size());
|
||||
break;
|
||||
case ox::ios_base::cur:
|
||||
base = static_cast<ox::Signed<std::size_t>>(m_it);
|
||||
break;
|
||||
default:
|
||||
return OxError(1, "Invalid seekdir");
|
||||
}
|
||||
m_it = static_cast<std::size_t>(base + off);
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto tellp() const noexcept {
|
||||
return m_it;
|
||||
}
|
||||
|
||||
constexpr ox::Error put(char val) noexcept {
|
||||
if (m_it >= m_buff.size()) [[unlikely]] {
|
||||
m_buff.resize(m_buff.size() + 1);
|
||||
}
|
||||
m_buff[m_it] = val;
|
||||
++m_it;
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ox::Error write(const char *inBuff, std::size_t cnt) noexcept {
|
||||
const auto end = m_it + cnt;
|
||||
if (end >= m_buff.size()) {
|
||||
m_buff.resize(end);
|
||||
}
|
||||
if (inBuff) {
|
||||
const auto buff = m_buff.data() + m_it;
|
||||
for (auto i = 0u; i < cnt; ++i) {
|
||||
buff[i] = inBuff[i];
|
||||
}
|
||||
}
|
||||
m_it += cnt;
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto data() const noexcept {
|
||||
return &m_buff;
|
||||
}
|
||||
};
|
||||
|
||||
class CharBuffWriter {
|
||||
private:
|
||||
std::size_t m_it = 0;
|
||||
std::size_t m_cap = 0;
|
||||
std::size_t m_size = 0;
|
||||
char *m_buff = nullptr;
|
||||
|
||||
public:
|
||||
template<std::size_t sz>
|
||||
explicit constexpr CharBuffWriter(ox::Array<char, sz> *buff) noexcept:
|
||||
m_cap(buff->size()),
|
||||
m_buff(buff->data()) {
|
||||
}
|
||||
|
||||
explicit constexpr CharBuffWriter(char *buff, std::size_t size) noexcept: m_cap(size), m_buff(buff) {
|
||||
}
|
||||
|
||||
constexpr ox::Error seekp(std::size_t p) noexcept {
|
||||
m_it = p;
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ox::Error seekp(ox::Signed<std::size_t> off, ox::ios_base::seekdir dir) noexcept {
|
||||
ox::Signed<std::size_t> base = 0;
|
||||
switch (dir) {
|
||||
case ox::ios_base::beg:
|
||||
base = 0;
|
||||
break;
|
||||
case ox::ios_base::end:
|
||||
base = static_cast<ox::Signed<std::size_t>>(m_size);
|
||||
break;
|
||||
case ox::ios_base::cur:
|
||||
base = static_cast<ox::Signed<std::size_t>>(m_it);
|
||||
break;
|
||||
default:
|
||||
return OxError(1, "Invalid seekdir");
|
||||
}
|
||||
m_it = static_cast<std::size_t>(base + off);
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto tellp() const noexcept {
|
||||
return m_it;
|
||||
}
|
||||
|
||||
constexpr ox::Error put(char val) noexcept {
|
||||
if (m_it >= m_cap) [[unlikely]] {
|
||||
return OxError(1, "Buffer overrun");
|
||||
}
|
||||
m_buff[m_it] = val;
|
||||
++m_it;
|
||||
m_size = ox::max(m_it, m_size);
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ox::Error write(const char *buff, std::size_t cnt) noexcept {
|
||||
const auto end = m_it + cnt;
|
||||
if (end > m_cap) [[unlikely]] {
|
||||
return OxError(1, "Buffer overrun");
|
||||
}
|
||||
if (buff) {
|
||||
for (auto i = 0u; i < cnt; ++i) {
|
||||
m_buff[m_it + i] = buff[i];
|
||||
}
|
||||
}
|
||||
m_it += cnt;
|
||||
m_size = ox::max(m_it, m_size);
|
||||
return {};
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr auto data() const noexcept {
|
||||
return m_buff;
|
||||
}
|
||||
};
|
||||
|
||||
extern template class WriterT<BufferWriter>;
|
||||
extern template class WriterT<CharBuffWriter>;
|
||||
|
||||
}
|
||||
|
36
deps/ox/src/ox/std/concepts.hpp
vendored
36
deps/ox/src/ox/std/concepts.hpp
vendored
@ -11,7 +11,43 @@
|
||||
#include "typetraits.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename T, typename U>
|
||||
concept CommonPtrWith = ox::is_same_v<typename ox::remove_pointer<const T*>::type,
|
||||
typename ox::remove_pointer<const U*>::type>;
|
||||
|
||||
template<typename T, typename U>
|
||||
concept same_as = ox::is_same_v<T, T>;
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
class BasicString;
|
||||
template<std::size_t sz>
|
||||
class BString;
|
||||
class StringView;
|
||||
|
||||
namespace detail {
|
||||
|
||||
constexpr auto isOxString(const auto*) noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr auto isOxString(const BasicString<sz>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr auto isOxString(const BString<sz>*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
constexpr auto isOxString(const StringView*) noexcept {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
concept OxString_c = detail::isOxString(static_cast<T*>(nullptr));
|
||||
|
||||
}
|
1
deps/ox/src/ox/std/def.hpp
vendored
1
deps/ox/src/ox/std/def.hpp
vendored
@ -75,6 +75,7 @@ constexpr void oxAssert(bool, const char*) noexcept {}
|
||||
constexpr void oxAssert(const ox::Error&, const char*) noexcept {}
|
||||
#endif
|
||||
|
||||
#define oxExpect(actual, expected) ox::expect(__FILE__, __LINE__, actual, expected)
|
||||
|
||||
// Alloca
|
||||
|
||||
|
15
deps/ox/src/ox/std/error.hpp
vendored
15
deps/ox/src/ox/std/error.hpp
vendored
@ -122,6 +122,8 @@ struct Exception: public std::exception {
|
||||
}
|
||||
};
|
||||
|
||||
void panic(const char *file, int line, const char *panicMsg, const Error &err) noexcept;
|
||||
|
||||
template<typename T>
|
||||
struct [[nodiscard]] Result {
|
||||
|
||||
@ -182,6 +184,19 @@ struct [[nodiscard]] Result {
|
||||
return error;
|
||||
}
|
||||
|
||||
constexpr auto &unwrap() noexcept {
|
||||
if (error) {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
constexpr const auto &unwrap() const noexcept {
|
||||
if (error) [[unlikely]] {
|
||||
oxPanic(error, "Failed unwrap");
|
||||
}
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
69
deps/ox/src/ox/std/fmt.hpp
vendored
69
deps/ox/src/ox/std/fmt.hpp
vendored
@ -27,60 +27,77 @@
|
||||
namespace ox {
|
||||
namespace detail {
|
||||
|
||||
constexpr const char *toCString(const char *s) noexcept {
|
||||
template<bool force = false>
|
||||
constexpr StringView toStringView(const StringView &s) noexcept {
|
||||
return s;
|
||||
}
|
||||
|
||||
template<std::size_t size>
|
||||
constexpr const char *toCString(const BString<size> &s) noexcept {
|
||||
template<bool force = false>
|
||||
constexpr StringView toStringView(const char *s) noexcept {
|
||||
return s;
|
||||
}
|
||||
|
||||
template<bool force = false, std::size_t size>
|
||||
constexpr StringView toStringView(const BString<size> &s) noexcept {
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
template<std::size_t size>
|
||||
constexpr const char *toCString(const BasicString<size> &s) noexcept {
|
||||
template<bool force = false, std::size_t size>
|
||||
constexpr StringView toStringView(const BasicString<size> &s) noexcept {
|
||||
return s.c_str();
|
||||
}
|
||||
|
||||
#if __has_include(<string>)
|
||||
template<bool force = false>
|
||||
#ifdef OX_OS_Darwin
|
||||
constexpr
|
||||
#else
|
||||
inline
|
||||
#endif
|
||||
const char *toCString(const std::string &s) noexcept {
|
||||
StringView toStringView(const std::string &s) noexcept {
|
||||
return s.c_str();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if __has_include(<QString>)
|
||||
inline const char *toCString(const QString &s) noexcept {
|
||||
template<bool force = false>
|
||||
inline StringView toStringView(const QString &s) noexcept {
|
||||
return s.toUtf8();
|
||||
}
|
||||
#endif
|
||||
|
||||
template<bool force = false>
|
||||
constexpr StringView toStringView(const auto&) noexcept requires(force) {
|
||||
return "<unstringable>";
|
||||
}
|
||||
|
||||
class FmtArg {
|
||||
|
||||
private:
|
||||
char dataStr[10] = {};
|
||||
|
||||
template<typename T>
|
||||
static StringView sv(const T &v, char *dataStr) noexcept {
|
||||
if constexpr(is_bool_v<T>) {
|
||||
return v ? "true" : "false";
|
||||
} else if constexpr(is_integer_v<T>) {
|
||||
return ox_itoa(v, dataStr);
|
||||
} else {
|
||||
return toStringView(v);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
const char *out = nullptr;
|
||||
const StringView out = nullptr;
|
||||
|
||||
template<typename T>
|
||||
constexpr FmtArg(const T &v) noexcept {
|
||||
if constexpr(is_bool_v<T>) {
|
||||
out = v ? "true" : "false";
|
||||
} else if constexpr(is_integer_v<T>) {
|
||||
out = ox_itoa(v, dataStr);
|
||||
} else {
|
||||
out = toCString(v);
|
||||
}
|
||||
constexpr FmtArg(const T &v) noexcept: out(sv(v, dataStr)) {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr uint64_t argCount(const char *str) noexcept {
|
||||
constexpr uint64_t argCount(StringView str) noexcept {
|
||||
uint64_t cnt = 0;
|
||||
const auto prev = [str](std::size_t i) -> char {
|
||||
if (i > 0) {
|
||||
@ -90,13 +107,13 @@ constexpr uint64_t argCount(const char *str) noexcept {
|
||||
}
|
||||
};
|
||||
const auto next = [str](std::size_t i) -> char {
|
||||
if (i < ox_strlen(str) - 1) {
|
||||
if (i < str.bytes() - 1) {
|
||||
return str[i + 1];
|
||||
} else {
|
||||
return '\0';
|
||||
}
|
||||
};
|
||||
for (std::size_t i = 0; i < ox_strlen(str); ++i) {
|
||||
for (std::size_t i = 0; i < str.bytes(); ++i) {
|
||||
if (str[i] == '{' && prev(i) != '\\' && next(i) == '}') {
|
||||
++cnt;
|
||||
}
|
||||
@ -120,7 +137,7 @@ struct FmtSegment {
|
||||
template<std::size_t sz>
|
||||
struct Fmt {
|
||||
static constexpr std::size_t size = sz;
|
||||
FmtSegment segments[sz];
|
||||
ox::Array<FmtSegment, sz> segments;
|
||||
|
||||
constexpr bool operator==(const Fmt<sz> &o) const noexcept {
|
||||
for (std::size_t i = 0; i < sz; ++i) {
|
||||
@ -134,7 +151,7 @@ struct Fmt {
|
||||
|
||||
template<std::size_t segementCnt>
|
||||
[[nodiscard]]
|
||||
constexpr Fmt<segementCnt> fmtSegments(const char *fmt) noexcept {
|
||||
constexpr Fmt<segementCnt> fmtSegments(StringView fmt) noexcept {
|
||||
Fmt<segementCnt> out;
|
||||
const auto prev = [fmt](std::size_t i) -> char {
|
||||
if (i > 0) {
|
||||
@ -144,18 +161,18 @@ constexpr Fmt<segementCnt> fmtSegments(const char *fmt) noexcept {
|
||||
}
|
||||
};
|
||||
const auto next = [fmt](std::size_t i) -> char {
|
||||
if (i < ox_strlen(fmt) - 1) {
|
||||
if (i < fmt.bytes() - 1) {
|
||||
return fmt[i + 1];
|
||||
} else {
|
||||
return '\0';
|
||||
}
|
||||
};
|
||||
auto current = &out.segments[0];
|
||||
current->str = fmt;
|
||||
for (std::size_t i = 0; i < ox_strlen(fmt); ++i) {
|
||||
current->str = fmt.data();
|
||||
for (std::size_t i = 0; i < fmt.bytes(); ++i) {
|
||||
if (fmt[i] == '{' && prev(i) != '\\' && next(i) == '}') {
|
||||
++current;
|
||||
current->str = fmt + i + 2;
|
||||
current->str = fmt.data() + i + 2;
|
||||
current->length = 0;
|
||||
i += 1;
|
||||
} else {
|
||||
@ -169,7 +186,7 @@ constexpr Fmt<segementCnt> fmtSegments(const char *fmt) noexcept {
|
||||
|
||||
template<typename StringType = String, typename ...Args>
|
||||
[[nodiscard]]
|
||||
constexpr StringType sfmt(const char *fmt, Args... args) noexcept {
|
||||
constexpr StringType sfmt(StringView fmt, Args... args) noexcept {
|
||||
assert(ox::detail::argCount(fmt) == sizeof...(args));
|
||||
StringType out;
|
||||
const auto fmtSegments = ox::detail::fmtSegments<sizeof...(args)+1>(fmt);
|
||||
|
6
deps/ox/src/ox/std/memops.hpp
vendored
6
deps/ox/src/ox/std/memops.hpp
vendored
@ -30,8 +30,8 @@ int ox_memcmp(const void *ptr1, const void *ptr2, std::size_t size) noexcept;
|
||||
|
||||
constexpr void *ox_memcpy(void *dest, const void *src, std::size_t size) noexcept {
|
||||
if (std::is_constant_evaluated() || !ox::defines::UseStdLib) {
|
||||
auto srcBuf = static_cast<const char *>(src);
|
||||
auto dstBuf = static_cast<char *>(dest);
|
||||
auto srcBuf = static_cast<const char*>(src);
|
||||
auto dstBuf = static_cast<char*>(dest);
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
dstBuf[i] = static_cast<char>(srcBuf[i]);
|
||||
}
|
||||
@ -56,7 +56,7 @@ constexpr void *ox_memmove(void *dest, const void *src, std::size_t size) noexce
|
||||
|
||||
constexpr void *ox_memset(void *ptr, int val, std::size_t size) noexcept {
|
||||
if (std::is_constant_evaluated() || !ox::defines::UseStdLib) {
|
||||
auto buf = static_cast<uint8_t *>(ptr);
|
||||
auto buf = static_cast<uint8_t*>(ptr);
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
buf[i] = static_cast<uint8_t>(val);
|
||||
}
|
||||
|
2
deps/ox/src/ox/std/memory.hpp
vendored
2
deps/ox/src/ox/std/memory.hpp
vendored
@ -282,7 +282,7 @@ constexpr bool operator!=(std::nullptr_t, const UniquePtr<T> &p2) noexcept {
|
||||
template<typename T, typename ...Args>
|
||||
[[nodiscard]]
|
||||
constexpr auto make_unique(Args&&... args) {
|
||||
return UniquePtr(new T(forward<Args>(args)...));
|
||||
return UniquePtr(new T(ox::forward<Args>(args)...));
|
||||
}
|
||||
|
||||
}
|
||||
|
25
deps/ox/src/ox/std/range.hpp
vendored
Normal file
25
deps/ox/src/ox/std/range.hpp
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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 http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename T>
|
||||
class range {
|
||||
|
||||
private:
|
||||
T m_begin = 0;
|
||||
T m_end = 0;
|
||||
|
||||
public:
|
||||
constexpr range(T begin, T end) noexcept: m_begin(begin), m_end(end) {
|
||||
}
|
||||
};
|
||||
|
||||
}
|
81
deps/ox/src/ox/std/serialize.hpp
vendored
Normal file
81
deps/ox/src/ox/std/serialize.hpp
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "array.hpp"
|
||||
#include "buffer.hpp"
|
||||
#include "types.hpp"
|
||||
#include "typetraits.hpp"
|
||||
#include "writer.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename PlatSpec>
|
||||
struct VectorMemMap {
|
||||
const std::size_t smallVecSize = 0; // not a map value
|
||||
uint8_t allocator = 0;
|
||||
typename PlatSpec::size_t size = 0;
|
||||
typename PlatSpec::size_t cap = 0;
|
||||
typename PlatSpec::PtrType items = 0;
|
||||
};
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr auto sizeOf(const VectorMemMap<PlatSpec> *t) noexcept {
|
||||
constexpr auto padding = [](std::size_t size, std::size_t al) {
|
||||
return size % al;
|
||||
};
|
||||
std::size_t size = 0;
|
||||
if (t->smallVecSize) {
|
||||
size += t->smallVecSize;
|
||||
size += padding(size, PlatSpec::alignOf(t->size));
|
||||
}
|
||||
size += sizeof(t->size);
|
||||
size += padding(size, PlatSpec::alignOf(t->cap));
|
||||
size += sizeof(t->cap);
|
||||
size += padding(size, PlatSpec::alignOf(t->items));
|
||||
size += sizeof(t->items);
|
||||
return size;
|
||||
}
|
||||
|
||||
template<typename PlatSpec, std::size_t SmallVecSize = 0>
|
||||
[[nodiscard]]
|
||||
constexpr auto alignOf(const VectorMemMap<PlatSpec>&) noexcept {
|
||||
const typename PlatSpec::size_t i = 0;
|
||||
return PlatSpec::alignOf(i);
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
constexpr ox::Error serialize(Writer_c auto *buff, const VectorMemMap<PlatSpec> &vm) noexcept {
|
||||
oxReturnError(buff->write(nullptr, vm.smallVecSize));
|
||||
oxReturnError(serialize(buff, PlatSpec::correctEndianness(vm.allocator)));
|
||||
oxReturnError(serialize(buff, PlatSpec::correctEndianness(vm.size)));
|
||||
oxReturnError(serialize(buff, PlatSpec::correctEndianness(vm.cap)));
|
||||
oxReturnError(serialize(buff, PlatSpec::correctEndianness(vm.items)));
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error serialize(Writer_c auto *buff, T val) noexcept requires(is_integer_v<T>) {
|
||||
ox::Array<char, sizeof(T)> tmp;
|
||||
for (auto i = 0u; i < sizeof(T); ++i) {
|
||||
tmp[i] = static_cast<char>((val >> i * 8) & 255);
|
||||
}
|
||||
return buff->write(tmp.data(), tmp.size());
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Result<ox::Array<char, sizeof(T)>> serialize(const T &in) noexcept {
|
||||
ox::Array<char, sizeof(T)> out = {};
|
||||
CharBuffWriter w(&out);
|
||||
oxReturnError(serialize(&w, in));
|
||||
return out;
|
||||
};
|
||||
|
||||
}
|
2
deps/ox/src/ox/std/std.hpp
vendored
2
deps/ox/src/ox/std/std.hpp
vendored
@ -30,9 +30,11 @@
|
||||
#include "optional.hpp"
|
||||
#include "random.hpp"
|
||||
#include "realstd.hpp"
|
||||
#include "serialize.hpp"
|
||||
#include "stacktrace.hpp"
|
||||
#include "stddef.hpp"
|
||||
#include "string.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "strongint.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "trace.hpp"
|
||||
|
5
deps/ox/src/ox/std/string.cpp
vendored
5
deps/ox/src/ox/std/string.cpp
vendored
@ -12,4 +12,9 @@ namespace ox {
|
||||
|
||||
template class BasicString<8>;
|
||||
|
||||
static_assert(StringView("Write") != String(""));
|
||||
static_assert(String("Write") != StringView(""));
|
||||
static_assert(String("Write") == StringView("Write"));
|
||||
static_assert(String(StringView("Write")) == StringView("Write"));
|
||||
|
||||
}
|
||||
|
256
deps/ox/src/ox/std/string.hpp
vendored
256
deps/ox/src/ox/std/string.hpp
vendored
@ -12,20 +12,24 @@
|
||||
#include <string>
|
||||
#endif
|
||||
|
||||
#include "algorithm.hpp"
|
||||
#include "buffer.hpp"
|
||||
#include "memops.hpp"
|
||||
#include "serialize.hpp"
|
||||
#include "stringview.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "typetraits.hpp"
|
||||
#include "vector.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
template<std::size_t SmallStringSize_v>
|
||||
class BasicString {
|
||||
private:
|
||||
Vector<char, SmallStringSize> m_buff;
|
||||
Vector<char, SmallStringSize_v> m_buff;
|
||||
|
||||
public:
|
||||
static constexpr auto SmallStringSize = SmallStringSize_v;
|
||||
constexpr BasicString() noexcept;
|
||||
|
||||
constexpr explicit BasicString(std::size_t cap) noexcept;
|
||||
@ -36,6 +40,8 @@ class BasicString {
|
||||
|
||||
constexpr BasicString(const char *str, std::size_t size) noexcept;
|
||||
|
||||
constexpr BasicString(CRStringView str) noexcept;
|
||||
|
||||
constexpr BasicString(const BasicString&) noexcept;
|
||||
|
||||
constexpr BasicString(BasicString&&) noexcept;
|
||||
@ -122,6 +128,8 @@ class BasicString {
|
||||
|
||||
constexpr BasicString &operator+=(Integer_c auto i) noexcept;
|
||||
|
||||
constexpr BasicString &operator+=(StringView src) noexcept;
|
||||
|
||||
constexpr BasicString &operator+=(const BasicString &src) noexcept;
|
||||
|
||||
constexpr BasicString operator+(const char *str) const noexcept;
|
||||
@ -136,11 +144,11 @@ class BasicString {
|
||||
|
||||
constexpr bool operator==(const char *other) const noexcept;
|
||||
|
||||
constexpr bool operator==(const BasicString &other) const noexcept;
|
||||
constexpr bool operator==(const OxString_c auto &other) const noexcept;
|
||||
|
||||
constexpr bool operator!=(const char *other) const noexcept;
|
||||
|
||||
constexpr bool operator!=(const BasicString &other) const noexcept;
|
||||
constexpr bool operator!=(const OxString_c auto &other) const noexcept;
|
||||
|
||||
constexpr bool operator<(const BasicString &other) const noexcept;
|
||||
|
||||
@ -230,13 +238,15 @@ class BasicString {
|
||||
template<std::size_t OtherSize>
|
||||
constexpr void set(const BasicString<OtherSize> &src) noexcept;
|
||||
|
||||
constexpr void set(StringView str) noexcept;
|
||||
|
||||
constexpr void set(const char *str) noexcept;
|
||||
|
||||
constexpr void set(const char8_t *str) noexcept;
|
||||
};
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize>::BasicString() noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString() noexcept {
|
||||
if (m_buff.size()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
@ -244,16 +254,16 @@ constexpr BasicString<SmallStringSize>::BasicString() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize>::BasicString(std::size_t cap) noexcept: m_buff(cap + 1) {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(std::size_t cap) noexcept: m_buff(cap + 1) {
|
||||
// GCC complains if you don't do this pretty unnecessary size check
|
||||
if (m_buff.size()) {
|
||||
m_buff[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize>::BasicString(const char *str) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(const char *str) noexcept {
|
||||
if (m_buff.size()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
@ -262,8 +272,8 @@ constexpr BasicString<SmallStringSize>::BasicString(const char *str) noexcept {
|
||||
set(str);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize>::BasicString(const char8_t *str) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(const char8_t *str) noexcept {
|
||||
if (m_buff.size()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
@ -272,105 +282,122 @@ constexpr BasicString<SmallStringSize>::BasicString(const char8_t *str) noexcept
|
||||
set(str);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize>::BasicString(const char *str, std::size_t size) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(const char *str, std::size_t size) noexcept {
|
||||
m_buff.resize(size + 1);
|
||||
memcpy(m_buff.data(), str, size);
|
||||
m_buff[size] = 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize>::BasicString(const BasicString &other) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(CRStringView str) noexcept {
|
||||
if (m_buff.size()) {
|
||||
m_buff[0] = 0;
|
||||
} else {
|
||||
m_buff.push_back(0);
|
||||
}
|
||||
set(str);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(const BasicString &other) noexcept {
|
||||
m_buff = other.m_buff;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize>::BasicString(BasicString &&other) noexcept: m_buff(std::move(other.m_buff)) {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v>::BasicString(BasicString &&other) noexcept: m_buff(std::move(other.m_buff)) {
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(const char *str) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(const char *str) noexcept {
|
||||
set(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(char c) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(char c) noexcept {
|
||||
char str[] = {c, 0};
|
||||
set(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(int i) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(int i) noexcept {
|
||||
this->operator=(static_cast<int64_t>(i));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(int64_t i) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(int64_t i) noexcept {
|
||||
char str[65] = {};
|
||||
ox_itoa(i, str);
|
||||
set(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(uint64_t i) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(uint64_t i) noexcept {
|
||||
char str[65] = {};
|
||||
ox_itoa(i, str);
|
||||
set(str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(const BasicString &src) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(const BasicString &src) noexcept {
|
||||
set(src);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator=(BasicString &&src) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator=(BasicString &&src) noexcept {
|
||||
m_buff = std::move(src.m_buff);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(const char *str) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(const char *str) noexcept {
|
||||
std::size_t strLen = ox_strlen(str);
|
||||
oxIgnoreError(append(str, strLen));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(char *str) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(char *str) noexcept {
|
||||
return *this += static_cast<const char*>(str);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(char c) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(char c) noexcept {
|
||||
const char str[] = {c, 0};
|
||||
return this->operator+=(str);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(Integer_c auto i) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(Integer_c auto i) noexcept {
|
||||
char str[65] = {};
|
||||
ox_itoa(i, str);
|
||||
return this->operator+=(str);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> &BasicString<SmallStringSize>::operator+=(const BasicString &src) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(StringView s) noexcept {
|
||||
std::size_t strLen = s.bytes();
|
||||
oxIgnoreError(append(s.data(), strLen));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> &BasicString<SmallStringSize_v>::operator+=(const BasicString &src) noexcept {
|
||||
oxIgnoreError(append(src.c_str(), src.len()));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(const char *str) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(const char *str) const noexcept {
|
||||
const std::size_t strLen = ox_strlen(str);
|
||||
const auto currentLen = len();
|
||||
BasicString<SmallStringSize> cpy(currentLen + strLen);
|
||||
BasicString<SmallStringSize_v> cpy(currentLen + strLen);
|
||||
cpy.m_buff.resize(m_buff.size() + strLen);
|
||||
memcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
|
||||
memcpy(&cpy.m_buff[currentLen], str, strLen);
|
||||
@ -379,37 +406,37 @@ constexpr BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(c
|
||||
return cpy;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(char *str) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(char *str) const noexcept {
|
||||
return *this + static_cast<const char*>(str);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(char c) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(char c) const noexcept {
|
||||
const char str[] = {c, 0};
|
||||
return *this + str;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(Integer_c auto i) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(Integer_c auto i) const noexcept {
|
||||
char str[65] = {};
|
||||
ox_itoa(i, str);
|
||||
return *this + str;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> BasicString<SmallStringSize>::operator+(const BasicString &src) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::operator+(const BasicString &src) const noexcept {
|
||||
const std::size_t strLen = src.len();
|
||||
const auto currentLen = len();
|
||||
BasicString<SmallStringSize> cpy(currentLen + strLen);
|
||||
BasicString<SmallStringSize_v> cpy(currentLen + strLen);
|
||||
cpy.m_buff.resize(m_buff.size() + strLen);
|
||||
memcpy(&cpy.m_buff[0], m_buff.data(), currentLen);
|
||||
memcpy(&cpy.m_buff[currentLen], src.data(), strLen + 1);
|
||||
return cpy;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator==(const char *other) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator==(const char *other) const noexcept {
|
||||
bool retval = true;
|
||||
for (auto i = 0u; i < m_buff.size() && (m_buff[i] || other[i]); ++i) {
|
||||
if (m_buff[i] != other[i]) {
|
||||
@ -420,15 +447,15 @@ constexpr bool BasicString<SmallStringSize>::operator==(const char *other) const
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator==(const BasicString &other) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator==(const OxString_c auto &other) const noexcept {
|
||||
if (len() != other.len()) {
|
||||
return false;
|
||||
}
|
||||
bool retval = true;
|
||||
std::size_t i = 0;
|
||||
while (i < m_buff.size() && (m_buff[i] || other.m_buff[i])) {
|
||||
if (m_buff[i] != other.m_buff[i]) {
|
||||
while (i < m_buff.size() && (m_buff[i] || other[i])) {
|
||||
if (m_buff[i] != other[i]) {
|
||||
retval = false;
|
||||
break;
|
||||
}
|
||||
@ -437,95 +464,95 @@ constexpr bool BasicString<SmallStringSize>::operator==(const BasicString &other
|
||||
return retval;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator!=(const char *other) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator!=(const char *other) const noexcept {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator!=(const BasicString &other) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator!=(const OxString_c auto &other) const noexcept {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator<(const BasicString &other) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<(const BasicString &other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) < 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator>(const BasicString &other) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>(const BasicString &other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) > 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator<=(const BasicString &other) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator<=(const BasicString &other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) < 1;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::operator>=(const BasicString &other) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::operator>=(const BasicString &other) const noexcept {
|
||||
return ox_strcmp(c_str(), other.c_str()) > -1;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr char BasicString<SmallStringSize>::operator[](std::size_t i) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr char BasicString<SmallStringSize_v>::operator[](std::size_t i) const noexcept {
|
||||
return m_buff[i];
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr char &BasicString<SmallStringSize>::operator[](std::size_t i) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr char &BasicString<SmallStringSize_v>::operator[](std::size_t i) noexcept {
|
||||
return m_buff[i];
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> BasicString<SmallStringSize>::substr(std::size_t pos) const noexcept {
|
||||
return m_buff.data() + pos;
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::substr(std::size_t pos) const noexcept {
|
||||
return BasicString(m_buff.data() + pos, m_buff.size() - pos);
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr BasicString<SmallStringSize> BasicString<SmallStringSize>::substr(std::size_t begin, std::size_t end) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr BasicString<SmallStringSize_v> BasicString<SmallStringSize_v>::substr(std::size_t begin, std::size_t end) const noexcept {
|
||||
const auto src = m_buff.data() + begin;
|
||||
const auto size = end - begin;
|
||||
BasicString<SmallStringSize> out(size);
|
||||
BasicString<SmallStringSize_v> out(size);
|
||||
const auto buff = out.data();
|
||||
memcpy(buff, src, size);
|
||||
buff[size] = 0;
|
||||
return out;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::beginsWith(const char *beginning) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::beginsWith(const char *beginning) const noexcept {
|
||||
const auto beginningLen = ox::min(ox_strlen(beginning), len());
|
||||
return ox_strncmp(data(), beginning, beginningLen) == 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::beginsWith(const BasicString &beginning) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::beginsWith(const BasicString &beginning) const noexcept {
|
||||
const auto sz = ox::min(beginning.len(), len());;
|
||||
return ox_strncmp(data(), beginning.c_str(), sz) == 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::endsWith(const char *ending) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::endsWith(const char *ending) const noexcept {
|
||||
const auto endingLen = ox_strlen(ending);
|
||||
return len() >= endingLen && ox_strcmp(data() + (len() - endingLen), ending) == 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr bool BasicString<SmallStringSize>::endsWith(const BasicString &ending) const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr bool BasicString<SmallStringSize_v>::endsWith(const BasicString &ending) const noexcept {
|
||||
const auto endingLen = ending.len();
|
||||
return len() >= endingLen && ox_strcmp(data() + (len() - endingLen), ending.c_str()) == 0;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr std::size_t BasicString<SmallStringSize>::bytes() const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr std::size_t BasicString<SmallStringSize_v>::bytes() const noexcept {
|
||||
std::size_t i;
|
||||
for (i = 0; i < m_buff.size() && m_buff[i]; i++);
|
||||
return i + 1; // add one for null terminator
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr std::size_t BasicString<SmallStringSize>::len() const noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr std::size_t BasicString<SmallStringSize_v>::len() const noexcept {
|
||||
std::size_t length = 0;
|
||||
for (const auto c : m_buff) {
|
||||
auto b = static_cast<uint8_t>(c);
|
||||
@ -542,29 +569,39 @@ constexpr std::size_t BasicString<SmallStringSize>::len() const noexcept {
|
||||
return length;
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
template<std::size_t SmallStringSize_v>
|
||||
template<std::size_t OtherSize>
|
||||
constexpr void BasicString<SmallStringSize>::set(const BasicString<OtherSize> &src) noexcept {
|
||||
constexpr void BasicString<SmallStringSize_v>::set(const BasicString<OtherSize> &src) noexcept {
|
||||
std::size_t strBytes = src.bytes();
|
||||
if (strBytes > 1) {
|
||||
m_buff.resize(strBytes);
|
||||
memcpy(m_buff.data(), src.data(), strBytes);
|
||||
copy_n(src.begin(), strBytes, m_buff.data());
|
||||
m_buff.back().value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr void BasicString<SmallStringSize>::set(const char *str) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(StringView str) noexcept {
|
||||
std::size_t strBytes = str.bytes();
|
||||
if (strBytes > 1) {
|
||||
m_buff.resize(strBytes + 1);
|
||||
copy_n(str.data(), strBytes, m_buff.data());
|
||||
m_buff.back().value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(const char *str) noexcept {
|
||||
std::size_t strBytes = ox_strlen(str) + 1;
|
||||
if (strBytes > 1) {
|
||||
m_buff.resize(strBytes);
|
||||
memcpy(m_buff.data(), str, strBytes);
|
||||
copy_n(str, strBytes, m_buff.data());
|
||||
m_buff.back().value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<std::size_t SmallStringSize>
|
||||
constexpr void BasicString<SmallStringSize>::set(const char8_t *str) noexcept {
|
||||
template<std::size_t SmallStringSize_v>
|
||||
constexpr void BasicString<SmallStringSize_v>::set(const char8_t *str) noexcept {
|
||||
std::size_t strBytes = ox_strlen(str) + 1;
|
||||
if (strBytes > 1) {
|
||||
m_buff.resize(strBytes);
|
||||
@ -576,5 +613,20 @@ constexpr void BasicString<SmallStringSize>::set(const char8_t *str) noexcept {
|
||||
extern template class BasicString<8>;
|
||||
|
||||
using String = BasicString<8>;
|
||||
using CRString = String const&;
|
||||
|
||||
template<typename PlatSpec, std::size_t SmallStringSize_v>
|
||||
[[nodiscard]]
|
||||
constexpr auto sizeOf(const ox::BasicString<SmallStringSize_v>*) noexcept {
|
||||
VectorMemMap<PlatSpec> v{.smallVecSize = SmallStringSize_v};
|
||||
return sizeOf<PlatSpec>(&v);
|
||||
}
|
||||
|
||||
template<typename PlatSpec, std::size_t SmallStringSize_v>
|
||||
[[nodiscard]]
|
||||
constexpr auto alignOf(const ox::BasicString<SmallStringSize_v>&) noexcept {
|
||||
VectorMemMap<PlatSpec> v{.smallVecSize = SmallStringSize_v};
|
||||
return alignOf<PlatSpec>(&v);
|
||||
}
|
||||
|
||||
}
|
||||
|
123
deps/ox/src/ox/std/stringview.hpp
vendored
Normal file
123
deps/ox/src/ox/std/stringview.hpp
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 "strops.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<std::size_t buffLen>
|
||||
class BString;
|
||||
|
||||
template<std::size_t buffLen>
|
||||
class BasicString;
|
||||
|
||||
class StringView {
|
||||
private:
|
||||
const char *m_str = nullptr;
|
||||
std::size_t m_len = 0;
|
||||
public:
|
||||
constexpr StringView() noexcept = default;
|
||||
|
||||
constexpr StringView(const StringView &sv) noexcept: m_str(sv.m_str), m_len(sv.m_len) {
|
||||
}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr StringView(const BasicString<SmallStrSz> &str) noexcept: m_str(str.c_str()), m_len(str.len()) {}
|
||||
|
||||
template<std::size_t SmallStrSz>
|
||||
constexpr StringView(const BString<SmallStrSz> &str) noexcept: m_str(str.c_str()), m_len(str.len()) {}
|
||||
|
||||
constexpr StringView(std::nullptr_t) noexcept {}
|
||||
|
||||
constexpr StringView(const char *str) noexcept: m_str(str), m_len(str ? ox_strlen(str) : 0) {}
|
||||
|
||||
constexpr StringView(const char *str, std::size_t len) noexcept: m_str(str), m_len(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];
|
||||
}
|
||||
|
||||
constexpr auto operator[](std::size_t i) const noexcept {
|
||||
return m_str[i];
|
||||
}
|
||||
|
||||
constexpr auto operator=(const StringView &other) noexcept {
|
||||
m_str = other.m_str;
|
||||
m_len = other.m_len;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr auto operator==(const StringView &other) const noexcept {
|
||||
if (other.len() != len()) {
|
||||
return false;
|
||||
}
|
||||
return ox_strncmp(m_str, other.m_str, len()) == 0;
|
||||
}
|
||||
|
||||
constexpr auto operator<=>(const StringView &str2) const noexcept {
|
||||
const StringView &str1 = *this;
|
||||
const auto maxLen = ox::min(str1.len(), str2.len());
|
||||
const auto a = &str1.front();
|
||||
const auto b = &str2.front();
|
||||
for (std::size_t i = 0; i < maxLen && (a[i] || b[i]); ++i) {
|
||||
if (a[i] < b[i]) {
|
||||
return -1;
|
||||
} else if (a[i] > b[i]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (str1.len() > str2.len()) {
|
||||
return 1;
|
||||
} else if (str1.len() < str2.len()) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using CRStringView = const StringView&;
|
||||
|
||||
static_assert(StringView("Read").bytes() == 4);
|
||||
static_assert(StringView("Read") == StringView("Read"));
|
||||
static_assert(StringView("Read") != StringView("Write"));
|
||||
static_assert(StringView("Write") != StringView("Read"));
|
||||
static_assert(StringView("Write") != StringView(""));
|
||||
static_assert(StringView("") != StringView("Read"));
|
||||
static_assert(StringView("") == StringView(""));
|
||||
static_assert(StringView("") == "");
|
||||
static_assert("Read" == StringView("Read"));
|
||||
static_assert(StringView("Read") == StringView("Read"));
|
||||
|
||||
}
|
||||
|
11
deps/ox/src/ox/std/strongint.hpp
vendored
11
deps/ox/src/ox/std/strongint.hpp
vendored
@ -13,16 +13,9 @@
|
||||
namespace ox {
|
||||
|
||||
struct BaseInteger {
|
||||
|
||||
constexpr BaseInteger() noexcept = default;
|
||||
|
||||
constexpr BaseInteger(const BaseInteger&) noexcept {
|
||||
}
|
||||
|
||||
constexpr BaseInteger operator=(const BaseInteger&) noexcept {
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr BaseInteger(const BaseInteger&) noexcept = default;
|
||||
constexpr BaseInteger &operator=(const BaseInteger&) noexcept = default;
|
||||
};
|
||||
|
||||
/**
|
||||
|
2
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
2
deps/ox/src/ox/std/test/CMakeLists.txt
vendored
@ -16,3 +16,5 @@ add_test("[ox/std] String" StdTest "String")
|
||||
add_test("[ox/std] Vector" StdTest "Vector")
|
||||
add_test("[ox/std] HashMap" StdTest "HashMap")
|
||||
add_test("[ox/std] HeapMgr" StdTest malloc)
|
||||
add_test("[ox/std] Serialize-Int" StdTest "Serialize-Int")
|
||||
add_test("[ox/std] BufferWriter" StdTest "BufferWriter")
|
||||
|
35
deps/ox/src/ox/std/test/tests.cpp
vendored
35
deps/ox/src/ox/std/test/tests.cpp
vendored
@ -11,7 +11,7 @@
|
||||
#include <map>
|
||||
#include <ox/std/std.hpp>
|
||||
|
||||
std::map<ox::String, ox::Error(*)()> tests = {
|
||||
static std::map<ox::String, ox::Error(*)()> tests = {
|
||||
{
|
||||
"malloc",
|
||||
[] {
|
||||
@ -122,6 +122,39 @@ std::map<ox::String, ox::Error(*)()> tests = {
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
{
|
||||
"Serialize-Int",
|
||||
[] {
|
||||
using BA = ox::Array<char, 4>;
|
||||
const auto actual = ox::serialize<uint32_t>(256).unwrap();
|
||||
oxOutf("[{}, {}, {}, {}]", static_cast<int>(actual[0]), static_cast<int>(actual[1]), static_cast<int>(actual[2]), static_cast<int>(actual[3]));
|
||||
oxExpect(ox::serialize<int32_t>(4).unwrap(), BA({4, 0, 0, 0}));
|
||||
oxExpect(ox::serialize<int32_t>(256).unwrap(), BA({0, 1, 0, 0}));
|
||||
oxExpect(ox::serialize<int32_t>(257).unwrap(), BA({1, 1, 0, 0}));
|
||||
oxExpect(ox::serialize<uint32_t>(4).unwrap(), BA({4, 0, 0, 0}));
|
||||
oxExpect(ox::serialize<uint32_t>(256).unwrap(), BA({0, 1, 0, 0}));
|
||||
oxExpect(ox::serialize<uint32_t>(257).unwrap(), BA({1, 1, 0, 0}));
|
||||
oxExpect(ox::serialize<uint32_t>(0xffff'ffff).unwrap(), BA({-1, -1, -1, -1}));
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
{
|
||||
"BufferWriter",
|
||||
[] {
|
||||
ox::Buffer b;
|
||||
ox::BufferWriter w(&b);
|
||||
oxAssert(w.write("asdf", 4), "write failed");
|
||||
oxExpect(b.size(), 4u);
|
||||
oxAssert(w.write("aoeu", 4), "write failed");
|
||||
oxExpect(b.size(), 8u);
|
||||
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeu");
|
||||
ox::StringView qwerty = "qwerty";
|
||||
oxAssert(w.write(qwerty.data(), qwerty.bytes()), "write failed");
|
||||
oxExpect(b.size(), 14u);
|
||||
oxExpect(ox::StringView(b.data(), b.size()), "asdfaoeuqwerty");
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
int main(int argc, const char **args) {
|
||||
|
17
deps/ox/src/ox/std/typetraits.hpp
vendored
17
deps/ox/src/ox/std/typetraits.hpp
vendored
@ -73,6 +73,14 @@ template<> struct is_integral<int16_t> : true_type {};
|
||||
template<> struct is_integral<uint16_t>: true_type {};
|
||||
template<> struct is_integral<int32_t> : true_type {};
|
||||
template<> struct is_integral<uint32_t>: true_type {};
|
||||
template<> struct is_integral<const bool> : true_type {};
|
||||
template<> struct is_integral<const wchar_t> : true_type {};
|
||||
template<> struct is_integral<const int8_t> : true_type {};
|
||||
template<> struct is_integral<const uint8_t> : true_type {};
|
||||
template<> struct is_integral<const int16_t> : true_type {};
|
||||
template<> struct is_integral<const uint16_t>: true_type {};
|
||||
template<> struct is_integral<const int32_t> : true_type {};
|
||||
template<> struct is_integral<const uint32_t>: true_type {};
|
||||
|
||||
// some of these need to be done with the actual language syntax because no one
|
||||
// can agree on what an (u)int64_t is...
|
||||
@ -80,6 +88,10 @@ template<> struct is_integral<long>: true_type {};
|
||||
template<> struct is_integral<long long>: true_type {};
|
||||
template<> struct is_integral<unsigned long>: true_type {};
|
||||
template<> struct is_integral<unsigned long long>: true_type {};
|
||||
template<> struct is_integral<const long>: true_type {};
|
||||
template<> struct is_integral<const long long>: true_type {};
|
||||
template<> struct is_integral<const unsigned long>: true_type {};
|
||||
template<> struct is_integral<const unsigned long long>: true_type {};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_integral_v = is_integral<T>::value;
|
||||
@ -184,6 +196,11 @@ struct is_pointer<T*> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_pointer<const T*> {
|
||||
static constexpr bool value = true;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr bool is_pointer_v = is_pointer<T>::value;
|
||||
|
||||
|
89
deps/ox/src/ox/std/vector.hpp
vendored
89
deps/ox/src/ox/std/vector.hpp
vendored
@ -22,38 +22,6 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename PlatSpec>
|
||||
struct VectorMemMap {
|
||||
typename PlatSpec::size_t size = 0;
|
||||
typename PlatSpec::size_t cap = 0;
|
||||
typename PlatSpec::PtrType items = 0;
|
||||
uint8_t allocator = 0;
|
||||
};
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr auto sizeOf(const VectorMemMap<PlatSpec> &t) noexcept {
|
||||
constexpr auto padding = [](std::size_t size, std::size_t al) {
|
||||
return size - size % al;
|
||||
};
|
||||
std::size_t size = 0;
|
||||
size += sizeof(t.size);
|
||||
size += padding(size, PlatSpec::alignOf(t.cap));
|
||||
size += sizeof(t.cap);
|
||||
size += padding(size, PlatSpec::alignOf(t.items));
|
||||
size += sizeof(t.items);
|
||||
size += padding(size, PlatSpec::alignOf(t.allocator));
|
||||
size += sizeof(t.allocator);
|
||||
return size;
|
||||
}
|
||||
|
||||
template<typename PlatSpec>
|
||||
[[nodiscard]]
|
||||
constexpr auto alignOf(const VectorMemMap<PlatSpec>&) noexcept {
|
||||
const typename PlatSpec::size_t i = 0;
|
||||
return PlatSpec::alignOf(i);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template<typename T, typename Allocator, std::size_t Size = 1>
|
||||
@ -75,12 +43,12 @@ struct VectorAllocator {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void moveConstructItemsFrom(T **items, VectorAllocator &src, const std::size_t count, const std::size_t cap) noexcept {
|
||||
constexpr void moveConstructItemsFrom(T **items, VectorAllocator *src, const std::size_t count, const std::size_t cap) noexcept {
|
||||
// this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
|
||||
// try removing it later
|
||||
if (cap <= Size && count <= Size) {
|
||||
const auto dstItems = reinterpret_cast<T*>(m_data.data());
|
||||
const auto srcItems = reinterpret_cast<T*>(src.m_data.data());
|
||||
const auto srcItems = reinterpret_cast<T*>(src->m_data.data());
|
||||
for (auto i = 0u; i < count; ++i) {
|
||||
std::construct_at<T>(&dstItems[i], std::move(srcItems[i]));
|
||||
}
|
||||
@ -88,12 +56,12 @@ struct VectorAllocator {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void moveItemsFrom(T **items, VectorAllocator &src, const std::size_t count, const std::size_t cap) noexcept {
|
||||
constexpr void moveItemsFrom(T **items, VectorAllocator *src, const std::size_t count, const std::size_t cap) noexcept {
|
||||
// this totally idiotic redundant check (&& count <= Size) is required to address a bug in devkitARM,
|
||||
// try removing it later
|
||||
if (cap <= Size && count <= Size) {
|
||||
const auto dstItems = reinterpret_cast<T*>(m_data.data());
|
||||
const auto srcItems = reinterpret_cast<T*>(src.m_data.data());
|
||||
const auto srcItems = reinterpret_cast<T*>(src->m_data.data());
|
||||
for (std::size_t i = 0; i < count; ++i) {
|
||||
dstItems[i] = std::move(srcItems[i]);
|
||||
}
|
||||
@ -124,11 +92,11 @@ struct VectorAllocator<T, Allocator, 0> {
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
constexpr void moveConstructItemsFrom(T**, VectorAllocator&, const std::size_t, const std::size_t) noexcept {
|
||||
constexpr void moveConstructItemsFrom(T**, VectorAllocator*, const std::size_t, const std::size_t) noexcept {
|
||||
}
|
||||
|
||||
[[maybe_unused]]
|
||||
constexpr void moveItemsFrom(T**, VectorAllocator&, const std::size_t, const std::size_t) noexcept {
|
||||
constexpr void moveItemsFrom(T**, VectorAllocator*, const std::size_t, const std::size_t) noexcept {
|
||||
}
|
||||
|
||||
constexpr void deallocate(T *items, std::size_t cap) noexcept {
|
||||
@ -142,7 +110,7 @@ struct VectorAllocator<T, Allocator, 0> {
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize = 0, typename Allocator = std::allocator<T>>
|
||||
class Vector {
|
||||
class Vector: detail::VectorAllocator<T, Allocator, SmallVectorSize> {
|
||||
|
||||
public:
|
||||
using value_type = T;
|
||||
@ -257,7 +225,6 @@ class Vector {
|
||||
std::size_t m_size = 0;
|
||||
std::size_t m_cap = 0;
|
||||
T *m_items = nullptr;
|
||||
detail::VectorAllocator<T, Allocator, SmallVectorSize> m_allocator;
|
||||
|
||||
public:
|
||||
constexpr Vector() noexcept = default;
|
||||
@ -408,8 +375,7 @@ class Vector {
|
||||
*/
|
||||
constexpr Error unordered_erase(std::size_t pos);
|
||||
|
||||
private:
|
||||
constexpr void expandCap(std::size_t cap);
|
||||
constexpr void reserve(std::size_t cap);
|
||||
|
||||
};
|
||||
|
||||
@ -425,7 +391,7 @@ template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(std::size_t size) noexcept {
|
||||
m_size = size;
|
||||
m_cap = m_size;
|
||||
m_allocator.allocate(&m_items, m_cap);
|
||||
this->allocate(&m_items, m_cap);
|
||||
for (std::size_t i = 0; i < size; ++i) {
|
||||
std::construct_at(&m_items[i]);
|
||||
}
|
||||
@ -442,7 +408,7 @@ template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::Vector(const Vector &other) {
|
||||
m_size = other.m_size;
|
||||
m_cap = other.m_cap;
|
||||
m_allocator.allocate(&m_items, other.m_cap);
|
||||
this->allocate(&m_items, other.m_cap);
|
||||
for (std::size_t i = 0; i < m_size; ++i) {
|
||||
std::construct_at(&m_items[i], other.m_items[i]);
|
||||
}
|
||||
@ -453,7 +419,7 @@ constexpr Vector<T, SmallVectorSize, Allocator>::Vector(Vector &&other) noexcept
|
||||
m_size = other.m_size;
|
||||
m_cap = other.m_cap;
|
||||
m_items = other.m_items;
|
||||
m_allocator.moveConstructItemsFrom(&m_items, other.m_allocator, m_size, m_cap);
|
||||
this->moveConstructItemsFrom(&m_items, &other, m_size, m_cap);
|
||||
other.m_size = 0;
|
||||
other.m_cap = 0;
|
||||
other.m_items = nullptr;
|
||||
@ -462,7 +428,7 @@ constexpr Vector<T, SmallVectorSize, Allocator>::Vector(Vector &&other) noexcept
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator>::~Vector() {
|
||||
clear();
|
||||
m_allocator.deallocate(m_items, m_cap);
|
||||
this->deallocate(m_items, m_cap);
|
||||
m_items = nullptr;
|
||||
}
|
||||
|
||||
@ -483,11 +449,11 @@ template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allocator>::operator=(const Vector &other) {
|
||||
if (this != &other) {
|
||||
clear();
|
||||
m_allocator.deallocate(m_items, m_cap);
|
||||
this->deallocate(m_items, m_cap);
|
||||
m_items = nullptr;
|
||||
m_size = other.m_size;
|
||||
m_cap = other.m_cap;
|
||||
m_allocator.allocate(&m_items, other.m_cap);
|
||||
this->allocate(&m_items, other.m_cap);
|
||||
for (std::size_t i = 0; i < m_size; i++) {
|
||||
std::construct_at(&m_items[i], other.m_items[i]);
|
||||
}
|
||||
@ -499,11 +465,11 @@ template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr Vector<T, SmallVectorSize, Allocator> &Vector<T, SmallVectorSize, Allocator>::operator=(Vector &&other) noexcept {
|
||||
if (this != &other) {
|
||||
clear();
|
||||
m_allocator.deallocate(m_items, m_cap);
|
||||
this->deallocate(m_items, m_cap);
|
||||
m_size = other.m_size;
|
||||
m_cap = other.m_cap;
|
||||
m_items = other.m_items;
|
||||
m_allocator.moveItemsFrom(&m_items, other.m_allocator, m_size, m_cap);
|
||||
this->moveItemsFrom(&m_items, &other, m_size, m_cap);
|
||||
other.m_size = 0;
|
||||
other.m_cap = 0;
|
||||
other.m_items = nullptr;
|
||||
@ -580,7 +546,7 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::clear() {
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::resize(std::size_t size) {
|
||||
if (m_cap < size) {
|
||||
expandCap(size);
|
||||
reserve(size * 2);
|
||||
}
|
||||
if (m_size < size) {
|
||||
for (std::size_t i = m_size; i < size; i++) {
|
||||
@ -606,9 +572,9 @@ constexpr bool Vector<T, SmallVectorSize, Allocator>::contains(const T &v) const
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, std::size_t cnt, const T &val) {
|
||||
// TODO: insert should ideally have its own expandCap
|
||||
// TODO: insert should ideally have its own reserve
|
||||
if (m_size + cnt > m_cap) {
|
||||
expandCap(m_cap ? m_size + cnt : initialSize);
|
||||
reserve(m_cap ? m_size + cnt : initialSize);
|
||||
}
|
||||
if (pos < m_size) {
|
||||
for (auto i = m_size + cnt - 1; i > pos; --i) {
|
||||
@ -625,9 +591,9 @@ constexpr void Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, st
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::insert(std::size_t pos, const T &val) {
|
||||
// TODO: insert should ideally have its own expandCap
|
||||
// TODO: insert should ideally have its own reserve
|
||||
if (m_size == m_cap) {
|
||||
expandCap(m_cap ? m_cap * 2 : initialSize);
|
||||
reserve(m_cap ? m_cap * 2 : initialSize);
|
||||
}
|
||||
if (pos < m_size) {
|
||||
for (auto i = m_size; i > pos; --i) {
|
||||
@ -644,7 +610,7 @@ template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
template<typename... Args>
|
||||
constexpr T &Vector<T, SmallVectorSize, Allocator>::emplace_back(Args&&... args) {
|
||||
if (m_size == m_cap) {
|
||||
expandCap(m_cap ? m_cap * 2 : initialSize);
|
||||
reserve(m_cap ? m_cap * 2 : initialSize);
|
||||
}
|
||||
auto out = std::construct_at(&m_items[m_size], ox::forward<Args>(args)...);
|
||||
++m_size;
|
||||
@ -654,7 +620,7 @@ constexpr T &Vector<T, SmallVectorSize, Allocator>::emplace_back(Args&&... args)
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::push_back(const T &item) {
|
||||
if (m_size == m_cap) {
|
||||
expandCap(m_cap ? m_cap * 2 : initialSize);
|
||||
reserve(m_cap ? m_cap * 2 : initialSize);
|
||||
}
|
||||
std::construct_at(&m_items[m_size], item);
|
||||
++m_size;
|
||||
@ -696,18 +662,21 @@ constexpr Error Vector<T, SmallVectorSize, Allocator>::unordered_erase(std::size
|
||||
}
|
||||
|
||||
template<typename T, std::size_t SmallVectorSize, typename Allocator>
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::expandCap(std::size_t cap) {
|
||||
constexpr void Vector<T, SmallVectorSize, Allocator>::reserve(std::size_t cap) {
|
||||
if (cap <= m_cap) {
|
||||
return;
|
||||
}
|
||||
const auto oldItems = m_items;
|
||||
const auto oldCap = m_cap;
|
||||
m_cap = cap;
|
||||
m_allocator.allocate(&m_items, cap);
|
||||
this->allocate(&m_items, cap);
|
||||
if (oldItems) { // move over old items
|
||||
const auto itRange = ox::min(cap, m_size);
|
||||
for (std::size_t i = 0; i < itRange; ++i) {
|
||||
std::construct_at(&m_items[i], std::move(oldItems[i]));
|
||||
oldItems[i].~T();
|
||||
}
|
||||
m_allocator.deallocate(oldItems, oldCap);
|
||||
this->deallocate(oldItems, oldCap);
|
||||
}
|
||||
}
|
||||
|
||||
|
78
deps/ox/src/ox/std/writer.hpp
vendored
Normal file
78
deps/ox/src/ox/std/writer.hpp
vendored
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* 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 http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "concepts.hpp"
|
||||
#include "error.hpp"
|
||||
#include "types.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
namespace ios_base {
|
||||
enum seekdir {
|
||||
beg,
|
||||
end,
|
||||
cur,
|
||||
};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
concept Writer_c = requires(T v) {
|
||||
{v.put(static_cast<char>(0))} -> ox::same_as<ox::Error>;
|
||||
{v.write(static_cast<const char*>(""), static_cast<std::size_t>(0))} -> ox::same_as<ox::Error>;
|
||||
{v.seekp(static_cast<std::size_t>(0))} -> ox::same_as<ox::Error>;
|
||||
{v.seekp(static_cast<std::size_t>(0), ios_base::beg)} -> ox::same_as<ox::Error>;
|
||||
{v.tellp()} -> ox::same_as<std::size_t>;
|
||||
};
|
||||
|
||||
class Writer_v {
|
||||
public:
|
||||
virtual constexpr ~Writer_v() noexcept = default;
|
||||
virtual constexpr auto put(char) noexcept -> ox::Error = 0;
|
||||
virtual constexpr auto write(const char*, std::size_t) noexcept -> ox::Error = 0;
|
||||
virtual constexpr auto seekp(std::size_t) noexcept -> ox::Error = 0;
|
||||
virtual constexpr auto seekp(int, ios_base::seekdir) -> ox::Error = 0;
|
||||
virtual constexpr auto tellp() noexcept -> std::size_t = 0;
|
||||
};
|
||||
|
||||
template<Writer_c T>
|
||||
class WriterT: public Writer_v {
|
||||
private:
|
||||
T m_writer{};
|
||||
public:
|
||||
template<typename ...Args>
|
||||
constexpr explicit WriterT(Args&&... args) noexcept: m_writer(args...) {
|
||||
}
|
||||
constexpr auto put(char v) noexcept -> ox::Error override {
|
||||
return m_writer.put(v);
|
||||
}
|
||||
constexpr auto write(const char *v, std::size_t cnt) noexcept -> ox::Error override {
|
||||
return m_writer.write(v, cnt);
|
||||
}
|
||||
constexpr auto seekp(std::size_t p) noexcept -> ox::Error override {
|
||||
return m_writer.seekp(p);
|
||||
}
|
||||
constexpr auto seekp(int p, ios_base::seekdir sd) noexcept -> ox::Error override {
|
||||
return m_writer.seekp(p, sd);
|
||||
}
|
||||
constexpr auto tellp() noexcept -> std::size_t override {
|
||||
return m_writer.tellp();
|
||||
}
|
||||
};
|
||||
|
||||
constexpr ox::Result<std::size_t> allocate(Writer_c auto *writer, std::size_t sz) noexcept {
|
||||
const auto p = writer->tellp();
|
||||
oxReturnError(writer->seekp(0, ios_base::end));
|
||||
const auto out = writer->tellp();
|
||||
oxReturnError(writer->write(nullptr, sz));
|
||||
oxReturnError(writer->seekp(p));
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user