feat: finish binstore setting get/set/reset
This commit is contained in:
@ -41,7 +41,7 @@ PRIVATE
|
|||||||
yycc/carton/binstore/types.cpp
|
yycc/carton/binstore/types.cpp
|
||||||
yycc/carton/binstore/setting.cpp
|
yycc/carton/binstore/setting.cpp
|
||||||
yycc/carton/binstore/configuration.cpp
|
yycc/carton/binstore/configuration.cpp
|
||||||
#yycc/carton/binstore/storage.cpp
|
yycc/carton/binstore/storage.cpp
|
||||||
)
|
)
|
||||||
target_sources(YYCCommonplace
|
target_sources(YYCCommonplace
|
||||||
PUBLIC
|
PUBLIC
|
||||||
@ -110,7 +110,7 @@ FILES
|
|||||||
yycc/carton/binstore/serializer.hpp
|
yycc/carton/binstore/serializer.hpp
|
||||||
yycc/carton/binstore/setting.hpp
|
yycc/carton/binstore/setting.hpp
|
||||||
yycc/carton/binstore/configuration.hpp
|
yycc/carton/binstore/configuration.hpp
|
||||||
#yycc/carton/binstore/storage.hpp
|
yycc/carton/binstore/storage.hpp
|
||||||
yycc/carton/fft.hpp
|
yycc/carton/fft.hpp
|
||||||
)
|
)
|
||||||
# Setup header infomations
|
# Setup header infomations
|
||||||
|
|||||||
@ -48,6 +48,7 @@ namespace yycc::carton::binstore::serializer {
|
|||||||
auto TMax = std::numeric_limits<T>::max(),
|
auto TMax = std::numeric_limits<T>::max(),
|
||||||
auto TDefault = static_cast<T>(0)>
|
auto TDefault = static_cast<T>(0)>
|
||||||
struct IntegralSerDes {
|
struct IntegralSerDes {
|
||||||
|
IntegralSerDes() = default;
|
||||||
YYCC_DEFAULT_COPY_MOVE(IntegralSerDes)
|
YYCC_DEFAULT_COPY_MOVE(IntegralSerDes)
|
||||||
|
|
||||||
static_assert(TMin <= TMax);
|
static_assert(TMin <= TMax);
|
||||||
@ -82,6 +83,11 @@ namespace yycc::carton::binstore::serializer {
|
|||||||
auto TMax = std::numeric_limits<T>::max(),
|
auto TMax = std::numeric_limits<T>::max(),
|
||||||
auto TDefault = static_cast<T>(0)>
|
auto TDefault = static_cast<T>(0)>
|
||||||
struct FloatingPointSerDes {
|
struct FloatingPointSerDes {
|
||||||
|
FloatingPointSerDes() {
|
||||||
|
// TODO: Remove this and make it "= default" when 3 common STL make std::isfinite become constexpr.
|
||||||
|
if (!std::isfinite(TMin)) throw std::logic_error("invalid float minimum value.");
|
||||||
|
if (!std::isfinite(TMax)) throw std::logic_error("invalid float maximum value.");
|
||||||
|
}
|
||||||
YYCC_DEFAULT_COPY_MOVE(FloatingPointSerDes)
|
YYCC_DEFAULT_COPY_MOVE(FloatingPointSerDes)
|
||||||
|
|
||||||
// TODO: Use static_assert once 3 common STL make this become constexpr.
|
// TODO: Use static_assert once 3 common STL make this become constexpr.
|
||||||
@ -116,6 +122,7 @@ namespace yycc::carton::binstore::serializer {
|
|||||||
|
|
||||||
template<bool TDefault = false>
|
template<bool TDefault = false>
|
||||||
struct BoolSerDes {
|
struct BoolSerDes {
|
||||||
|
BoolSerDes() = default;
|
||||||
YYCC_DEFAULT_COPY_MOVE(BoolSerDes)
|
YYCC_DEFAULT_COPY_MOVE(BoolSerDes)
|
||||||
|
|
||||||
using ValueType = bool;
|
using ValueType = bool;
|
||||||
@ -140,6 +147,7 @@ namespace yycc::carton::binstore::serializer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct StringSerDes {
|
struct StringSerDes {
|
||||||
|
StringSerDes() = default;
|
||||||
YYCC_DEFAULT_COPY_MOVE(StringSerDes)
|
YYCC_DEFAULT_COPY_MOVE(StringSerDes)
|
||||||
|
|
||||||
using ValueType = std::u8string;
|
using ValueType = std::u8string;
|
||||||
|
|||||||
@ -1,13 +1,72 @@
|
|||||||
#include "storage.hpp"
|
#include "storage.hpp"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#define TYPES ::yycc::carton::binstore::types
|
||||||
|
#define CFG ::yycc::carton::binstore::configuration
|
||||||
|
#define SERDES ::yycc::carton::binstore::serializer
|
||||||
|
|
||||||
namespace yycc::carton::binstore::storage {
|
namespace yycc::carton::binstore::storage {
|
||||||
|
|
||||||
#pragma region Storage Class
|
#pragma region Storage Class
|
||||||
|
|
||||||
Storage::Storage() {}
|
Storage::Storage(CFG::Configuration&& cfg) : cfg(std::move(cfg)), raws() {}
|
||||||
|
|
||||||
Storage::~Storage() {}
|
Storage::~Storage() {}
|
||||||
|
|
||||||
|
TYPES::BinstoreResult<void> Storage::load_from_file(const std::filesystem::path& fpath, LoadStrategy strategy) {
|
||||||
|
std::ifstream fs(fpath, std::ios::binary);
|
||||||
|
if (fs.is_open()) {
|
||||||
|
auto rv = this->load(fs, strategy);
|
||||||
|
fs.close();
|
||||||
|
return rv;
|
||||||
|
} else {
|
||||||
|
return std::unexpected(TYPES::BinstoreError::Io);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPES::BinstoreResult<void> Storage::load(std::istream& s, LoadStrategy strategy) {
|
||||||
|
return TYPES::BinstoreResult<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPES::BinstoreResult<void> Storage::save_into_file(const std::filesystem::path& fpath) {
|
||||||
|
std::ofstream fs(fpath, std::ios::binary);
|
||||||
|
if (fs.is_open()) {
|
||||||
|
auto rv = this->save(fs);
|
||||||
|
fs.close();
|
||||||
|
return rv;
|
||||||
|
} else {
|
||||||
|
return std::unexpected(TYPES::BinstoreError::Io);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TYPES::BinstoreResult<void> Storage::save(std::ostream& s) {
|
||||||
|
return TYPES::BinstoreResult<void>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::has_setting(TYPES::Token token) const {
|
||||||
|
return this->cfg.get_settings().has_setting(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Storage::is_setting_stored(TYPES::Token token) const {
|
||||||
|
if (!this->has_setting(token)) throw std::logic_error("given setting token is invalid");
|
||||||
|
return this->raws.contains(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
const TYPES::ByteArray& Storage::get_raw_value(TYPES::Token token) const {
|
||||||
|
if (!this->has_setting(token)) throw std::logic_error("given setting token is invalid");
|
||||||
|
auto finder = this->raws.find(token);
|
||||||
|
if (finder != this->raws.end()) {
|
||||||
|
return finder->second;
|
||||||
|
} else {
|
||||||
|
throw std::logic_error("given setting has not been stored yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Storage::set_raw_value(TYPES::Token token, TYPES::ByteArray&& ba) {
|
||||||
|
if (!this->has_setting(token)) throw std::logic_error("given setting token is invalid");
|
||||||
|
this->raws.insert_or_assign(token, std::move(ba));
|
||||||
|
}
|
||||||
|
|
||||||
#pragma endregion
|
#pragma endregion
|
||||||
|
|
||||||
} // namespace yycc::carton::binstore::storage
|
} // namespace yycc::carton::binstore::storage
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#define NS_YYCC_BINSTORE_TYPES ::yycc::carton::binstore::types
|
#define NS_YYCC_BINSTORE_TYPES ::yycc::carton::binstore::types
|
||||||
#define NS_YYCC_BINSTORE_CFG ::yycc::carton::binstore::configuration
|
#define NS_YYCC_BINSTORE_CFG ::yycc::carton::binstore::configuration
|
||||||
@ -44,19 +45,6 @@ namespace yycc::carton::binstore::storage {
|
|||||||
AcceptAll,
|
AcceptAll,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief The operation result state when getting setting's value.
|
|
||||||
enum class GetValueState {
|
|
||||||
Ok, ///< Successfully load value from raw part. We return it.
|
|
||||||
Default, ///< Given setting is not presented. We create it from its default value and return.
|
|
||||||
Reset, ///< Can not read from raw part. We reset it in its default value and return.
|
|
||||||
};
|
|
||||||
|
|
||||||
/// @brief The operation result state when setting setting's value.
|
|
||||||
enum class SetValueState {
|
|
||||||
Ok, ///< Successfully set value.
|
|
||||||
Reset, ///< Given value is not meet the requirement of this setting and its value was reset into default value.
|
|
||||||
};
|
|
||||||
|
|
||||||
class Storage {
|
class Storage {
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
@ -65,81 +53,129 @@ namespace yycc::carton::binstore::storage {
|
|||||||
* Valus is its stored value in raw data format.
|
* Valus is its stored value in raw data format.
|
||||||
*/
|
*/
|
||||||
std::map<NS_YYCC_BINSTORE_TYPES::Token, NS_YYCC_BINSTORE_TYPES::ByteArray> raws;
|
std::map<NS_YYCC_BINSTORE_TYPES::Token, NS_YYCC_BINSTORE_TYPES::ByteArray> raws;
|
||||||
NS_YYCC_BINSTORE_CFG::Configuration configuration; ///< The configuration associated with this storage.
|
NS_YYCC_BINSTORE_CFG::Configuration cfg; ///< The configuration associated with this storage.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Storage();
|
Storage(NS_YYCC_BINSTORE_CFG::Configuration&& cfg);
|
||||||
~Storage();
|
~Storage();
|
||||||
|
YYCC_DEFAULT_COPY_MOVE(Storage)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_YYCC_BINSTORE_TYPES::BinstoreResult<void> load_from_file(const std::filesystem::path& fpath, LoadStrategy strategy);
|
NS_YYCC_BINSTORE_TYPES::BinstoreResult<void> load_from_file(const std::filesystem::path& fpath, LoadStrategy strategy);
|
||||||
NS_YYCC_BINSTORE_TYPES::BinstoreResult<void> load_from_io(std::istream& s, LoadStrategy strategy);
|
NS_YYCC_BINSTORE_TYPES::BinstoreResult<void> load(std::istream& s, LoadStrategy strategy);
|
||||||
NS_YYCC_BINSTORE_TYPES::BinstoreResult<void> save_into_file(const std::filesystem::path& fpath);
|
NS_YYCC_BINSTORE_TYPES::BinstoreResult<void> save_into_file(const std::filesystem::path& fpath);
|
||||||
NS_YYCC_BINSTORE_TYPES::BinstoreResult<void> save_into_io(std::ostream& s);
|
NS_YYCC_BINSTORE_TYPES::BinstoreResult<void> save(std::ostream& s);
|
||||||
/**
|
|
||||||
* @brief Reset all values of setting to their default value.
|
|
||||||
* @details Please note that all stored value will be wiped before assign them with default value.65
|
|
||||||
*/
|
|
||||||
void reset();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool has_value(NS_YYCC_BINSTORE_TYPES::Token token) const;
|
/**
|
||||||
|
* @brief Check whether given token is a valid token to registered settings.
|
||||||
|
* @param[in] token Token for checking.
|
||||||
|
* @return True if it is a registered setting, otherwise false.
|
||||||
|
*/
|
||||||
|
bool has_setting(NS_YYCC_BINSTORE_TYPES::Token token) const;
|
||||||
|
/**
|
||||||
|
* @brief Check whether given token is stored in raw value dictionary.
|
||||||
|
* @param[in] token Token for checking.
|
||||||
|
* @return True if it is stored, otherwise false.
|
||||||
|
* @exception std::logic_error Given token is not point to a registered setting.
|
||||||
|
*/
|
||||||
|
bool is_setting_stored(NS_YYCC_BINSTORE_TYPES::Token token) const;
|
||||||
|
/**
|
||||||
|
* @brief Get raw value of given setting.
|
||||||
|
* @param[in] token Token for fetching.
|
||||||
|
* @return The const reference to given setting's raw data.
|
||||||
|
* @exception std::logic_error Given token is not point to a registered setting.
|
||||||
|
* @exception std::logic_error Given token pointed to setting is not stored yet.
|
||||||
|
*/
|
||||||
const NS_YYCC_BINSTORE_TYPES::ByteArray& get_raw_value(NS_YYCC_BINSTORE_TYPES::Token token) const;
|
const NS_YYCC_BINSTORE_TYPES::ByteArray& get_raw_value(NS_YYCC_BINSTORE_TYPES::Token token) const;
|
||||||
|
/**
|
||||||
|
* @brief Set raw value for given setting.
|
||||||
|
* @param[in] token Token for setting.
|
||||||
|
* @param[in] ba The right-value raw value for setting.
|
||||||
|
* @exception std::logic_error Given token is not point to a registered setting.
|
||||||
|
*/
|
||||||
void set_raw_value(NS_YYCC_BINSTORE_TYPES::Token token, NS_YYCC_BINSTORE_TYPES::ByteArray&& ba);
|
void set_raw_value(NS_YYCC_BINSTORE_TYPES::Token token, NS_YYCC_BINSTORE_TYPES::ByteArray&& ba);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/**
|
||||||
|
* @brief Reset given setting into default value.
|
||||||
|
* @tparam T The SerDes applied to this setting.
|
||||||
|
* @param[in] token Token to setting for resetting.
|
||||||
|
* @param[in] serdes Optional SerDes passed if it can not be constructed from default ctor.
|
||||||
|
*/
|
||||||
template<NS_YYCC_BINSTORE_SERDES::SerDes T>
|
template<NS_YYCC_BINSTORE_SERDES::SerDes T>
|
||||||
NS_YYCC_BINSTORE_TYPES::BinstoreResult<std::pair<GetValueState, NS_YYCC_BINSTORE_SERDES::SerDesValueType<T>>> get_value(
|
void reset_value(NS_YYCC_BINSTORE_TYPES::Token token, const T& serdes = T{}) {
|
||||||
NS_YYCC_BINSTORE_TYPES::Token token, const T& serdes = T{}) {
|
// Check whether has this setting.
|
||||||
// If we have value, we fetch it first
|
if (!has_setting(token)) throw std::logic_error("given setting token is invalid");
|
||||||
if (this->has_value(token)) {
|
// Reset it.
|
||||||
|
auto ba = serdes.reset();
|
||||||
|
this->set_raw_value(token, std::move(ba));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief Get given setting's value.
|
||||||
|
* @tparam T The SerDes applied to this setting.
|
||||||
|
* @param[in] token Token to setting for fetching value.
|
||||||
|
* @param[in] serdes Optional SerDes passed if it can not be constructed from default ctor.
|
||||||
|
* @return Fetched value. If there is no such setting before or fail to deserialize underlying data,
|
||||||
|
* Default value will be forcely set before the return of this function.
|
||||||
|
*/
|
||||||
|
template<NS_YYCC_BINSTORE_SERDES::SerDes T>
|
||||||
|
NS_YYCC_BINSTORE_SERDES::SerDesValueType<T> get_value(NS_YYCC_BINSTORE_TYPES::Token token, const T& serdes = T{}) {
|
||||||
|
// Check whether has this setting.
|
||||||
|
if (!has_setting(token)) throw std::logic_error("given setting token is invalid");
|
||||||
|
|
||||||
|
// If we have stored raw value, we fetch it first.
|
||||||
|
if (this->is_setting_stored(token)) {
|
||||||
// Get raw value.
|
// Get raw value.
|
||||||
const auto& ba = this->get_raw_value(token);
|
const auto& ba = this->get_raw_value(token);
|
||||||
// Try to deserialize it.
|
// Try to deserialize it.
|
||||||
auto value = serdes.deserialize(raw_value);
|
auto value = serdes.deserialize(raw_value);
|
||||||
// If the result is okey, return it.
|
// If the result is okey, return it.
|
||||||
if (value.has_value()) {
|
if (value.has_value()) {
|
||||||
return std::make_pair(GetValueState::Ok, std::move(value.value()));
|
return value.value();
|
||||||
}
|
}
|
||||||
// Otherwise we need reset it into default value.
|
// Otherwise we need reset it into default value.
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we do not have this setting,
|
// If we do not have this setting, or we need reset it into default value
|
||||||
// or we need reset it into default value,
|
// due to failed deserialization, we need execute following code.
|
||||||
// we need execute following code.
|
// Reset its value first
|
||||||
// First decide the return state.
|
this->reset_value(token, serdes);
|
||||||
GetValueState state = this->has_value(token) ? GetValueState::Reset : GetValueState::Default;
|
// The re-fetch its raw value and deserialize it.
|
||||||
{
|
|
||||||
// Fetch the default raw data.
|
|
||||||
auto ba = serdes.reset();
|
|
||||||
// Set it for this setting.
|
|
||||||
this->set_raw_value(token, std::move(ba));
|
|
||||||
}
|
|
||||||
// The get it and deserialize it.
|
|
||||||
const auto& ba = this->get_raw_value(token);
|
const auto& ba = this->get_raw_value(token);
|
||||||
auto value = serdes.deserialize(ba);
|
auto value = serdes.deserialize(ba);
|
||||||
// Default must can be deserialized.
|
// Default value must can be deserialized.
|
||||||
// If not, throw exception.
|
// If not, throw exception.
|
||||||
if (value.has_value()) {
|
if (value.has_value()) {
|
||||||
return std::make_pair(state, std::move(value));
|
return value.value();
|
||||||
} else {
|
} else {
|
||||||
throw std::logic_error("default value can not be deserialized");
|
throw std::logic_error("default value must can be deserialized");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @brief Set given setting's value.
|
||||||
|
* @tparam T The SerDes applied to this setting.
|
||||||
|
* @param[in] token Token to setting for setting value.
|
||||||
|
* @param[in] value The value to set.
|
||||||
|
* @param[in] serdes Optional SerDes passed if it can not be constructed from default ctor.
|
||||||
|
* @return True if the setting was set to your given value,
|
||||||
|
* otherwise false, the value was set as default value because given value can not be serialized.
|
||||||
|
*/
|
||||||
template<NS_YYCC_BINSTORE_SERDES::SerDes T>
|
template<NS_YYCC_BINSTORE_SERDES::SerDes T>
|
||||||
NS_YYCC_BINSTORE_TYPES::BinstoreResult<SetValueState> set_value(NS_YYCC_BINSTORE_TYPES::Token token,
|
bool set_value(NS_YYCC_BINSTORE_TYPES::Token token,
|
||||||
const NS_YYCC_BINSTORE_SERDES::SerDesValueType<T>& value,
|
const NS_YYCC_BINSTORE_SERDES::SerDesValueType<T>& value,
|
||||||
const T& serdes = T{}) {
|
const T& serdes = T{}) {
|
||||||
// First we try assign it.
|
// Check whether has this setting.
|
||||||
{
|
if (!has_setting(token)) throw std::logic_error("given setting token is invalid");
|
||||||
// Convert it into raw format.
|
|
||||||
auto ba = serdes.serialize(value);
|
// We try to serialize given value first.
|
||||||
// If we can not serialize it, we need reset it into default value.
|
auto rv_ser = serdes.serialize(value);
|
||||||
// Otherwise assign it and return.
|
// If we can serialize it, we directly use it,'
|
||||||
if (ba.has_value()) {
|
// otherwise we need fetch it from default value.
|
||||||
this->set_raw_value(token, )
|
auto success_ser = rv_ser.has_value();
|
||||||
}
|
auto ba = success_ser ? std::move(rv_ser.value()) : serdes.reset();
|
||||||
}
|
// Assign it to setting's raw value.
|
||||||
|
this->set_raw_value(token, std::move(ba));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user