diff --git a/src/yycc/carton/binstore/serializer.hpp b/src/yycc/carton/binstore/serializer.hpp index f71a184..c7965e5 100644 --- a/src/yycc/carton/binstore/serializer.hpp +++ b/src/yycc/carton/binstore/serializer.hpp @@ -61,15 +61,15 @@ namespace yycc::carton::binstore::serializer { if (value > TMax || value < TMin) return std::nullopt; NS_YYCC_BINSTORE_TYPES::ByteArray ba; - ba.ResizeData(VALUE_SIZE); - std::memcpy(ba.GetDataPtr(), &value, VALUE_SIZE); + ba.resize_data(VALUE_SIZE); + std::memcpy(ba.get_data_ptr(), &value, VALUE_SIZE); return ba; } std::optional deserialize(const NS_YYCC_BINSTORE_TYPES::ByteArray& ba) const { - if (ba.GetDataSize() != VALUE_SIZE) return std::nullopt; + if (ba.get_data_size() != VALUE_SIZE) return std::nullopt; ValueType value; - std::memcpy(&value, ba.GetDataPtr(), VALUE_SIZE); + std::memcpy(&value, ba.get_data_ptr(), VALUE_SIZE); if (value > TMax || value < TMin) return std::nullopt; return value; @@ -103,16 +103,16 @@ namespace yycc::carton::binstore::serializer { if (value > TMax || value < TMin) return std::nullopt; NS_YYCC_BINSTORE_TYPES::ByteArray ba; - ba.ResizeData(VALUE_SIZE); - std::memcpy(ba.GetDataPtr(), &value, VALUE_SIZE); + ba.resize_data(VALUE_SIZE); + std::memcpy(ba.get_data_ptr(), &value, VALUE_SIZE); return ba; } std::optional deserialize(const NS_YYCC_BINSTORE_TYPES::ByteArray& ba) const { - if (ba.GetDataSize() != VALUE_SIZE) return std::nullopt; + if (ba.get_data_size() != VALUE_SIZE) return std::nullopt; ValueType value; - std::memcpy(&value, ba.GetDataPtr(), VALUE_SIZE); + std::memcpy(&value, ba.get_data_ptr(), VALUE_SIZE); if (value > TMax || value < TMin) return std::nullopt; return value; } @@ -130,16 +130,16 @@ namespace yycc::carton::binstore::serializer { std::optional serialize(const ValueType& value) const { NS_YYCC_BINSTORE_TYPES::ByteArray ba; - ba.ResizeData(VALUE_SIZE); - std::memcpy(ba.GetDataPtr(), &value, VALUE_SIZE); + ba.resize_data(VALUE_SIZE); + std::memcpy(ba.get_data_ptr(), &value, VALUE_SIZE); return ba; } std::optional deserialize(const NS_YYCC_BINSTORE_TYPES::ByteArray& ba) const { - if (ba.GetDataSize() != VALUE_SIZE) return std::nullopt; + if (ba.get_data_size() != VALUE_SIZE) return std::nullopt; ValueType value; - std::memcpy(&value, ba.GetDataPtr(), VALUE_SIZE); + std::memcpy(&value, ba.get_data_ptr(), VALUE_SIZE); return value; } @@ -160,12 +160,12 @@ namespace yycc::carton::binstore::serializer { // Prepare byte array and allocate size. NS_YYCC_BINSTORE_TYPES::ByteArray ba; - ba.ResizeData(HEADER_SIZE + length); + ba.resize_data(HEADER_SIZE + length); // Copy length first - std::memcpy(ba.GetDataPtr(), &length, HEADER_SIZE); + std::memcpy(ba.get_data_ptr(), &length, HEADER_SIZE); // Copy string data - std::memcpy(ba.GetDataPtr(HEADER_SIZE), value.data(), length); + std::memcpy(ba.get_data_ptr(HEADER_SIZE), value.data(), length); // Okey return ba; @@ -173,20 +173,20 @@ namespace yycc::carton::binstore::serializer { std::optional deserialize(const NS_YYCC_BINSTORE_TYPES::ByteArray& ba) const { // Get byte array size - size_t ba_size = ba.GetDataSize(); + size_t ba_size = ba.get_data_size(); // Check whether it has header if (ba_size < HEADER_SIZE) return std::nullopt; // Get header HeaderType length; - std::memcpy(&length, ba.GetDataPtr(), HEADER_SIZE); + std::memcpy(&length, ba.get_data_ptr(), HEADER_SIZE); // Check whether full size is header + length. if (ba_size != HEADER_SIZE + length) return std::nullopt; // Prepare result std::u8string value(length, u8'\0'); // Read into result - std::memcpy(value.data(), ba.GetDataPtr(HEADER_SIZE), length); + std::memcpy(value.data(), ba.get_data_ptr(HEADER_SIZE), length); // Okey return value; diff --git a/src/yycc/carton/binstore/storage.cpp b/src/yycc/carton/binstore/storage.cpp index 8967a24..1726975 100644 --- a/src/yycc/carton/binstore/storage.cpp +++ b/src/yycc/carton/binstore/storage.cpp @@ -1,12 +1,85 @@ #include "storage.hpp" +#include "../../num/safe_cast.hpp" #include +#include +#include #define TYPES ::yycc::carton::binstore::types #define CFG ::yycc::carton::binstore::configuration #define SERDES ::yycc::carton::binstore::serializer +#define SAFECAST ::yycc::num::safe_cast namespace yycc::carton::binstore::storage { +#pragma region Read and Write Helper Functions + + static bool read_buffer(std::istream& s, void* buffer, size_t length) { + // Cast length + auto rv_length = SAFECAST::try_to(length); + if (!rv_length.has_value()) return false; + auto cast_length = rv_length.value(); + + // Read data. + s.read(static_cast(buffer), cast_length); + // Check read count. + if (s.gcount() != cast_length) return false; + // Return IO status. + return s.good(); + } + + template + requires std::is_pod_v + static bool read_pod(std::istream& s, T& val) { + return read_buffer(s, &val, sizeof(T)); + } + + static bool read_byte_array(std::istream& s, TYPES::ByteArray& ba) { + size_t length = 0; + if (!read_pod(s, length)) return false; + + // Resize byte array. + // There is an exception may be thrown that resized length is too large. + // We need capture it and return error. + try { + ba.resize_data(length); + } catch (const std::exception&) { + return false; + } + // Read data into byte array. + read_buffer(s, ba.get_data_ptr(), length); + // Okey + return true; + } + + static bool write_buffer(std::ostream& s, const void* buffer, size_t length) { + // Cast length + auto rv_length = SAFECAST::try_to(length); + if (!rv_length.has_value()) return false; + auto cast_length = rv_length.value(); + + // Write data. + s.write(static_cast(buffer), cast_length); + // There is no function to tell how many data was written, + // so directly return. + return s.good(); + } + + template + requires std::is_pod_v + static bool write_pod(std::ostream& s, const T& val) { + return write_buffer(s, &val, sizeof(T)); + } + + static bool write_byte_array(std::ostream& s, const TYPES::ByteArray& ba) { + // Write length header. + auto length = ba.get_data_size(); + if (!write_pod(s, length)) return false; + // Write body + return write_buffer(s, ba.get_data_ptr(), length); + } + +#pragma endregion + #pragma region Storage Class Storage::Storage(CFG::Configuration&& cfg) : cfg(std::move(cfg)), raws() {} diff --git a/src/yycc/carton/binstore/types.cpp b/src/yycc/carton/binstore/types.cpp index 53e11ba..4b44e91 100644 --- a/src/yycc/carton/binstore/types.cpp +++ b/src/yycc/carton/binstore/types.cpp @@ -8,19 +8,19 @@ namespace yycc::carton::binstore::types { ByteArray::~ByteArray() {} - size_t ByteArray::GetDataSize() const { + size_t ByteArray::get_data_size() const { return this->datas.size(); } - void ByteArray::ResizeData(size_t new_size) { + void ByteArray::resize_data(size_t new_size) { this->datas.resize(new_size); } - const void* ByteArray::GetDataPtr(size_t offset) const { + const void* ByteArray::get_data_ptr(size_t offset) const { return this->datas.data() + offset; } - void* ByteArray::GetDataPtr(size_t offset) { + void* ByteArray::get_data_ptr(size_t offset) { return this->datas.data() + offset; } diff --git a/src/yycc/carton/binstore/types.hpp b/src/yycc/carton/binstore/types.hpp index c8fd6ae..c308f2a 100644 --- a/src/yycc/carton/binstore/types.hpp +++ b/src/yycc/carton/binstore/types.hpp @@ -51,27 +51,27 @@ namespace yycc::carton::binstore::types { * @remarks This is usually used when reading data. * @return The length of internal buffer. */ - size_t GetDataSize() const; + size_t get_data_size() const; /** * @brief Resize internal buffer to given size. * @remarks This is usually used when writing data. * @param[in] new_size The new size of internal buffer. */ - void ResizeData(size_t new_size); + void resize_data(size_t new_size); /** * @brief Get data pointer to internal buffer for reading. * @remarks This is usually used when reading data. * @param[in] offset The offset in byte added to underlying pointer. * @return The data pointer to internal buffer. */ - const void* GetDataPtr(size_t offset = 0) const; + const void* get_data_ptr(size_t offset = 0) const; /** * @brief Get data pointer to internal buffer for writing. * @remarks This is usually used when writing data. * @param[in] offset The offset in byte added to underlying pointer. * @return The data pointer to internal buffer. */ - void* GetDataPtr(size_t offset = 0); + void* get_data_ptr(size_t offset = 0); private: std::vector datas; ///< The internal buffer.