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/setting.cpp
|
||||
yycc/carton/binstore/configuration.cpp
|
||||
#yycc/carton/binstore/storage.cpp
|
||||
yycc/carton/binstore/storage.cpp
|
||||
)
|
||||
target_sources(YYCCommonplace
|
||||
PUBLIC
|
||||
@ -110,7 +110,7 @@ FILES
|
||||
yycc/carton/binstore/serializer.hpp
|
||||
yycc/carton/binstore/setting.hpp
|
||||
yycc/carton/binstore/configuration.hpp
|
||||
#yycc/carton/binstore/storage.hpp
|
||||
yycc/carton/binstore/storage.hpp
|
||||
yycc/carton/fft.hpp
|
||||
)
|
||||
# Setup header infomations
|
||||
|
||||
@ -48,6 +48,7 @@ namespace yycc::carton::binstore::serializer {
|
||||
auto TMax = std::numeric_limits<T>::max(),
|
||||
auto TDefault = static_cast<T>(0)>
|
||||
struct IntegralSerDes {
|
||||
IntegralSerDes() = default;
|
||||
YYCC_DEFAULT_COPY_MOVE(IntegralSerDes)
|
||||
|
||||
static_assert(TMin <= TMax);
|
||||
@ -82,6 +83,11 @@ namespace yycc::carton::binstore::serializer {
|
||||
auto TMax = std::numeric_limits<T>::max(),
|
||||
auto TDefault = static_cast<T>(0)>
|
||||
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)
|
||||
|
||||
// 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>
|
||||
struct BoolSerDes {
|
||||
BoolSerDes() = default;
|
||||
YYCC_DEFAULT_COPY_MOVE(BoolSerDes)
|
||||
|
||||
using ValueType = bool;
|
||||
@ -140,6 +147,7 @@ namespace yycc::carton::binstore::serializer {
|
||||
};
|
||||
|
||||
struct StringSerDes {
|
||||
StringSerDes() = default;
|
||||
YYCC_DEFAULT_COPY_MOVE(StringSerDes)
|
||||
|
||||
using ValueType = std::u8string;
|
||||
|
||||
@ -1,13 +1,72 @@
|
||||
#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 {
|
||||
|
||||
#pragma region Storage Class
|
||||
|
||||
Storage::Storage() {}
|
||||
Storage::Storage(CFG::Configuration&& cfg) : cfg(std::move(cfg)), raws() {}
|
||||
|
||||
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
|
||||
|
||||
} // namespace yycc::carton::binstore::storage
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include <filesystem>
|
||||
#include <istream>
|
||||
#include <ostream>
|
||||
#include <stdexcept>
|
||||
|
||||
#define NS_YYCC_BINSTORE_TYPES ::yycc::carton::binstore::types
|
||||
#define NS_YYCC_BINSTORE_CFG ::yycc::carton::binstore::configuration
|
||||
@ -44,19 +45,6 @@ namespace yycc::carton::binstore::storage {
|
||||
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 {
|
||||
private:
|
||||
/**
|
||||
@ -65,81 +53,129 @@ namespace yycc::carton::binstore::storage {
|
||||
* Valus is its stored value in raw data format.
|
||||
*/
|
||||
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:
|
||||
Storage();
|
||||
Storage(NS_YYCC_BINSTORE_CFG::Configuration&& cfg);
|
||||
~Storage();
|
||||
YYCC_DEFAULT_COPY_MOVE(Storage)
|
||||
|
||||
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_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_io(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();
|
||||
NS_YYCC_BINSTORE_TYPES::BinstoreResult<void> save(std::ostream& s);
|
||||
|
||||
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;
|
||||
/**
|
||||
* @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);
|
||||
|
||||
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>
|
||||
NS_YYCC_BINSTORE_TYPES::BinstoreResult<std::pair<GetValueState, NS_YYCC_BINSTORE_SERDES::SerDesValueType<T>>> get_value(
|
||||
NS_YYCC_BINSTORE_TYPES::Token token, const T& serdes = T{}) {
|
||||
// If we have value, we fetch it first
|
||||
if (this->has_value(token)) {
|
||||
void reset_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");
|
||||
// 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.
|
||||
const auto& ba = this->get_raw_value(token);
|
||||
// Try to deserialize it.
|
||||
auto value = serdes.deserialize(raw_value);
|
||||
// If the result is okey, return it.
|
||||
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.
|
||||
}
|
||||
|
||||
// If we do not have this setting,
|
||||
// or we need reset it into default value,
|
||||
// we need execute following code.
|
||||
// First decide the return state.
|
||||
GetValueState state = this->has_value(token) ? GetValueState::Reset : GetValueState::Default;
|
||||
{
|
||||
// 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.
|
||||
// If we do not have this setting, or we need reset it into default value
|
||||
// due to failed deserialization, we need execute following code.
|
||||
// Reset its value first
|
||||
this->reset_value(token, serdes);
|
||||
// The re-fetch its raw value and deserialize it.
|
||||
const auto& ba = this->get_raw_value(token);
|
||||
auto value = serdes.deserialize(ba);
|
||||
// Default must can be deserialized.
|
||||
// Default value must can be deserialized.
|
||||
// If not, throw exception.
|
||||
if (value.has_value()) {
|
||||
return std::make_pair(state, std::move(value));
|
||||
return value.value();
|
||||
} 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>
|
||||
NS_YYCC_BINSTORE_TYPES::BinstoreResult<SetValueState> set_value(NS_YYCC_BINSTORE_TYPES::Token token,
|
||||
const NS_YYCC_BINSTORE_SERDES::SerDesValueType<T>& value,
|
||||
const T& serdes = T{}) {
|
||||
// First we try assign it.
|
||||
{
|
||||
// Convert it into raw format.
|
||||
auto ba = serdes.serialize(value);
|
||||
// If we can not serialize it, we need reset it into default value.
|
||||
// Otherwise assign it and return.
|
||||
if (ba.has_value()) {
|
||||
this->set_raw_value(token, )
|
||||
}
|
||||
}
|
||||
bool set_value(NS_YYCC_BINSTORE_TYPES::Token token,
|
||||
const NS_YYCC_BINSTORE_SERDES::SerDesValueType<T>& value,
|
||||
const T& serdes = T{}) {
|
||||
// Check whether has this setting.
|
||||
if (!has_setting(token)) throw std::logic_error("given setting token is invalid");
|
||||
|
||||
// We try to serialize given value first.
|
||||
auto rv_ser = serdes.serialize(value);
|
||||
// If we can serialize it, we directly use it,'
|
||||
// otherwise we need fetch it from default value.
|
||||
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