From b3fa531aa0bb6c02167042c1ae2c0609d544ee5d Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Thu, 16 Apr 2020 22:21:59 -0500 Subject: [PATCH] [ox/model] Add support to SerStr for allocating string --- deps/ox/src/ox/mc/read.cpp | 10 +++++++--- deps/ox/src/ox/mc/test/tests.cpp | 12 +++++++++++- deps/ox/src/ox/mc/write.cpp | 2 +- deps/ox/src/ox/model/types.hpp | 17 ++++++++++++++--- deps/ox/src/ox/std/strops.hpp | 12 ++++++++++++ 5 files changed, 45 insertions(+), 8 deletions(-) diff --git a/deps/ox/src/ox/mc/read.cpp b/deps/ox/src/ox/mc/read.cpp index dd780c44..ba7349e0 100644 --- a/deps/ox/src/ox/mc/read.cpp +++ b/deps/ox/src/ox/mc/read.cpp @@ -83,11 +83,12 @@ Error MetalClawReader::field(const char*, SerStr val) { auto [size, err] = mc::decodeInteger(&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(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; diff --git a/deps/ox/src/ox/mc/test/tests.cpp b/deps/ox/src/ox/mc/test/tests.cpp index f19f2ad5..7ba076ec 100644 --- a/deps/ox/src/ox/mc/test/tests.cpp +++ b/deps/ox/src/ox/mc/test/tests.cpp @@ -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 @@ -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 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 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"); diff --git a/deps/ox/src/ox/mc/write.cpp b/deps/ox/src/ox/mc/write.cpp index 1facd371..93915e68 100644 --- a/deps/ox/src/ox/mc/write.cpp +++ b/deps/ox/src/ox/mc/write.cpp @@ -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) { diff --git a/deps/ox/src/ox/model/types.hpp b/deps/ox/src/ox/model/types.hpp index aa60e1c1..6716ba9e 100644 --- a/deps/ox/src/ox/model/types.hpp +++ b/deps/ox/src/ox/model/types.hpp @@ -20,6 +20,7 @@ class SerStr { protected: int m_cap = 0; char *m_str = nullptr; + char **m_tgt = nullptr; public: template @@ -33,6 +34,12 @@ class SerStr { m_cap = cap; } + constexpr SerStr(char **tgt, int cap = -1) noexcept { + m_tgt = tgt; + m_str = const_cast(*tgt); + m_cap = cap; + } + template 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 { diff --git a/deps/ox/src/ox/std/strops.hpp b/deps/ox/src/ox/std/strops.hpp index 4d17351f..b4beb099 100644 --- a/deps/ox/src/ox/std/strops.hpp +++ b/deps/ox/src/ox/std/strops.hpp @@ -12,6 +12,18 @@ #include "types.hpp" #include "typetraits.hpp" +template +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 constexpr char *ox_strncpy(T1 dest, T2 src, std::size_t maxLen) noexcept { std::size_t i = 0;