[ox/mc] Add basic walking of data by data descriptor

(synced from cd91f6b60a)
This commit is contained in:
2019-03-07 06:05:08 -06:00
parent 66ee721678
commit c212ebeda7
15 changed files with 571 additions and 168 deletions
+46 -46
View File
@@ -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());
}