[ox/mc] Add basic walking of data by data descriptor
This commit is contained in:
parent
8b7db3d544
commit
cd91f6b60a
20
deps/ox/src/ox/mc/defread.cpp
vendored
Normal file
20
deps/ox/src/ox/mc/defread.cpp
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2015 - 2019 gtalent2@gmail.com
|
||||
*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#include "defread.hpp"
|
||||
|
||||
namespace ox::mc {
|
||||
|
||||
MetalClawDefReader::MetalClawDefReader(uint8_t *buff, std::size_t buffLen): MetalClawReader(buff, buffLen) {
|
||||
}
|
||||
|
||||
const mc::TypeStore &MetalClawDefReader::typeStore() const {
|
||||
return m_typeStore;
|
||||
}
|
||||
|
||||
}
|
34
deps/ox/src/ox/mc/defread.hpp
vendored
Normal file
34
deps/ox/src/ox/mc/defread.hpp
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2015 - 2018 gtalent2@gmail.com
|
||||
*
|
||||
* 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 "deftypes.hpp"
|
||||
#include "read.hpp"
|
||||
|
||||
namespace ox::mc {
|
||||
|
||||
|
||||
class MetalClawDefReader: public MetalClawReader {
|
||||
private:
|
||||
TypeStore m_typeStore;
|
||||
|
||||
public:
|
||||
MetalClawDefReader(uint8_t *buff, std::size_t buffLen);
|
||||
|
||||
const mc::TypeStore &typeStore() const;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
int readMCDef(uint8_t *buff, std::size_t buffLen, T *val) {
|
||||
MetalClawDefReader reader(buff, buffLen);
|
||||
return ioOp(&reader, val);
|
||||
}
|
||||
|
||||
}
|
19
deps/ox/src/ox/mc/deftypes.cpp
vendored
Normal file
19
deps/ox/src/ox/mc/deftypes.cpp
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2015 - 2018 gtalent2@gmail.com
|
||||
*
|
||||
* 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/.
|
||||
*/
|
||||
|
||||
#include "deftypes.hpp"
|
||||
|
||||
namespace ox::mc {
|
||||
|
||||
Field::~Field() {
|
||||
if (ownsType) {
|
||||
delete type;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
61
deps/ox/src/ox/mc/deftypes.hpp
vendored
61
deps/ox/src/ox/mc/deftypes.hpp
vendored
@ -22,7 +22,7 @@ enum class PrimitiveType: uint8_t {
|
||||
UnsignedInteger = 0,
|
||||
SignedInteger = 1,
|
||||
Bool = 2,
|
||||
Float = 3,
|
||||
// Float = 3, reserved, but not implemented
|
||||
String = 4,
|
||||
Struct = 5,
|
||||
};
|
||||
@ -39,7 +39,59 @@ struct Field {
|
||||
TypeName typeName; // gives reference to type for lookup if type is null
|
||||
bool ownsType = false;
|
||||
|
||||
constexpr Field() noexcept = default;
|
||||
|
||||
/**
|
||||
* Allow for explicit copying.
|
||||
*/
|
||||
constexpr explicit Field(const Field &other) noexcept {
|
||||
type = other.type;
|
||||
fieldName = other.fieldName;
|
||||
subscriptLevels = other.subscriptLevels;
|
||||
typeName = other.typeName;
|
||||
ownsType = false; // is copy, only owns type if move
|
||||
}
|
||||
|
||||
constexpr Field(const Type *type, const FieldName &fieldName, int subscriptLevels, const TypeName &typeName, bool ownsType) noexcept {
|
||||
this->type = type;
|
||||
this->fieldName = fieldName;
|
||||
this->subscriptLevels = subscriptLevels;
|
||||
this->typeName = typeName;
|
||||
this->ownsType = ownsType;
|
||||
}
|
||||
|
||||
constexpr Field(Field &&other) noexcept {
|
||||
type = other.type;
|
||||
fieldName = other.fieldName;
|
||||
subscriptLevels = other.subscriptLevels;
|
||||
typeName = other.typeName;
|
||||
ownsType = other.ownsType;
|
||||
|
||||
other.type = {};
|
||||
other.fieldName = "";
|
||||
other.subscriptLevels = {};
|
||||
other.typeName = "";
|
||||
other.ownsType = {};
|
||||
}
|
||||
|
||||
~Field();
|
||||
|
||||
constexpr const Field &operator=(Field &&other) noexcept {
|
||||
type = other.type;
|
||||
fieldName = other.fieldName;
|
||||
subscriptLevels = other.subscriptLevels;
|
||||
typeName = other.typeName;
|
||||
ownsType = other.ownsType;
|
||||
|
||||
other.type = {};
|
||||
other.fieldName = "";
|
||||
other.subscriptLevels = {};
|
||||
other.typeName = "";
|
||||
other.ownsType = {};
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
using FieldList = Vector<Field>;
|
||||
@ -86,8 +138,9 @@ int ioOpWrite(T *io, Field *field) {
|
||||
err |= io->op("type", static_cast<decltype(field->type)>(nullptr));
|
||||
}
|
||||
err |= io->op("fieldName", &field->fieldName);
|
||||
// defaultValue is unused now, but placeholder for backwards compatibility
|
||||
err |= io->op("defaultValue", nullptr);
|
||||
// defaultValue is unused now, but leave placeholder for backwards compatibility
|
||||
const int DefaultValue = 0;
|
||||
err |= io->op("defaultValue", &DefaultValue);
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -116,6 +169,6 @@ int ioOpRead(T *io, Field *field) {
|
||||
return err;
|
||||
}
|
||||
|
||||
using TypeStore = ox::HashMap<mc::String, mc::Type>;
|
||||
using TypeStore = ox::HashMap<mc::String, mc::Type*>;
|
||||
|
||||
}
|
||||
|
22
deps/ox/src/ox/mc/defwriter.cpp
vendored
22
deps/ox/src/ox/mc/defwriter.cpp
vendored
@ -102,6 +102,12 @@ mc::Type *MetalClawDefWriter::type(uint64_t*, bool *alreadyExisted) {
|
||||
return getType(TypeName, PT, Bytes, alreadyExisted);
|
||||
}
|
||||
|
||||
mc::Type *MetalClawDefWriter::type(const char*, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:string";
|
||||
constexpr auto PT = mc::PrimitiveType::String;
|
||||
return getType(TypeName, PT, 0, alreadyExisted);
|
||||
}
|
||||
|
||||
mc::Type *MetalClawDefWriter::type(McStr, bool *alreadyExisted) {
|
||||
constexpr auto TypeName = "B:string";
|
||||
constexpr auto PT = mc::PrimitiveType::String;
|
||||
@ -116,8 +122,11 @@ mc::Type *MetalClawDefWriter::type(bool*, bool *alreadyExisted) {
|
||||
}
|
||||
|
||||
void MetalClawDefWriter::setTypeInfo(const char *name, int) {
|
||||
m_typeAlreayExisted = m_typeStore->contains(name);
|
||||
m_type = &m_typeStore->at(name);
|
||||
auto &t = m_typeStore->at(name);
|
||||
if (!t) {
|
||||
t = new mc::Type;
|
||||
}
|
||||
m_type = t;
|
||||
m_type->typeName = name;
|
||||
m_type->primitiveType = mc::PrimitiveType::Struct;
|
||||
}
|
||||
@ -125,10 +134,15 @@ void MetalClawDefWriter::setTypeInfo(const char *name, int) {
|
||||
mc::Type *MetalClawDefWriter::getType(mc::TypeName tn, mc::PrimitiveType pt, int b, bool *alreadyExisted) {
|
||||
if (m_typeStore->contains(tn)) {
|
||||
*alreadyExisted = true;
|
||||
return &m_typeStore->at(tn);
|
||||
auto type = m_typeStore->at(tn);
|
||||
oxAssert(type != nullptr, "MetalClawDefWriter::getType returning null Type");
|
||||
return type;
|
||||
} else {
|
||||
*alreadyExisted = false;
|
||||
auto t = &m_typeStore->at(tn);
|
||||
auto &t = m_typeStore->at(tn);
|
||||
if (!t) {
|
||||
t = new mc::Type;
|
||||
}
|
||||
t->typeName = tn;
|
||||
t->primitiveType = pt;
|
||||
t->length = b;
|
||||
|
82
deps/ox/src/ox/mc/defwriter.hpp
vendored
82
deps/ox/src/ox/mc/defwriter.hpp
vendored
@ -19,6 +19,7 @@
|
||||
#include "err.hpp"
|
||||
#include "optype.hpp"
|
||||
#include "types.hpp"
|
||||
#include "write.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -35,11 +36,29 @@ static constexpr int indirectionLevels(T *t) {
|
||||
class MetalClawDefWriter {
|
||||
|
||||
private:
|
||||
struct NameCatcher {
|
||||
|
||||
mc::TypeName name;
|
||||
|
||||
constexpr void setTypeInfo(const char *name, int) noexcept {
|
||||
this->name = name;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error op(const char*, T*, std::size_t) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error op(const char*, T*) noexcept {
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
mc::TypeStore *m_typeStoreOwnerRef = nullptr;
|
||||
mc::TypeStore *m_typeStore = nullptr;
|
||||
mc::Type *m_type = nullptr;
|
||||
// indicates whether or not m_type already existed in the TypeStore
|
||||
bool m_typeAlreayExisted = false;
|
||||
|
||||
public:
|
||||
explicit MetalClawDefWriter(mc::TypeStore *typeStore = nullptr);
|
||||
@ -61,9 +80,9 @@ class MetalClawDefWriter {
|
||||
return m_type;
|
||||
}
|
||||
|
||||
static constexpr OpType opType() {
|
||||
static constexpr OpType opType() {
|
||||
return OpType::WriteDefinition;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
mc::Type *type(int8_t *val, bool *alreadyExisted);
|
||||
@ -78,8 +97,13 @@ class MetalClawDefWriter {
|
||||
|
||||
mc::Type *type(bool *val, bool *alreadyExisted);
|
||||
|
||||
mc::Type *type(const char *val, bool *alreadyExisted);
|
||||
|
||||
mc::Type *type(McStr val, bool *alreadyExisted);
|
||||
|
||||
template<std::size_t sz>
|
||||
mc::Type *type(BString<sz> *val, bool *alreadyExisted);
|
||||
|
||||
template<typename T>
|
||||
mc::Type *type(T *val, bool *alreadyExisted);
|
||||
|
||||
@ -90,10 +114,14 @@ class MetalClawDefWriter {
|
||||
template<typename T>
|
||||
ox::Error MetalClawDefWriter::op(const char *name, T *val, std::size_t) {
|
||||
if (m_type) {
|
||||
constexpr typename RemoveIndirection<decltype(val)>::type *p = nullptr;
|
||||
constexpr typename ox::remove_pointer<decltype(val)>::type *p = nullptr;
|
||||
bool alreadyExisted = false;
|
||||
const auto t = type(p, &alreadyExisted);
|
||||
m_type->fieldList.push_back(mc::Field{t, name, indirectionLevels(val), alreadyExisted ? t->typeName : "", !alreadyExisted});
|
||||
oxAssert(t != nullptr, "op(const char *name, T *val, std::size_t): Type not found or generated");
|
||||
if (t == nullptr) {
|
||||
type(p, &alreadyExisted);
|
||||
}
|
||||
m_type->fieldList.emplace_back(t, name, indirectionLevels(val), alreadyExisted ? t->typeName : "", !alreadyExisted);
|
||||
return OxError(0);
|
||||
}
|
||||
return OxError(1);
|
||||
@ -109,25 +137,49 @@ ox::Error MetalClawDefWriter::op(const char *name, T *val) {
|
||||
if (m_type) {
|
||||
bool alreadyExisted = false;
|
||||
const auto t = type(val, &alreadyExisted);
|
||||
m_type->fieldList.push_back(mc::Field{t, name, 0, alreadyExisted ? t->typeName : "", !alreadyExisted});
|
||||
oxAssert(t != nullptr, "op(const char *name, T *val): Type not found or generated");
|
||||
m_type->fieldList.emplace_back(t, name, 0, alreadyExisted ? t->typeName : "", !alreadyExisted);
|
||||
return OxError(0);
|
||||
}
|
||||
return OxError(1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
mc::Type *MetalClawDefWriter::type(T *val, bool *alreadyExisted) {
|
||||
MetalClawDefWriter dw(m_typeStore);
|
||||
oxLogError(ioOp(&dw, val));
|
||||
*alreadyExisted = dw.m_typeAlreayExisted;
|
||||
return dw.m_type;
|
||||
template<std::size_t sz>
|
||||
mc::Type *MetalClawDefWriter::type(BString<sz> *val, bool *alreadyExisted) {
|
||||
return type(McStr(val), alreadyExisted);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] ValErr<mc::Type*> writeMCDef(T *val) {
|
||||
mc::Type *MetalClawDefWriter::type(T *val, bool *alreadyExisted) {
|
||||
NameCatcher nc;
|
||||
ioOp(&nc, val);
|
||||
if (m_typeStore->contains(nc.name)) {
|
||||
*alreadyExisted = true;
|
||||
return m_typeStore->at(nc.name);
|
||||
} else {
|
||||
MetalClawDefWriter dw(m_typeStore);
|
||||
oxLogError(ioOp(&dw, val));
|
||||
*alreadyExisted = false;
|
||||
return dw.m_type;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
[[nodiscard]] ValErr<mc::Type*> buildMCDef(T *val) {
|
||||
MetalClawDefWriter writer;
|
||||
ox::Error err = ioOp(&writer, val);
|
||||
Error err = ioOp(&writer, val);
|
||||
return {writer.definition(), err};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
Error writeMCDef(uint8_t *buff, std::size_t buffLen, T *val, std::size_t *sizeOut = nullptr) {
|
||||
auto def = buildMCDef(val);
|
||||
auto err = def.error;
|
||||
if (!err) {
|
||||
err |= writeMC(buff, buffLen, def.value, sizeOut);
|
||||
}
|
||||
delete def.value;
|
||||
return err;
|
||||
}
|
||||
|
||||
}
|
||||
|
54
deps/ox/src/ox/mc/read.cpp
vendored
54
deps/ox/src/ox/mc/read.cpp
vendored
@ -14,95 +14,101 @@
|
||||
|
||||
namespace ox {
|
||||
|
||||
MetalClawReader::MetalClawReader(uint8_t *buff, std::size_t buffLen): m_fieldPresence(buff, buffLen) {
|
||||
MetalClawReader::MetalClawReader(uint8_t *buff, std::size_t buffLen, MetalClawReader *parent): m_fieldPresence(buff, buffLen) {
|
||||
m_buff = buff;
|
||||
m_buffLen = buffLen;
|
||||
m_parent = parent;
|
||||
}
|
||||
|
||||
MetalClawReader::~MetalClawReader() {
|
||||
if (m_parent) {
|
||||
m_parent->m_buffIt += m_buffIt;
|
||||
}
|
||||
oxAssert(m_field == m_fields, "MetalClawReader: incorrect fields number given");
|
||||
}
|
||||
|
||||
int MetalClawReader::op(const char*, int8_t *val) {
|
||||
Error MetalClawReader::op(const char*, int8_t *val) {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
int MetalClawReader::op(const char*, int16_t *val) {
|
||||
Error MetalClawReader::op(const char*, int16_t *val) {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
int MetalClawReader::op(const char*, int32_t *val) {
|
||||
Error MetalClawReader::op(const char*, int32_t *val) {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
int MetalClawReader::op(const char*, int64_t *val) {
|
||||
Error MetalClawReader::op(const char*, int64_t *val) {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
|
||||
int MetalClawReader::op(const char*, uint8_t *val) {
|
||||
Error MetalClawReader::op(const char*, uint8_t *val) {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
int MetalClawReader::op(const char*, uint16_t *val) {
|
||||
Error MetalClawReader::op(const char*, uint16_t *val) {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
int MetalClawReader::op(const char*, uint32_t *val) {
|
||||
Error MetalClawReader::op(const char*, uint32_t *val) {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
int MetalClawReader::op(const char*, uint64_t *val) {
|
||||
Error MetalClawReader::op(const char*, uint64_t *val) {
|
||||
return readInteger(val);
|
||||
}
|
||||
|
||||
int MetalClawReader::op(const char*, bool *val) {
|
||||
Error MetalClawReader::op(const char*, bool *val) {
|
||||
*val = m_fieldPresence.get(m_field++);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Error MetalClawReader::op(const char*, McStr val) {
|
||||
int err = 0;
|
||||
if (m_fieldPresence.get(m_field)) {
|
||||
// read the length
|
||||
int size = 0;
|
||||
StringLength size = 0;
|
||||
if (m_buffIt + sizeof(StringLength) < m_buffLen) {
|
||||
size = *reinterpret_cast<LittleEndian<StringLength>*>(&m_buff[m_buffIt]);
|
||||
m_buffIt += sizeof(StringLength);
|
||||
} else {
|
||||
err |= MC_BUFFENDED;
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
|
||||
// read the string
|
||||
if (val.cap() >= size) {
|
||||
if (val.cap() > -1 && static_cast<StringLength>(val.cap()) >= size) {
|
||||
if (m_buffIt + size < m_buffLen) {
|
||||
ox_memcpy(val.data(), &m_buff[m_buffIt], size);
|
||||
m_buffIt += size;
|
||||
} else {
|
||||
err |= MC_BUFFENDED;
|
||||
return OxError(MC_BUFFENDED);
|
||||
}
|
||||
} else {
|
||||
err |= MC_OUTBUFFENDED;
|
||||
return OxError(MC_OUTBUFFENDED);
|
||||
}
|
||||
} else {
|
||||
val.data()[0] = 0;
|
||||
}
|
||||
m_field++;
|
||||
return err;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
[[nodiscard]] std::size_t MetalClawReader::arrayLength() {
|
||||
[[nodiscard]] ArrayLength MetalClawReader::arrayLength(bool pass) {
|
||||
std::size_t len = 0;
|
||||
if (m_fieldPresence.get(m_field)) {
|
||||
// read the length
|
||||
if (m_buffIt + sizeof(ArrayLength) < m_buffLen) {
|
||||
len = *reinterpret_cast<LittleEndian<ArrayLength>*>(&m_buff[m_buffIt]);
|
||||
if (pass) {
|
||||
m_buffIt += sizeof(ArrayLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
std::size_t MetalClawReader::stringLength(const char*) {
|
||||
[[nodiscard]] StringLength MetalClawReader::stringLength() {
|
||||
std::size_t len = 0;
|
||||
if (m_fieldPresence.get(m_field)) {
|
||||
// read the length
|
||||
@ -121,15 +127,19 @@ void MetalClawReader::setTypeInfo(const char*, int fields) {
|
||||
}
|
||||
|
||||
MetalClawReader MetalClawReader::child() {
|
||||
return MetalClawReader(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||
return MetalClawReader(m_buff + m_buffIt, m_buffLen - m_buffIt, this);
|
||||
}
|
||||
|
||||
bool MetalClawReader::fieldPresent() {
|
||||
bool MetalClawReader::fieldPresent() const {
|
||||
return m_fieldPresence.get(m_field);
|
||||
}
|
||||
|
||||
bool MetalClawReader::fieldPresent(int fieldNo) {
|
||||
bool MetalClawReader::fieldPresent(int fieldNo) const {
|
||||
return m_fieldPresence.get(fieldNo);
|
||||
}
|
||||
|
||||
void MetalClawReader::nextField() noexcept {
|
||||
++m_field;
|
||||
}
|
||||
|
||||
}
|
||||
|
92
deps/ox/src/ox/mc/read.hpp
vendored
92
deps/ox/src/ox/mc/read.hpp
vendored
@ -28,69 +28,69 @@ class MetalClawReader {
|
||||
std::size_t m_buffIt = 0;
|
||||
std::size_t m_buffLen = 0;
|
||||
uint8_t *m_buff = nullptr;
|
||||
MetalClawReader *m_parent = nullptr;
|
||||
|
||||
public:
|
||||
MetalClawReader(uint8_t *buff, std::size_t buffLen);
|
||||
MetalClawReader(uint8_t *buff, std::size_t buffLen, MetalClawReader *parent = nullptr);
|
||||
|
||||
~MetalClawReader();
|
||||
|
||||
int op(const char*, int8_t *val);
|
||||
int op(const char*, int16_t *val);
|
||||
int op(const char*, int32_t *val);
|
||||
int op(const char*, int64_t *val);
|
||||
Error op(const char*, int8_t *val);
|
||||
Error op(const char*, int16_t *val);
|
||||
Error op(const char*, int32_t *val);
|
||||
Error op(const char*, int64_t *val);
|
||||
|
||||
int op(const char*, uint8_t *val);
|
||||
int op(const char*, uint16_t *val);
|
||||
int op(const char*, uint32_t *val);
|
||||
int op(const char*, uint64_t *val);
|
||||
Error op(const char*, uint8_t *val);
|
||||
Error op(const char*, uint16_t *val);
|
||||
Error op(const char*, uint32_t *val);
|
||||
Error op(const char*, uint64_t *val);
|
||||
|
||||
int op(const char*, bool *val);
|
||||
Error op(const char*, bool *val);
|
||||
|
||||
/**
|
||||
* Reads an array length from the current location in the buffer.
|
||||
*/
|
||||
[[nodiscard]] std::size_t arrayLength();
|
||||
// array handler
|
||||
template<typename T>
|
||||
Error op(const char*, T *val, std::size_t len);
|
||||
|
||||
template<typename T>
|
||||
int op(const char*, T *val, std::size_t len);
|
||||
Error op(const char*, ox::Vector<T> *val);
|
||||
|
||||
template<typename T>
|
||||
int op(const char*, ox::Vector<T> *val);
|
||||
|
||||
template<typename T>
|
||||
int op(const char*, T *val);
|
||||
Error op(const char*, T *val);
|
||||
|
||||
template<std::size_t L>
|
||||
int op(const char*, ox::BString<L> *val);
|
||||
Error op(const char*, ox::BString<L> *val);
|
||||
|
||||
Error op(const char*, McStr val);
|
||||
|
||||
std::size_t arrayLength(const char*);
|
||||
/**
|
||||
* Reads an array length from the current location in the buffer.
|
||||
* @param pass indicates that the parsing should iterate past the array length
|
||||
*/
|
||||
[[nodiscard]] ArrayLength arrayLength(bool pass = true);
|
||||
|
||||
// stringLength returns the length of the string, including the null terminator.
|
||||
std::size_t stringLength(const char*);
|
||||
/**
|
||||
* Reads an string length from the current location in the buffer.
|
||||
*/
|
||||
[[nodiscard]] StringLength stringLength();
|
||||
|
||||
void setTypeInfo(const char *name, int fields);
|
||||
|
||||
/**
|
||||
* Returns a MetalClawReader to parse a child object.
|
||||
*/
|
||||
MetalClawReader child();
|
||||
[[nodiscard]] MetalClawReader child();
|
||||
|
||||
/**
|
||||
* Indicates whether or not the next field to be read is present.
|
||||
*/
|
||||
bool fieldPresent();
|
||||
bool fieldPresent() const;
|
||||
|
||||
/**
|
||||
* Indicates whether or not the given field is present.
|
||||
*/
|
||||
bool fieldPresent(int fieldNo);
|
||||
bool fieldPresent(int fieldNo) const;
|
||||
|
||||
/**
|
||||
* @return the number of fields in this struct or list
|
||||
*/
|
||||
bool fields();
|
||||
void nextField() noexcept;
|
||||
|
||||
static constexpr OpType opType() {
|
||||
return OpType::Read;
|
||||
@ -98,35 +98,35 @@ class MetalClawReader {
|
||||
|
||||
private:
|
||||
template<typename I>
|
||||
int readInteger(I *val);
|
||||
Error readInteger(I *val);
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
int MetalClawReader::op(const char*, T *val) {
|
||||
int err = 0;
|
||||
Error MetalClawReader::op(const char*, T *val) {
|
||||
Error err = 0;
|
||||
if (val && m_fieldPresence.get(m_field)) {
|
||||
MetalClawReader reader(m_buff + m_buffIt, m_buffLen - m_buffIt);
|
||||
auto reader = child();
|
||||
err |= ioOp(&reader, val);
|
||||
m_buffIt += reader.m_buffIt;
|
||||
}
|
||||
m_field++;
|
||||
return err;
|
||||
};
|
||||
|
||||
template<std::size_t L>
|
||||
int MetalClawReader::op(const char *name, ox::BString<L> *val) {
|
||||
Error MetalClawReader::op(const char *name, ox::BString<L> *val) {
|
||||
return op(name, McStr(val->data(), val->cap()));
|
||||
}
|
||||
|
||||
template<typename I>
|
||||
int MetalClawReader::readInteger(I *val) {
|
||||
int err = 0;
|
||||
Error MetalClawReader::readInteger(I *val) {
|
||||
Error err = 0;
|
||||
if (m_fieldPresence.get(m_field)) {
|
||||
if (m_buffIt + sizeof(I) < m_buffLen) {
|
||||
*val = *reinterpret_cast<LittleEndian<I>*>(&m_buff[m_buffIt]);
|
||||
m_buffIt += sizeof(I);
|
||||
} else {
|
||||
err = MC_BUFFENDED;
|
||||
err = OxError(MC_BUFFENDED);
|
||||
}
|
||||
} else {
|
||||
*val = 0;
|
||||
@ -135,17 +135,18 @@ int MetalClawReader::readInteger(I *val) {
|
||||
return err;
|
||||
};
|
||||
|
||||
// array handler
|
||||
template<typename T>
|
||||
int MetalClawReader::op(const char*, T *val, std::size_t valLen) {
|
||||
int err = 0;
|
||||
Error MetalClawReader::op(const char*, T *val, std::size_t valLen) {
|
||||
Error err = 0;
|
||||
if (m_fieldPresence.get(m_field)) {
|
||||
// read the length
|
||||
std::size_t len = 0;
|
||||
ArrayLength len = 0;
|
||||
if (m_buffIt + sizeof(ArrayLength) < m_buffLen) {
|
||||
len = *reinterpret_cast<LittleEndian<ArrayLength>*>(&m_buff[m_buffIt]);
|
||||
m_buffIt += sizeof(ArrayLength);
|
||||
} else {
|
||||
err = MC_BUFFENDED;
|
||||
err = OxError(MC_BUFFENDED);
|
||||
}
|
||||
|
||||
// read the list
|
||||
@ -155,9 +156,8 @@ int MetalClawReader::op(const char*, T *val, std::size_t valLen) {
|
||||
for (std::size_t i = 0; i < len; i++) {
|
||||
err |= reader.op("", &val[i]);
|
||||
}
|
||||
m_buffIt += reader.m_buffIt;
|
||||
} else {
|
||||
err = MC_OUTBUFFENDED;
|
||||
err = OxError(MC_OUTBUFFENDED);
|
||||
}
|
||||
}
|
||||
m_field++;
|
||||
@ -165,7 +165,7 @@ int MetalClawReader::op(const char*, T *val, std::size_t valLen) {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
int MetalClawReader::op(const char*, ox::Vector<T> *val) {
|
||||
Error MetalClawReader::op(const char*, ox::Vector<T> *val) {
|
||||
return op(nullptr, val->data(), val->size());
|
||||
}
|
||||
|
||||
|
168
deps/ox/src/ox/mc/test/tests.cpp
vendored
168
deps/ox/src/ox/mc/test/tests.cpp
vendored
@ -7,7 +7,9 @@
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <ox/mc/mc.hpp>
|
||||
#include <ox/std/std.hpp>
|
||||
@ -36,8 +38,8 @@ struct TestStruct {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
int ioOp(T *io, TestStructNest *obj) {
|
||||
int32_t err = 0;
|
||||
ox::Error ioOp(T *io, TestStructNest *obj) {
|
||||
ox::Error err = 0;
|
||||
io->setTypeInfo("TestStructNest", 3);
|
||||
err |= io->op("Bool", &obj->Bool);
|
||||
err |= io->op("Int", &obj->Int);
|
||||
@ -46,8 +48,8 @@ int ioOp(T *io, TestStructNest *obj) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
int ioOp(T *io, TestStruct *obj) {
|
||||
int err = 0;
|
||||
ox::Error ioOp(T *io, TestStruct *obj) {
|
||||
ox::Error err = 0;
|
||||
io->setTypeInfo("TestStruct", 14);
|
||||
err |= io->op("Bool", &obj->Bool);
|
||||
err |= io->op("Int", &obj->Int);
|
||||
@ -86,7 +88,6 @@ std::map<std::string, ox::Error(*)()> tests = {
|
||||
{
|
||||
"MetalClawReader",
|
||||
[] {
|
||||
ox::Error err = 0;
|
||||
constexpr size_t buffLen = 1024;
|
||||
uint8_t buff[buffLen];
|
||||
TestStruct testIn, testOut;
|
||||
@ -102,41 +103,144 @@ std::map<std::string, ox::Error(*)()> tests = {
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
|
||||
err |= ox::writeMC(buff, buffLen, &testIn);
|
||||
err |= ox::readMC(buff, buffLen, &testOut);
|
||||
oxAssert(ox::writeMC(buff, buffLen, &testIn), "writeMC failed");
|
||||
oxAssert(ox::readMC(buff, buffLen, &testOut), "writeMC failed");
|
||||
|
||||
err |= !(testIn.Bool == testOut.Bool);
|
||||
err |= !(testIn.Int == testOut.Int);
|
||||
err |= !(testIn.Int1 == testOut.Int1);
|
||||
err |= !(testIn.Int2 == testOut.Int2);
|
||||
err |= !(testIn.Int3 == testOut.Int3);
|
||||
err |= !(testIn.Int4 == testOut.Int4);
|
||||
err |= !(testIn.Int5 == testOut.Int5);
|
||||
err |= !(testIn.Int6 == testOut.Int6);
|
||||
err |= !(testIn.Int7 == testOut.Int7);
|
||||
err |= !(testIn.Int8 == testOut.Int8);
|
||||
err |= !(testIn.String == testOut.String);
|
||||
err |= !(testIn.List[0] == testOut.List[0]);
|
||||
err |= !(testIn.List[1] == testOut.List[1]);
|
||||
err |= !(testIn.List[2] == testOut.List[2]);
|
||||
err |= !(testIn.List[3] == testOut.List[3]);
|
||||
err |= !(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool);
|
||||
err |= !(testIn.EmptyStruct.Int == testOut.EmptyStruct.Int);
|
||||
err |= !(testIn.EmptyStruct.String == testOut.EmptyStruct.String);
|
||||
err |= !(testIn.Struct.Int == testOut.Struct.Int);
|
||||
err |= !(testIn.Struct.String == testOut.Struct.String);
|
||||
err |= !(testIn.Struct.Bool == testOut.Struct.Bool);
|
||||
oxAssert(testIn.Bool == testOut.Bool, "Bool value mismatch");
|
||||
oxAssert(testIn.Int == testOut.Int, "Int value mismatch");
|
||||
oxAssert(testIn.Int1 == testOut.Int1, "Int1 value mismatch");
|
||||
oxAssert(testIn.Int2 == testOut.Int2, "Int2 value mismatch");
|
||||
oxAssert(testIn.Int3 == testOut.Int3, "Int3 value mismatch");
|
||||
oxAssert(testIn.Int4 == testOut.Int4, "Int4 value mismatch");
|
||||
oxAssert(testIn.Int5 == testOut.Int5, "Int5 value mismatch");
|
||||
oxAssert(testIn.Int6 == testOut.Int6, "Int6 value mismatch");
|
||||
oxAssert(testIn.Int7 == testOut.Int7, "Int7 value mismatch");
|
||||
oxAssert(testIn.Int8 == testOut.Int8, "Int8 value mismatch");
|
||||
oxAssert(testIn.String == testOut.String, "String value mismatch");
|
||||
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");
|
||||
oxAssert(testIn.List[1] == testOut.List[1], "List[1] value mismatch");
|
||||
oxAssert(testIn.List[2] == testOut.List[2], "List[2] value mismatch");
|
||||
oxAssert(testIn.List[3] == testOut.List[3], "List[3] value mismatch");
|
||||
oxAssert(testIn.EmptyStruct.Bool == testOut.EmptyStruct.Bool, "EmptyStruct.Bool value mismatch");
|
||||
oxAssert(testIn.EmptyStruct.Int == testOut.EmptyStruct.Int, "EmptyStruct.Int value mismatch");
|
||||
oxAssert(testIn.EmptyStruct.String == testOut.EmptyStruct.String, "EmptyStruct.String value mismatch");
|
||||
oxAssert(testIn.Struct.Int == testOut.Struct.Int, "Struct.Int value mismatch");
|
||||
oxAssert(testIn.Struct.String == testOut.Struct.String, "Struct.String value mismatch");
|
||||
oxAssert(testIn.Struct.Bool == testOut.Struct.Bool, "Struct.Bool value mismatch");
|
||||
|
||||
auto def = ox::writeMCDef(&testIn);
|
||||
err |= def.error;
|
||||
|
||||
return err;
|
||||
return OxError(0);
|
||||
}
|
||||
},
|
||||
{
|
||||
"MetalClawDef",
|
||||
[] {
|
||||
ox::Error err = 0;
|
||||
//constexpr size_t descBuffLen = 1024;
|
||||
//uint8_t descBuff[descBuffLen];
|
||||
constexpr size_t dataBuffLen = 1024;
|
||||
uint8_t dataBuff[dataBuffLen];
|
||||
TestStruct testIn, testOut;
|
||||
|
||||
testIn.Bool = true;
|
||||
testIn.Int = 42;
|
||||
testIn.String = "Test String 1";
|
||||
testIn.List[0] = 1;
|
||||
testIn.List[1] = 2;
|
||||
testIn.List[2] = 3;
|
||||
testIn.List[3] = 4;
|
||||
testIn.Struct.Bool = false;
|
||||
testIn.Struct.Int = 300;
|
||||
testIn.Struct.String = "Test String 2";
|
||||
|
||||
oxAssert(ox::writeMC(dataBuff, dataBuffLen, &testIn), "Data generation failed");
|
||||
auto type = ox::buildMCDef(&testIn);
|
||||
oxAssert(type.error, "Descriptor write failed");
|
||||
ox::walkMC(type.value, dataBuff, dataBuffLen,
|
||||
[](const ox::Vector<ox::mc::FieldName>&, const ox::Vector<ox::mc::TypeName>&, const ox::mc::Field &f, ox::MetalClawReader *rdr) -> ox::Error {
|
||||
//std::cout << f.fieldName.c_str() << '\n';
|
||||
auto fieldName = f.fieldName.c_str();
|
||||
switch (f.type->primitiveType) {
|
||||
case ox::mc::PrimitiveType::UnsignedInteger:
|
||||
std::cout << fieldName << ":\tuint" << f.type->length << "_t:\t";
|
||||
switch (f.type->length) {
|
||||
case 8: {
|
||||
uint8_t i = {};
|
||||
oxAssert(rdr->op(fieldName, &i), "Walking ioOp failed.");
|
||||
std::cout << i;
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
uint16_t i = {};
|
||||
oxAssert(rdr->op(fieldName, &i), "Walking ioOp failed.");
|
||||
std::cout << i;
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
uint32_t i = {};
|
||||
oxAssert(rdr->op(fieldName, &i), "Walking ioOp failed.");
|
||||
std::cout << i;
|
||||
break;
|
||||
}
|
||||
case 64: {
|
||||
uint64_t i = {};
|
||||
oxAssert(rdr->op(fieldName, &i), "Walking ioOp failed.");
|
||||
std::cout << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::cout << '\n';
|
||||
break;
|
||||
case ox::mc::PrimitiveType::SignedInteger:
|
||||
std::cout << fieldName << ":\tint" << f.type->length << "_t:\t";
|
||||
switch (f.type->length) {
|
||||
case 8: {
|
||||
int8_t i = {};
|
||||
oxAssert(rdr->op(fieldName, &i), "Walking ioOp failed.");
|
||||
std::cout << i;
|
||||
break;
|
||||
}
|
||||
case 16: {
|
||||
int16_t i = {};
|
||||
oxAssert(rdr->op(fieldName, &i), "Walking ioOp failed.");
|
||||
std::cout << i;
|
||||
break;
|
||||
}
|
||||
case 32: {
|
||||
int32_t i = {};
|
||||
oxAssert(rdr->op(fieldName, &i), "Walking ioOp failed.");
|
||||
std::cout << i;
|
||||
break;
|
||||
}
|
||||
case 64: {
|
||||
int64_t i = {};
|
||||
oxAssert(rdr->op(fieldName, &i), "Walking ioOp failed.");
|
||||
std::cout << i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
std::cout << '\n';
|
||||
break;
|
||||
case ox::mc::PrimitiveType::Bool: {
|
||||
bool i = {};
|
||||
oxAssert(rdr->op(fieldName, &i), "Walking ioOp failed.");
|
||||
std::cout << fieldName << ":\t" << "bool:\t" << (i ? "true" : "false") << '\n';
|
||||
break;
|
||||
}
|
||||
case ox::mc::PrimitiveType::String: {
|
||||
ox::Vector<char> v(rdr->stringLength());
|
||||
//std::cout << rdr->stringLength() << '\n';
|
||||
oxAssert(rdr->op(fieldName, ox::McStr(v.data(), v.size())), "Walking ioOp failed.");
|
||||
std::cout << fieldName << ":\t" << "string: " << v.data() << '\n';
|
||||
break;
|
||||
}
|
||||
case ox::mc::PrimitiveType::Struct:
|
||||
break;
|
||||
}
|
||||
return OxError(0);
|
||||
}
|
||||
);
|
||||
delete type.value;
|
||||
|
||||
return err;
|
||||
}
|
||||
},
|
||||
|
17
deps/ox/src/ox/mc/types.hpp
vendored
17
deps/ox/src/ox/mc/types.hpp
vendored
@ -20,19 +20,14 @@ using ArrayLength = uint32_t;
|
||||
class McStr {
|
||||
|
||||
protected:
|
||||
int m_cap = -1;
|
||||
int m_cap = 0;
|
||||
char *m_str = nullptr;
|
||||
|
||||
public:
|
||||
explicit constexpr McStr(const char *str) noexcept {
|
||||
m_str = const_cast<char*>(str);
|
||||
m_cap = -1;
|
||||
}
|
||||
|
||||
template<std::size_t sz>
|
||||
constexpr McStr(BString<sz> *str) noexcept {
|
||||
m_str = const_cast<char*>(str->data());
|
||||
m_cap = -1;
|
||||
m_str = str->data();
|
||||
m_cap = str->cap();
|
||||
}
|
||||
|
||||
constexpr McStr(char *str, int cap) noexcept {
|
||||
@ -46,11 +41,7 @@ class McStr {
|
||||
|
||||
constexpr char *data() noexcept {
|
||||
// do not return a non-const pointer to the const_casted m_str
|
||||
if (m_cap > -1) {
|
||||
return m_str;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
return m_str;
|
||||
}
|
||||
|
||||
constexpr int len() noexcept {
|
||||
|
96
deps/ox/src/ox/mc/walker.hpp
vendored
96
deps/ox/src/ox/mc/walker.hpp
vendored
@ -20,97 +20,141 @@ class MetalClawWalker {
|
||||
template<typename FH>
|
||||
friend ox::Error ioOp(class MetalClawReader*, MetalClawWalker<FH>*);
|
||||
|
||||
template<typename FH>
|
||||
friend ox::Error parseField(const mc::Field &field, MetalClawReader *rdr, MetalClawWalker<FH> *walker);
|
||||
|
||||
private:
|
||||
mc::Type *m_type = nullptr;
|
||||
T *m_fieldHandler = nullptr;
|
||||
Vector<const mc::Type*> m_typeStack;
|
||||
T m_fieldHandler;
|
||||
Vector<mc::FieldName> m_path;
|
||||
Vector<mc::TypeName> m_typePath;
|
||||
|
||||
public:
|
||||
MetalClawWalker(T *fieldHandler);
|
||||
MetalClawWalker(mc::Type *type, T fieldHandler);
|
||||
|
||||
[[nodiscard]] const mc::Type *type() const noexcept;
|
||||
|
||||
void read(const mc::Field&, MetalClawReader *rdr);
|
||||
ox::Error read(const mc::Field&, MetalClawReader *rdr);
|
||||
|
||||
protected:
|
||||
void pushNamePath(mc::FieldName fn);
|
||||
|
||||
void popNamePath();
|
||||
|
||||
void pushType(const mc::Type *type);
|
||||
|
||||
void popType();
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
MetalClawWalker<T>::MetalClawWalker(T *fieldHandler) {
|
||||
m_fieldHandler = fieldHandler;
|
||||
MetalClawWalker<T>::MetalClawWalker(mc::Type *type, T fieldHandler): m_fieldHandler(fieldHandler) {
|
||||
m_typeStack.push_back(type);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const mc::Type *MetalClawWalker<T>::type() const noexcept {
|
||||
return m_type;
|
||||
return m_typeStack.back();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MetalClawWalker<T>::read(const mc::Field &f, MetalClawReader *rdr) {
|
||||
ox::Error MetalClawWalker<T>::read(const mc::Field &f, MetalClawReader *rdr) {
|
||||
// get const ref of paths
|
||||
const auto &pathCr = m_path;
|
||||
m_fieldHandler->read(pathCr, f, rdr);
|
||||
const auto &typePathCr = m_typePath;
|
||||
return m_fieldHandler(pathCr, typePathCr, f, rdr);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MetalClawWalker<T>::pushNamePath(mc::FieldName fn) {
|
||||
m_path.push_back(fn);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MetalClawWalker<T>::popNamePath() {
|
||||
m_path.pop_back();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MetalClawWalker<T>::pushType(const mc::Type *type) {
|
||||
m_typeStack.push_back(type);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MetalClawWalker<T>::popType() {
|
||||
m_typeStack.pop_back();
|
||||
}
|
||||
|
||||
template<typename FH>
|
||||
static ox::Error parseField(mc::Field field, MetalClawReader *rdr, MetalClawWalker<FH> *walker) {
|
||||
ox::Error err = 0;
|
||||
static ox::Error parseField(const mc::Field &field, MetalClawReader *rdr, MetalClawWalker<FH> *walker) {
|
||||
walker->pushNamePath(field.fieldName);
|
||||
if (field.subscriptLevels) {
|
||||
// add array handling
|
||||
const auto arrayLen = rdr->arrayLength(true);
|
||||
auto child = rdr->child();
|
||||
const auto arrayLen = rdr->arrayLength();
|
||||
auto f = field;
|
||||
child.setTypeInfo(field.fieldName.c_str(), arrayLen);
|
||||
mc::Field f(field); // create mutable copy
|
||||
--f.subscriptLevels;
|
||||
rdr->setTypeInfo(field.type->typeName.c_str(), arrayLen);
|
||||
BString<100> subscript;
|
||||
for (ArrayLength i = 0; i < arrayLen; i++) {
|
||||
subscript = "[";
|
||||
subscript += i;
|
||||
subscript += "]";
|
||||
walker->pushNamePath(subscript);
|
||||
err |= parseField(f, &child, walker);
|
||||
walker->pophNamePath();
|
||||
oxReturnError(parseField(f, &child, walker));
|
||||
walker->popNamePath();
|
||||
}
|
||||
rdr->nextField();
|
||||
} else {
|
||||
switch (field.type->primitiveType) {
|
||||
case mc::PrimitiveType::UnsignedInteger:
|
||||
case mc::PrimitiveType::SignedInteger:
|
||||
case mc::PrimitiveType::Bool:
|
||||
case mc::PrimitiveType::Float:
|
||||
case mc::PrimitiveType::String:
|
||||
err |= walker->read(field, rdr);
|
||||
oxReturnError(walker->read(field, rdr));
|
||||
break;
|
||||
case mc::PrimitiveType::Struct:
|
||||
if (rdr->fieldPresent()) {
|
||||
auto child = rdr->child();
|
||||
rdr->setTypeInfo(field.type->typeName.c_str(), field.type->fieldList.size());
|
||||
err |= ioOp(&child, walker);
|
||||
walker->pushType(field.type);
|
||||
oxReturnError(ioOp(&child, walker));
|
||||
walker->popType();
|
||||
rdr->nextField();
|
||||
} else {
|
||||
// skip and discard absent field
|
||||
int discard;
|
||||
err |= rdr->op("", &discard);
|
||||
oxReturnError(rdr->op("", &discard));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
walker->popNamePath();
|
||||
return err;
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename FH>
|
||||
ox::Error ioOp(MetalClawReader *rdr, MetalClawWalker<FH> *walker) {
|
||||
Error err = 0;
|
||||
auto &fields = walker->type()->fieldList;
|
||||
auto type = walker->type();
|
||||
if (!type) {
|
||||
return OxError(1);
|
||||
}
|
||||
auto typeName = type->typeName.c_str();
|
||||
auto &fields = type->fieldList;
|
||||
rdr->setTypeInfo(typeName, fields.size());
|
||||
for (std::size_t i = 0; i < fields.size(); i++) {
|
||||
auto &field = fields[i];
|
||||
parseField(field, rdr, walker);
|
||||
if (field.type->primitiveType == mc::PrimitiveType::Struct) {
|
||||
}
|
||||
oxReturnError(parseField(field, rdr, walker));
|
||||
}
|
||||
return OxError(err);
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
template<typename Handler>
|
||||
ox::Error walkMC(mc::Type *type, uint8_t *data, std::size_t dataLen, Handler handler) {
|
||||
MetalClawWalker walker(type, handler);
|
||||
MetalClawReader rdr(data, dataLen);
|
||||
return ioOp(&rdr, &walker);
|
||||
}
|
||||
|
||||
}
|
||||
|
4
deps/ox/src/ox/std/hashmap.hpp
vendored
4
deps/ox/src/ox/std/hashmap.hpp
vendored
@ -18,8 +18,8 @@ class HashMap {
|
||||
|
||||
private:
|
||||
struct Pair {
|
||||
K key;
|
||||
T value;
|
||||
K key = {};
|
||||
T value = {};
|
||||
};
|
||||
Vector<K> m_keys;
|
||||
Vector<Pair*> m_pairs;
|
||||
|
2
deps/ox/src/ox/std/string.hpp
vendored
2
deps/ox/src/ox/std/string.hpp
vendored
@ -10,7 +10,7 @@
|
||||
|
||||
#include "memops.hpp"
|
||||
#include "strops.hpp"
|
||||
#include "types.hpp"
|
||||
#include "typetraits.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
|
20
deps/ox/src/ox/std/utility.hpp
vendored
Normal file
20
deps/ox/src/ox/std/utility.hpp
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2015 - 2019 gtalent2@gmail.com
|
||||
*
|
||||
* 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 "typetraits.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template<typename T>
|
||||
constexpr typename ox::remove_reference<T>::type &&move(T &&t) noexcept {
|
||||
return static_cast<typename ox::remove_reference<T>::type&&>(t);
|
||||
}
|
||||
|
||||
}
|
48
deps/ox/src/ox/std/vector.hpp
vendored
48
deps/ox/src/ox/std/vector.hpp
vendored
@ -9,6 +9,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "types.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
@ -39,6 +40,14 @@ class Vector {
|
||||
|
||||
const T &operator[](std::size_t i) const noexcept;
|
||||
|
||||
T &front() noexcept;
|
||||
|
||||
const T &front() const noexcept;
|
||||
|
||||
T &back() noexcept;
|
||||
|
||||
const T &back() const noexcept;
|
||||
|
||||
std::size_t size() const noexcept;
|
||||
|
||||
void resize(std::size_t size) noexcept;
|
||||
@ -47,6 +56,9 @@ class Vector {
|
||||
|
||||
bool contains(T) const noexcept;
|
||||
|
||||
template<typename... Args>
|
||||
void emplace_back(Args&&... args) noexcept;
|
||||
|
||||
void push_back(const T &item) noexcept;
|
||||
|
||||
void pop_back() noexcept;
|
||||
@ -85,7 +97,7 @@ Vector<T>::Vector(Vector<T> &other) noexcept {
|
||||
m_cap = other.m_cap;
|
||||
m_items = new T[m_cap];
|
||||
for (std::size_t i = 0; i < m_size; i++) {
|
||||
m_items[i] = other.m_items[i];
|
||||
m_items[i] = ox::move(other.m_items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -139,6 +151,26 @@ const T &Vector<T>::operator[](std::size_t i) const noexcept {
|
||||
return m_items[i];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T &Vector<T>::front() noexcept {
|
||||
return m_items[0];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T &Vector<T>::front() const noexcept {
|
||||
return m_items[0];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T &Vector<T>::back() noexcept {
|
||||
return m_items[m_size - 1];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const T &Vector<T>::back() const noexcept {
|
||||
return m_items[m_size - 1];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::size_t Vector<T>::size() const noexcept {
|
||||
return m_size;
|
||||
@ -170,6 +202,16 @@ bool Vector<T>::contains(T v) const noexcept {
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename... Args>
|
||||
void Vector<T>::emplace_back(Args&&... args) noexcept {
|
||||
if (m_size == m_cap) {
|
||||
expandCap(m_cap ? m_cap * 2 : 100);
|
||||
}
|
||||
new (&m_items[m_size]) T{args...};
|
||||
++m_size;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void Vector<T>::push_back(const T &item) noexcept {
|
||||
if (m_size == m_cap) {
|
||||
@ -206,10 +248,10 @@ void Vector<T>::expandCap(std::size_t cap) noexcept {
|
||||
if (oldItems) { // move over old items
|
||||
const auto itRange = cap > m_size ? m_size : cap;
|
||||
for (std::size_t i = 0; i < itRange; i++) {
|
||||
m_items[i] = oldItems[i];
|
||||
m_items[i] = ox::move(oldItems[i]);
|
||||
}
|
||||
for (std::size_t i = itRange; i < m_cap; i++) {
|
||||
m_items[i] = T();
|
||||
new (&m_items[i]) T;
|
||||
}
|
||||
delete[] oldItems;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user