feat: finish storage helper functions.
- finish IO read and write function for binstore storage. - refactor binstore ByteArray.
This commit is contained in:
@ -61,15 +61,15 @@ namespace yycc::carton::binstore::serializer {
|
|||||||
if (value > TMax || value < TMin) return std::nullopt;
|
if (value > TMax || value < TMin) return std::nullopt;
|
||||||
|
|
||||||
NS_YYCC_BINSTORE_TYPES::ByteArray ba;
|
NS_YYCC_BINSTORE_TYPES::ByteArray ba;
|
||||||
ba.ResizeData(VALUE_SIZE);
|
ba.resize_data(VALUE_SIZE);
|
||||||
std::memcpy(ba.GetDataPtr(), &value, VALUE_SIZE);
|
std::memcpy(ba.get_data_ptr(), &value, VALUE_SIZE);
|
||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ValueType> deserialize(const NS_YYCC_BINSTORE_TYPES::ByteArray& ba) const {
|
std::optional<ValueType> 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;
|
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;
|
if (value > TMax || value < TMin) return std::nullopt;
|
||||||
return value;
|
return value;
|
||||||
@ -103,16 +103,16 @@ namespace yycc::carton::binstore::serializer {
|
|||||||
if (value > TMax || value < TMin) return std::nullopt;
|
if (value > TMax || value < TMin) return std::nullopt;
|
||||||
|
|
||||||
NS_YYCC_BINSTORE_TYPES::ByteArray ba;
|
NS_YYCC_BINSTORE_TYPES::ByteArray ba;
|
||||||
ba.ResizeData(VALUE_SIZE);
|
ba.resize_data(VALUE_SIZE);
|
||||||
std::memcpy(ba.GetDataPtr(), &value, VALUE_SIZE);
|
std::memcpy(ba.get_data_ptr(), &value, VALUE_SIZE);
|
||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ValueType> deserialize(const NS_YYCC_BINSTORE_TYPES::ByteArray& ba) const {
|
std::optional<ValueType> 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;
|
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;
|
if (value > TMax || value < TMin) return std::nullopt;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
@ -130,16 +130,16 @@ namespace yycc::carton::binstore::serializer {
|
|||||||
|
|
||||||
std::optional<NS_YYCC_BINSTORE_TYPES::ByteArray> serialize(const ValueType& value) const {
|
std::optional<NS_YYCC_BINSTORE_TYPES::ByteArray> serialize(const ValueType& value) const {
|
||||||
NS_YYCC_BINSTORE_TYPES::ByteArray ba;
|
NS_YYCC_BINSTORE_TYPES::ByteArray ba;
|
||||||
ba.ResizeData(VALUE_SIZE);
|
ba.resize_data(VALUE_SIZE);
|
||||||
std::memcpy(ba.GetDataPtr(), &value, VALUE_SIZE);
|
std::memcpy(ba.get_data_ptr(), &value, VALUE_SIZE);
|
||||||
return ba;
|
return ba;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ValueType> deserialize(const NS_YYCC_BINSTORE_TYPES::ByteArray& ba) const {
|
std::optional<ValueType> 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;
|
ValueType value;
|
||||||
std::memcpy(&value, ba.GetDataPtr(), VALUE_SIZE);
|
std::memcpy(&value, ba.get_data_ptr(), VALUE_SIZE);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,12 +160,12 @@ namespace yycc::carton::binstore::serializer {
|
|||||||
|
|
||||||
// Prepare byte array and allocate size.
|
// Prepare byte array and allocate size.
|
||||||
NS_YYCC_BINSTORE_TYPES::ByteArray ba;
|
NS_YYCC_BINSTORE_TYPES::ByteArray ba;
|
||||||
ba.ResizeData(HEADER_SIZE + length);
|
ba.resize_data(HEADER_SIZE + length);
|
||||||
|
|
||||||
// Copy length first
|
// Copy length first
|
||||||
std::memcpy(ba.GetDataPtr(), &length, HEADER_SIZE);
|
std::memcpy(ba.get_data_ptr(), &length, HEADER_SIZE);
|
||||||
// Copy string data
|
// Copy string data
|
||||||
std::memcpy(ba.GetDataPtr(HEADER_SIZE), value.data(), length);
|
std::memcpy(ba.get_data_ptr(HEADER_SIZE), value.data(), length);
|
||||||
|
|
||||||
// Okey
|
// Okey
|
||||||
return ba;
|
return ba;
|
||||||
@ -173,20 +173,20 @@ namespace yycc::carton::binstore::serializer {
|
|||||||
|
|
||||||
std::optional<ValueType> deserialize(const NS_YYCC_BINSTORE_TYPES::ByteArray& ba) const {
|
std::optional<ValueType> deserialize(const NS_YYCC_BINSTORE_TYPES::ByteArray& ba) const {
|
||||||
// Get byte array size
|
// Get byte array size
|
||||||
size_t ba_size = ba.GetDataSize();
|
size_t ba_size = ba.get_data_size();
|
||||||
// Check whether it has header
|
// Check whether it has header
|
||||||
if (ba_size < HEADER_SIZE) return std::nullopt;
|
if (ba_size < HEADER_SIZE) return std::nullopt;
|
||||||
|
|
||||||
// Get header
|
// Get header
|
||||||
HeaderType length;
|
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.
|
// Check whether full size is header + length.
|
||||||
if (ba_size != HEADER_SIZE + length) return std::nullopt;
|
if (ba_size != HEADER_SIZE + length) return std::nullopt;
|
||||||
// Prepare result
|
// Prepare result
|
||||||
std::u8string value(length, u8'\0');
|
std::u8string value(length, u8'\0');
|
||||||
// Read into result
|
// Read into result
|
||||||
std::memcpy(value.data(), ba.GetDataPtr(HEADER_SIZE), length);
|
std::memcpy(value.data(), ba.get_data_ptr(HEADER_SIZE), length);
|
||||||
|
|
||||||
// Okey
|
// Okey
|
||||||
return value;
|
return value;
|
||||||
|
|||||||
@ -1,12 +1,85 @@
|
|||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
|
#include "../../num/safe_cast.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <concepts>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
#define TYPES ::yycc::carton::binstore::types
|
#define TYPES ::yycc::carton::binstore::types
|
||||||
#define CFG ::yycc::carton::binstore::configuration
|
#define CFG ::yycc::carton::binstore::configuration
|
||||||
#define SERDES ::yycc::carton::binstore::serializer
|
#define SERDES ::yycc::carton::binstore::serializer
|
||||||
|
#define SAFECAST ::yycc::num::safe_cast
|
||||||
|
|
||||||
namespace yycc::carton::binstore::storage {
|
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<std::streamsize>(length);
|
||||||
|
if (!rv_length.has_value()) return false;
|
||||||
|
auto cast_length = rv_length.value();
|
||||||
|
|
||||||
|
// Read data.
|
||||||
|
s.read(static_cast<std::istream::char_type*>(buffer), cast_length);
|
||||||
|
// Check read count.
|
||||||
|
if (s.gcount() != cast_length) return false;
|
||||||
|
// Return IO status.
|
||||||
|
return s.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
requires std::is_pod_v<T>
|
||||||
|
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<std::streamsize>(length);
|
||||||
|
if (!rv_length.has_value()) return false;
|
||||||
|
auto cast_length = rv_length.value();
|
||||||
|
|
||||||
|
// Write data.
|
||||||
|
s.write(static_cast<const std::istream::char_type*>(buffer), cast_length);
|
||||||
|
// There is no function to tell how many data was written,
|
||||||
|
// so directly return.
|
||||||
|
return s.good();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
requires std::is_pod_v<T>
|
||||||
|
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
|
#pragma region Storage Class
|
||||||
|
|
||||||
Storage::Storage(CFG::Configuration&& cfg) : cfg(std::move(cfg)), raws() {}
|
Storage::Storage(CFG::Configuration&& cfg) : cfg(std::move(cfg)), raws() {}
|
||||||
|
|||||||
@ -8,19 +8,19 @@ namespace yycc::carton::binstore::types {
|
|||||||
|
|
||||||
ByteArray::~ByteArray() {}
|
ByteArray::~ByteArray() {}
|
||||||
|
|
||||||
size_t ByteArray::GetDataSize() const {
|
size_t ByteArray::get_data_size() const {
|
||||||
return this->datas.size();
|
return this->datas.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ByteArray::ResizeData(size_t new_size) {
|
void ByteArray::resize_data(size_t new_size) {
|
||||||
this->datas.resize(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;
|
return this->datas.data() + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* ByteArray::GetDataPtr(size_t offset) {
|
void* ByteArray::get_data_ptr(size_t offset) {
|
||||||
return this->datas.data() + offset;
|
return this->datas.data() + offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -51,27 +51,27 @@ namespace yycc::carton::binstore::types {
|
|||||||
* @remarks This is usually used when reading data.
|
* @remarks This is usually used when reading data.
|
||||||
* @return The length of internal buffer.
|
* @return The length of internal buffer.
|
||||||
*/
|
*/
|
||||||
size_t GetDataSize() const;
|
size_t get_data_size() const;
|
||||||
/**
|
/**
|
||||||
* @brief Resize internal buffer to given size.
|
* @brief Resize internal buffer to given size.
|
||||||
* @remarks This is usually used when writing data.
|
* @remarks This is usually used when writing data.
|
||||||
* @param[in] new_size The new size of internal buffer.
|
* @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.
|
* @brief Get data pointer to internal buffer for reading.
|
||||||
* @remarks This is usually used when reading data.
|
* @remarks This is usually used when reading data.
|
||||||
* @param[in] offset The offset in byte added to underlying pointer.
|
* @param[in] offset The offset in byte added to underlying pointer.
|
||||||
* @return The data pointer to internal buffer.
|
* @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.
|
* @brief Get data pointer to internal buffer for writing.
|
||||||
* @remarks This is usually used when writing data.
|
* @remarks This is usually used when writing data.
|
||||||
* @param[in] offset The offset in byte added to underlying pointer.
|
* @param[in] offset The offset in byte added to underlying pointer.
|
||||||
* @return The data pointer to internal buffer.
|
* @return The data pointer to internal buffer.
|
||||||
*/
|
*/
|
||||||
void* GetDataPtr(size_t offset = 0);
|
void* get_data_ptr(size_t offset = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<uint8_t> datas; ///< The internal buffer.
|
std::vector<uint8_t> datas; ///< The internal buffer.
|
||||||
|
|||||||
Reference in New Issue
Block a user