1
0

feat: finish binstore setting get/set/reset

This commit is contained in:
2025-12-12 20:25:06 +08:00
parent 6c2dba74d1
commit f49d974a46
4 changed files with 162 additions and 59 deletions

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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,
bool 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, )
}
}
// 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));
}
};