[ox/model] Add support to SerStr for allocating string

This commit is contained in:
Gary Talent 2020-04-16 22:21:59 -05:00
parent 8753d39b66
commit b3fa531aa0
5 changed files with 45 additions and 8 deletions

View File

@ -83,11 +83,12 @@ Error MetalClawReader::field(const char*, SerStr val) {
auto [size, err] = mc::decodeInteger<StringLength>(&m_buff[m_buffIt], m_buffLen - m_buffIt, &bytesRead);
m_buffIt += bytesRead;
oxReturnError(err);
auto data = val.data(size + 1);
// read the string
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);
val.data()[size] = 0;
ox_memcpy(data, &m_buff[m_buffIt], size);
data[size] = 0;
m_buffIt += size;
} else {
return OxError(MC_BUFFENDED);
@ -96,7 +97,10 @@ Error MetalClawReader::field(const char*, SerStr val) {
return OxError(MC_OUTBUFFENDED);
}
} else {
val.data()[0] = 0;
auto data = val.data();
if (data) {
data[0] = 0;
}
}
}
++m_field;

View File

@ -36,7 +36,7 @@ struct TestStructNest {
struct TestStruct {
static constexpr auto TypeName = "TestStruct";
static constexpr auto Fields = 15;
static constexpr auto Fields = 16;
bool Bool = false;
int32_t Int = 0;
int32_t Int1 = 0;
@ -48,10 +48,16 @@ struct TestStruct {
int32_t Int7 = 0;
int32_t Int8 = 0;
TestUnion Union;
char *CString = nullptr;
ox::BString<32> String = "";
uint32_t List[4] = {0, 0, 0, 0};
TestStructNest EmptyStruct;
TestStructNest Struct;
~TestStruct() {
delete[] CString;
}
};
template<typename T>
@ -86,6 +92,7 @@ ox::Error model(T *io, TestStruct *obj) {
oxReturnError(io->field("Int7", &obj->Int7));
oxReturnError(io->field("Int8", &obj->Int8));
oxReturnError(io->field("Union", ox::UnionView{&obj->Union, 1}));
oxReturnError(io->field("CString", ox::SerStr(&obj->CString)));
oxReturnError(io->field("String", &obj->String));
oxReturnError(io->field("List", obj->List, 4));
oxReturnError(io->field("EmptyStruct", &obj->EmptyStruct));
@ -120,6 +127,8 @@ std::map<std::string, ox::Error(*)()> tests = {
testIn.Int = 42;
testIn.Union.Int = 42;
testIn.String = "Test String 1";
testIn.CString = new char[ox_strlen("c-string") + 1];
ox_strcpy(testIn.CString, "c-string");
testIn.List[0] = 1;
testIn.List[1] = 2;
testIn.List[2] = 3;
@ -142,6 +151,7 @@ std::map<std::string, ox::Error(*)()> tests = {
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(ox_strcmp(testIn.CString, testOut.CString) == 0, "CString value mismatch");
oxAssert(testIn.Union.Int == testOut.Union.Int, "Union.Int value mismatch");
oxAssert(testIn.String == testOut.String, "String value mismatch");
oxAssert(testIn.List[0] == testOut.List[0], "List[0] value mismatch");

View File

@ -68,7 +68,7 @@ Error MetalClawWriter::field(const char*, bool *val) noexcept {
Error MetalClawWriter::field(const char*, SerStr val) noexcept {
bool fieldSet = false;
if (val.cap() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
if (val.len() && (m_unionIdx == -1 || m_unionIdx == m_field)) {
// write the length
const auto strLen = mc::encodeInteger(val.len());
if (m_buffIt + strLen.length + val.len() < m_buffLen) {

View File

@ -20,6 +20,7 @@ class SerStr {
protected:
int m_cap = 0;
char *m_str = nullptr;
char **m_tgt = nullptr;
public:
template<std::size_t sz>
@ -33,6 +34,12 @@ class SerStr {
m_cap = cap;
}
constexpr SerStr(char **tgt, int cap = -1) noexcept {
m_tgt = tgt;
m_str = const_cast<char*>(*tgt);
m_cap = cap;
}
template<std::size_t cap>
constexpr SerStr(char (&str)[cap]) noexcept {
m_str = str;
@ -43,13 +50,17 @@ class SerStr {
return m_str;
}
constexpr char *data() noexcept {
// do not return a non-const pointer to the const_casted m_str
constexpr char *data(std::size_t sz = 0) noexcept {
if (m_tgt && sz) {
*m_tgt = new char[sz];
m_str = *m_tgt;
m_cap = sz;
}
return m_str;
}
constexpr int len() noexcept {
return ox_strlen(m_str);
return m_str ? ox_strlen(m_str) : 0;
}
constexpr int cap() noexcept {

View File

@ -12,6 +12,18 @@
#include "types.hpp"
#include "typetraits.hpp"
template<typename T1, typename T2>
constexpr char *ox_strcpy(T1 dest, T2 src) noexcept {
std::size_t i = 0;
while (src[i]) {
dest[i] = src[i];
++i;
}
// set null terminator
dest[i] = 0;
return dest;
}
template<typename T1, typename T2>
constexpr char *ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept {
std::size_t i = 0;