[ox] Cleanup MetalClawWriter and FieldBitmapWriter
This commit is contained in:
1
deps/ox/src/ox/mc/CMakeLists.txt
vendored
1
deps/ox/src/ox/mc/CMakeLists.txt
vendored
@@ -1,6 +1,5 @@
|
||||
add_library(
|
||||
OxMetalClaw
|
||||
presenceindicator.cpp
|
||||
read.cpp
|
||||
write.cpp
|
||||
)
|
||||
|
||||
17
deps/ox/src/ox/mc/presenceindicator.cpp
vendored
17
deps/ox/src/ox/mc/presenceindicator.cpp
vendored
@@ -1,17 +0,0 @@
|
||||
/*
|
||||
* Copyright 2015 - 2025 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/.
|
||||
*/
|
||||
|
||||
#include "err.hpp"
|
||||
#include "presenceindicator.hpp"
|
||||
|
||||
namespace ox {
|
||||
|
||||
template class FieldBitmapWriterBase<uint8_t>;
|
||||
template class FieldBitmapWriterBase<uint8_t const>;
|
||||
|
||||
}
|
||||
222
deps/ox/src/ox/mc/presenceindicator.hpp
vendored
222
deps/ox/src/ox/mc/presenceindicator.hpp
vendored
@@ -22,145 +22,101 @@ namespace ox {
|
||||
template<Reader_c Reader>
|
||||
class FieldBitmapReader {
|
||||
protected:
|
||||
mutable size_t m_mapBlockIdx = ~size_t{0};
|
||||
mutable uint64_t m_mapBlock = 0;
|
||||
size_t m_mapStart = 0;
|
||||
mutable size_t m_mapBlockIdx = ~size_t{};
|
||||
mutable uint64_t m_mapBlock{};
|
||||
size_t m_mapStart{};
|
||||
Reader &m_reader;
|
||||
|
||||
public:
|
||||
explicit constexpr FieldBitmapReader(Reader &reader) noexcept;
|
||||
explicit constexpr FieldBitmapReader(Reader &reader) noexcept:
|
||||
m_mapStart(reader.tellg()),
|
||||
m_reader(reader) {
|
||||
}
|
||||
|
||||
constexpr Result<bool> get(size_t idx) const noexcept;
|
||||
constexpr Result<bool> get(size_t idx) const noexcept {
|
||||
constexpr auto blockBits = sizeof(m_mapBlock);
|
||||
auto const blockIdx = idx / blockBits;
|
||||
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
|
||||
OX_RETURN_ERROR(loadMapBlock(blockIdx));
|
||||
}
|
||||
idx %= blockBits;
|
||||
return (m_mapBlock >> idx) & 1;
|
||||
}
|
||||
|
||||
private:
|
||||
constexpr Error loadMapBlock(size_t idx) const noexcept;
|
||||
|
||||
};
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr FieldBitmapReader<Reader>::FieldBitmapReader(Reader &reader) noexcept:
|
||||
m_mapStart(reader.tellg()),
|
||||
m_reader(reader) {
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Result<bool> FieldBitmapReader<Reader>::get(size_t idx) const noexcept {
|
||||
constexpr auto blockBits = sizeof(m_mapBlock);
|
||||
auto const blockIdx = idx / blockBits;
|
||||
if (m_mapBlockIdx != blockIdx) [[unlikely]] {
|
||||
OX_RETURN_ERROR(loadMapBlock(blockIdx));
|
||||
}
|
||||
idx %= blockBits;
|
||||
return (m_mapBlock >> idx) & 1;
|
||||
}
|
||||
|
||||
template<Reader_c Reader>
|
||||
constexpr Error FieldBitmapReader<Reader>::loadMapBlock(size_t const idx) const noexcept {
|
||||
OX_REQUIRE(g, m_reader.tellg());
|
||||
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
|
||||
Array<char, sizeof(m_mapBlock)> mapBlock{};
|
||||
OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
|
||||
// Warning: narrow-conv
|
||||
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
|
||||
m_mapBlock = 0;
|
||||
for (uint64_t i{}; auto b : mapBlock) {
|
||||
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
|
||||
i += 8;
|
||||
}
|
||||
m_mapBlockIdx = idx;
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
class FieldBitmapWriterBase {
|
||||
protected:
|
||||
Span<T> m_map;
|
||||
size_t m_mapLen = 0;
|
||||
|
||||
public:
|
||||
explicit constexpr FieldBitmapWriterBase(Span<T> map) noexcept;
|
||||
|
||||
constexpr auto setBuffer(Span<T> map) noexcept;
|
||||
|
||||
constexpr Result<bool> get(size_t i) const noexcept;
|
||||
|
||||
constexpr Error setFields(int) noexcept;
|
||||
|
||||
constexpr void setMaxLen(int) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
constexpr int64_t getMaxLen() const noexcept;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr FieldBitmapWriterBase<T>::FieldBitmapWriterBase(Span<T> map) noexcept:
|
||||
m_map(map),
|
||||
m_mapLen(m_map.size()) {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr auto FieldBitmapWriterBase<T>::setBuffer(Span<T> map) noexcept {
|
||||
m_map = map;
|
||||
m_mapLen = map.size();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Result<bool> FieldBitmapWriterBase<T>::get(size_t const i) const noexcept {
|
||||
if (i / 8 < m_mapLen) {
|
||||
return (m_map[i / 8] >> (i % 8)) & 1;
|
||||
} else {
|
||||
return Error{McPresenceMapOverflow};
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr Error FieldBitmapWriterBase<T>::setFields(int const fields) noexcept {
|
||||
m_mapLen = static_cast<size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
||||
if (m_mapLen > m_map.size()) [[unlikely]] {
|
||||
return Error{McPresenceMapOverflow};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr void FieldBitmapWriterBase<T>::setMaxLen(int const maxLen) noexcept {
|
||||
m_mapLen = static_cast<size_t>(maxLen);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
constexpr int64_t FieldBitmapWriterBase<T>::getMaxLen() const noexcept {
|
||||
return static_cast<int64_t>(m_mapLen);
|
||||
}
|
||||
|
||||
extern template class FieldBitmapWriterBase<uint8_t>;
|
||||
extern template class FieldBitmapWriterBase<uint8_t const>;
|
||||
|
||||
class FieldBitmap: public FieldBitmapWriterBase<uint8_t> {
|
||||
|
||||
public:
|
||||
explicit constexpr FieldBitmap(Span<uint8_t> map) noexcept;
|
||||
|
||||
constexpr Error set(size_t i, bool on) noexcept;
|
||||
|
||||
};
|
||||
|
||||
constexpr FieldBitmap::FieldBitmap(Span<uint8_t> map) noexcept:
|
||||
FieldBitmapWriterBase(map) {
|
||||
}
|
||||
|
||||
constexpr Error FieldBitmap::set(size_t const i, bool const on) noexcept {
|
||||
if (i / 8 < m_mapLen) {
|
||||
if (on) {
|
||||
m_map[i / 8] |= 1 << (i % 8);
|
||||
} else {
|
||||
m_map[i / 8] &= ~static_cast<uint8_t>(1 << (i % 8));
|
||||
constexpr Error loadMapBlock(size_t const idx) const noexcept {
|
||||
OX_REQUIRE(g, m_reader.tellg());
|
||||
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(m_mapStart + idx), ox::ios_base::beg));
|
||||
Array<char, sizeof(m_mapBlock)> mapBlock{};
|
||||
OX_RETURN_ERROR(m_reader.read(mapBlock.data(), sizeof(m_mapBlock)));
|
||||
// Warning: narrow-conv
|
||||
OX_RETURN_ERROR(m_reader.seekg(static_cast<int>(g), ox::ios_base::beg));
|
||||
m_mapBlock = 0;
|
||||
for (uint64_t i{}; auto b : mapBlock) {
|
||||
m_mapBlock |= static_cast<uint64_t>(std::bit_cast<uint8_t>(b)) << i;
|
||||
i += 8;
|
||||
}
|
||||
m_mapBlockIdx = idx;
|
||||
return {};
|
||||
}
|
||||
return {};
|
||||
} else {
|
||||
return Error(McPresenceMapOverflow);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class FieldBitmapWriter {
|
||||
protected:
|
||||
Span<char> m_map;
|
||||
size_t m_mapLen{};
|
||||
|
||||
public:
|
||||
explicit constexpr FieldBitmapWriter(Span<char> const &map) noexcept:
|
||||
m_map(map),
|
||||
m_mapLen(m_map.size()) {
|
||||
}
|
||||
|
||||
constexpr auto setBuffer(Span<char> const &map) noexcept {
|
||||
m_map = map;
|
||||
m_mapLen = map.size();
|
||||
}
|
||||
|
||||
constexpr Result<bool> get(size_t const i) const noexcept {
|
||||
if (i / 8 < m_mapLen) {
|
||||
return (std::bit_cast<uint8_t>(m_map[i / 8]) >> (i % 8)) & 1;
|
||||
}
|
||||
return Error{McPresenceMapOverflow};
|
||||
}
|
||||
|
||||
constexpr Error setFields(int const fields) noexcept {
|
||||
m_mapLen = static_cast<size_t>((fields / 8 + 1) - (fields % 8 == 0));
|
||||
if (m_mapLen > m_map.size()) [[unlikely]] {
|
||||
return Error{McPresenceMapOverflow};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr void setMaxLen(int const maxLen) noexcept {
|
||||
m_mapLen = static_cast<size_t>(maxLen);
|
||||
}
|
||||
|
||||
constexpr int64_t getMaxLen() const noexcept {
|
||||
return static_cast<int64_t>(m_mapLen);
|
||||
}
|
||||
|
||||
constexpr Error set(size_t const i, bool const on) noexcept {
|
||||
if (i / 8 < m_mapLen) {
|
||||
char &actual = m_map[i / 8];
|
||||
uint8_t v = std::bit_cast<uint8_t>(actual);
|
||||
if (on) {
|
||||
v |= 1 << (i % 8);
|
||||
} else {
|
||||
v &= ~static_cast<uint8_t>(1 << (i % 8));
|
||||
}
|
||||
actual = std::bit_cast<char>(v);
|
||||
return {};
|
||||
}
|
||||
return Error{McPresenceMapOverflow};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
49
deps/ox/src/ox/mc/write.hpp
vendored
49
deps/ox/src/ox/mc/write.hpp
vendored
@@ -29,12 +29,12 @@
|
||||
namespace ox {
|
||||
|
||||
template<Writer_c Writer>
|
||||
class MetalClawWriter {
|
||||
class MetalClawWriter: public ModelHandlerBase<MetalClawWriter<Writer>, OpType::Write> {
|
||||
|
||||
private:
|
||||
Vector<uint8_t, 16> m_presenceMapBuff{};
|
||||
FieldBitmap m_fieldPresence;
|
||||
int m_field = 0;
|
||||
Vector<char, 16> m_presenceMapBuff{};
|
||||
FieldBitmapWriter m_fieldPresence{m_presenceMapBuff};
|
||||
int m_field{};
|
||||
Optional<int> m_unionIdx;
|
||||
size_t m_writerBeginP{};
|
||||
Writer &m_writer;
|
||||
@@ -105,12 +105,7 @@ class MetalClawWriter {
|
||||
return 0;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
static constexpr auto opType() noexcept {
|
||||
return OpType::Write;
|
||||
}
|
||||
|
||||
Error finalize() noexcept;
|
||||
constexpr Error finalize() noexcept;
|
||||
|
||||
private:
|
||||
constexpr Error appendInteger(Integer_c auto val) noexcept {
|
||||
@@ -132,7 +127,6 @@ extern template class ModelHandlerInterface<MetalClawWriter<CharBuffWriter>>;
|
||||
|
||||
template<Writer_c Writer>
|
||||
constexpr MetalClawWriter<Writer>::MetalClawWriter(Writer &writer, Optional<int> const &unionIdx) noexcept:
|
||||
m_fieldPresence(m_presenceMapBuff),
|
||||
m_unionIdx(unionIdx),
|
||||
m_writerBeginP(writer.tellp()),
|
||||
m_writer(writer) {
|
||||
@@ -267,9 +261,8 @@ constexpr Error MetalClawWriter<Writer>::field(CString, T const *val) noexcept {
|
||||
bool fieldSet = false;
|
||||
if (val && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
auto const writeIdx = m_writer.tellp();
|
||||
MetalClawWriter<Writer> writer(m_writer);
|
||||
ModelHandlerInterface<MetalClawWriter<Writer>> handler{writer};
|
||||
OX_RETURN_ERROR(model(&handler, val));
|
||||
MetalClawWriter writer(m_writer);
|
||||
OX_RETURN_ERROR(model(writer.interface(), val));
|
||||
OX_RETURN_ERROR(writer.finalize());
|
||||
fieldSet = writeIdx != m_writer.tellp();
|
||||
}
|
||||
@@ -285,9 +278,8 @@ constexpr Error MetalClawWriter<Writer>::field(CString, UnionView<U, force> val)
|
||||
bool fieldSet = false;
|
||||
if (val.get() && (!m_unionIdx.has_value() || *m_unionIdx == m_field)) {
|
||||
auto const writeIdx = m_writer.tellp();
|
||||
MetalClawWriter<Writer> writer(m_writer, Optional<int>(in_place, val.idx()));
|
||||
ModelHandlerInterface handler{writer};
|
||||
OX_RETURN_ERROR(model(&handler, val.get()));
|
||||
MetalClawWriter writer(m_writer, Optional<int>(in_place, val.idx()));
|
||||
OX_RETURN_ERROR(model(writer.interface(), val.get()));
|
||||
OX_RETURN_ERROR(writer.finalize());
|
||||
fieldSet = writeIdx != m_writer.tellp();
|
||||
}
|
||||
@@ -305,13 +297,12 @@ constexpr Error MetalClawWriter<Writer>::field(CString, T const *val, size_t con
|
||||
auto const arrLen = mc::encodeInteger(len);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(arrLen.data.data()), arrLen.length));
|
||||
auto const writeIdx = m_writer.tellp();
|
||||
MetalClawWriter<Writer> writer(m_writer);
|
||||
ModelHandlerInterface handler{writer};
|
||||
OX_RETURN_ERROR(handler.template setTypeInfo<T>("List", 0, {}, static_cast<size_t>(len)));
|
||||
MetalClawWriter writer(m_writer);
|
||||
OX_RETURN_ERROR(writer.interface()->template setTypeInfo<T>("List", 0, {}, static_cast<size_t>(len)));
|
||||
// write the array
|
||||
for (size_t i{}; i < len; ++i) {
|
||||
OX_ALLOW_UNSAFE_BUFFERS_BEGIN
|
||||
OX_RETURN_ERROR(handler.field("", &val[i]));
|
||||
OX_RETURN_ERROR(writer.interface()->field("", &val[i]));
|
||||
OX_ALLOW_UNSAFE_BUFFERS_END
|
||||
}
|
||||
OX_RETURN_ERROR(writer.finalize());
|
||||
@@ -333,10 +324,9 @@ constexpr Error MetalClawWriter<Writer>::field(CString, HashMap<String, T> const
|
||||
auto const arrLen = mc::encodeInteger(len);
|
||||
OX_RETURN_ERROR(m_writer.write(reinterpret_cast<CString>(arrLen.data.data()), arrLen.length));
|
||||
// write map
|
||||
MetalClawWriter<Writer> writer(m_writer);
|
||||
ModelHandlerInterface handler{writer};
|
||||
MetalClawWriter writer(m_writer);
|
||||
// double len for both key and value
|
||||
OX_RETURN_ERROR(handler.setTypeInfo("Map", 0, {}, len * 2));
|
||||
OX_RETURN_ERROR(writer.interface()->setTypeInfo("Map", 0, {}, len * 2));
|
||||
// this loop body needs to be in a lambda because of the potential alloca call
|
||||
constexpr auto loopBody = [](auto &handler, auto const &key, auto const &val) -> Error {
|
||||
auto const keyLen = key.size();
|
||||
@@ -349,7 +339,7 @@ constexpr Error MetalClawWriter<Writer>::field(CString, HashMap<String, T> const
|
||||
// write the array
|
||||
for (size_t i{}; i < len; ++i) {
|
||||
auto const &key = keys[i];
|
||||
OX_RETURN_ERROR(loopBody(handler, key, *val));
|
||||
OX_RETURN_ERROR(loopBody(*writer.interface(), key, *val));
|
||||
}
|
||||
OX_RETURN_ERROR(writer.finalize());
|
||||
fieldSet = true;
|
||||
@@ -374,20 +364,19 @@ constexpr Error MetalClawWriter<Writer>::setTypeInfo(
|
||||
}
|
||||
|
||||
template<Writer_c Writer>
|
||||
Error MetalClawWriter<Writer>::finalize() noexcept {
|
||||
constexpr Error MetalClawWriter<Writer>::finalize() noexcept {
|
||||
auto const end = m_writer.tellp();
|
||||
OX_RETURN_ERROR(m_writer.seekp(m_writerBeginP));
|
||||
OX_RETURN_ERROR(m_writer.write(
|
||||
reinterpret_cast<CString>(m_presenceMapBuff.data()),
|
||||
m_presenceMapBuff.size()));
|
||||
m_presenceMapBuff.data(),
|
||||
m_presenceMapBuff.size()));
|
||||
OX_RETURN_ERROR(m_writer.seekp(end));
|
||||
return {};
|
||||
}
|
||||
|
||||
Result<Buffer> writeMC(Writer_c auto &writer, auto const &val) noexcept {
|
||||
MetalClawWriter mcWriter(writer);
|
||||
ModelHandlerInterface handler{mcWriter};
|
||||
OX_RETURN_ERROR(model(&handler, &val));
|
||||
OX_RETURN_ERROR(model(mcWriter.interface(), &val));
|
||||
OX_RETURN_ERROR(mcWriter.finalize());
|
||||
return {};
|
||||
}
|
||||
|
||||
16
deps/ox/src/ox/model/modelhandleradaptor.hpp
vendored
16
deps/ox/src/ox/model/modelhandleradaptor.hpp
vendored
@@ -123,7 +123,7 @@ class ModelHandlerInterface {
|
||||
{
|
||||
auto &u = v->template get<ModelUnion>();
|
||||
if constexpr(opType_v == OpType::Read) {
|
||||
u.setActiveField(m_handler.whichFieldPresent(name, u));
|
||||
u.setActiveField(whichFieldPresent(m_handler, 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()));
|
||||
@@ -199,6 +199,20 @@ class ModelHandlerInterface {
|
||||
constexpr auto handler() noexcept {
|
||||
return m_handler;
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename H>
|
||||
static constexpr int whichFieldPresent(H &h, const char *name, ModelUnion const &u) noexcept
|
||||
requires(H::opType() == OpType::Read) {
|
||||
return h.whichFieldPresent(name, u);
|
||||
}
|
||||
|
||||
template<typename H>
|
||||
static constexpr int whichFieldPresent(H&, const char*, ModelUnion const&) noexcept
|
||||
requires(H::opType() != OpType::Read) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename Handler, OpType opType_v = Handler::opType()>
|
||||
|
||||
6
deps/ox/src/ox/model/modelvalue.hpp
vendored
6
deps/ox/src/ox/model/modelvalue.hpp
vendored
@@ -200,8 +200,6 @@ class ModelValue {
|
||||
template<typename T>
|
||||
constexpr Error set(T &&v) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(ModelValue &val) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(const ModelValue &val) noexcept;
|
||||
|
||||
constexpr ModelValue &operator=(ModelValue &&val) noexcept;
|
||||
@@ -1202,10 +1200,6 @@ constexpr Error ModelValue::set(T &&v) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
constexpr ModelValue &ModelValue::operator=(ModelValue &other) noexcept {
|
||||
return this->operator=(const_cast<const ModelValue&>(other));
|
||||
}
|
||||
|
||||
constexpr ModelValue &ModelValue::operator=(const ModelValue &other) noexcept {
|
||||
if (this == &other) [[unlikely]] {
|
||||
return *this;
|
||||
|
||||
Reference in New Issue
Block a user