From 0130f3c97163a4a2ed01ae24dbf3be69c959c8fa Mon Sep 17 00:00:00 2001 From: EntireTwix Date: Wed, 14 Jul 2021 22:56:10 -0700 Subject: [PATCH] :tada::sparkles: FBE --- fbe/user_model.fbe | 27 + fbe/user_model/bank_dom.cpp | 197 +++++ fbe/user_model/bank_dom.h | 238 ++++++ fbe/user_model/bank_dom_final_models.cpp | 638 ++++++++++++++++ fbe/user_model/bank_dom_final_models.h | 320 ++++++++ fbe/user_model/bank_dom_models.cpp | 930 +++++++++++++++++++++++ fbe/user_model/bank_dom_models.h | 396 ++++++++++ fbe/user_model/fbe.cpp | 401 ++++++++++ fbe/user_model/fbe.h | 650 ++++++++++++++++ fbe/user_model/fbe_final_models.cpp | 436 +++++++++++ fbe/user_model/fbe_final_models.h | 457 +++++++++++ fbe/user_model/fbe_final_models.inl | 635 ++++++++++++++++ fbe/user_model/fbe_models.cpp | 514 +++++++++++++ fbe/user_model/fbe_models.h | 469 ++++++++++++ fbe/user_model/fbe_models.inl | 687 +++++++++++++++++ 15 files changed, 6995 insertions(+) create mode 100644 fbe/user_model.fbe create mode 100644 fbe/user_model/bank_dom.cpp create mode 100644 fbe/user_model/bank_dom.h create mode 100644 fbe/user_model/bank_dom_final_models.cpp create mode 100644 fbe/user_model/bank_dom_final_models.h create mode 100644 fbe/user_model/bank_dom_models.cpp create mode 100644 fbe/user_model/bank_dom_models.h create mode 100644 fbe/user_model/fbe.cpp create mode 100644 fbe/user_model/fbe.h create mode 100644 fbe/user_model/fbe_final_models.cpp create mode 100644 fbe/user_model/fbe_final_models.h create mode 100644 fbe/user_model/fbe_final_models.inl create mode 100644 fbe/user_model/fbe_models.cpp create mode 100644 fbe/user_model/fbe_models.h create mode 100644 fbe/user_model/fbe_models.inl diff --git a/fbe/user_model.fbe b/fbe/user_model.fbe new file mode 100644 index 0000000..59a5c00 --- /dev/null +++ b/fbe/user_model.fbe @@ -0,0 +1,27 @@ +package bank_dom + +struct Transaction +{ + string from = ""; + string to = ""; + uint32 amount = 0; + timestamp time; +} + +struct Logs +{ + Transaction[] data; +} + +struct User +{ + uint32 balance = 0; + uint64 password = 0; + Logs? logs = null; +} + +struct Global +{ + string[] keys; + User[] users; +} \ No newline at end of file diff --git a/fbe/user_model/bank_dom.cpp b/fbe/user_model/bank_dom.cpp new file mode 100644 index 0000000..d4e60c0 --- /dev/null +++ b/fbe/user_model/bank_dom.cpp @@ -0,0 +1,197 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: user_model.fbe +// Version: 1.7.0.0 + +#include "bank_dom.h" + +namespace bank_dom { + +Transaction::Transaction() + : from("") + , to("") + , amount((uint32_t)0ull) + , time((uint64_t)0ull) +{} + +Transaction::Transaction(const std::string& arg_from, const std::string& arg_to, uint32_t arg_amount, uint64_t arg_time) + : from(arg_from) + , to(arg_to) + , amount(arg_amount) + , time(arg_time) +{} + +bool Transaction::operator==(const Transaction& other) const noexcept +{ + return ( + true + ); +} + +bool Transaction::operator<(const Transaction& other) const noexcept +{ + return false; +} + +void Transaction::swap(Transaction& other) noexcept +{ + using std::swap; + swap(from, other.from); + swap(to, other.to); + swap(amount, other.amount); + swap(time, other.time); +} + +std::ostream& operator<<(std::ostream& stream, const Transaction& value) +{ + stream << "Transaction("; + stream << "from="; stream << "\"" << value.from << "\""; + stream << ",to="; stream << "\"" << value.to << "\""; + stream << ",amount="; stream << value.amount; + stream << ",time="; stream << value.time; + stream << ")"; + return stream; +} + +Logs::Logs() + : data() +{} + +Logs::Logs(const std::vector<::bank_dom::Transaction>& arg_data) + : data(arg_data) +{} + +bool Logs::operator==(const Logs& other) const noexcept +{ + return ( + true + ); +} + +bool Logs::operator<(const Logs& other) const noexcept +{ + return false; +} + +void Logs::swap(Logs& other) noexcept +{ + using std::swap; + swap(data, other.data); +} + +std::ostream& operator<<(std::ostream& stream, const Logs& value) +{ + stream << "Logs("; + { + bool first = true; + stream << "data=[" << value.data.size() << "]["; + for (const auto& it : value.data) + { + stream << std::string(first ? "" : ",") << it; + first = false; + } + stream << "]"; + } + stream << ")"; + return stream; +} + +User::User() + : balance((uint32_t)0ull) + , password((uint64_t)0ull) + , logs(std::nullopt) +{} + +User::User(uint32_t arg_balance, uint64_t arg_password, const std::optional<::bank_dom::Logs>& arg_logs) + : balance(arg_balance) + , password(arg_password) + , logs(arg_logs) +{} + +bool User::operator==(const User& other) const noexcept +{ + return ( + true + ); +} + +bool User::operator<(const User& other) const noexcept +{ + return false; +} + +void User::swap(User& other) noexcept +{ + using std::swap; + swap(balance, other.balance); + swap(password, other.password); + swap(logs, other.logs); +} + +std::ostream& operator<<(std::ostream& stream, const User& value) +{ + stream << "User("; + stream << "balance="; stream << value.balance; + stream << ",password="; stream << value.password; + stream << ",logs="; if (value.logs) stream << *value.logs; else stream << "null"; + stream << ")"; + return stream; +} + +Global::Global() + : keys() + , users() +{} + +Global::Global(const std::vector& arg_keys, const std::vector<::bank_dom::User>& arg_users) + : keys(arg_keys) + , users(arg_users) +{} + +bool Global::operator==(const Global& other) const noexcept +{ + return ( + true + ); +} + +bool Global::operator<(const Global& other) const noexcept +{ + return false; +} + +void Global::swap(Global& other) noexcept +{ + using std::swap; + swap(keys, other.keys); + swap(users, other.users); +} + +std::ostream& operator<<(std::ostream& stream, const Global& value) +{ + stream << "Global("; + { + bool first = true; + stream << "keys=[" << value.keys.size() << "]["; + for (const auto& it : value.keys) + { + stream << std::string(first ? "" : ",") << "\"" << it << "\""; + first = false; + } + stream << "]"; + } + { + bool first = true; + stream << ",users=[" << value.users.size() << "]["; + for (const auto& it : value.users) + { + stream << std::string(first ? "" : ",") << it; + first = false; + } + stream << "]"; + } + stream << ")"; + return stream; +} + +} // namespace bank_dom diff --git a/fbe/user_model/bank_dom.h b/fbe/user_model/bank_dom.h new file mode 100644 index 0000000..04f8375 --- /dev/null +++ b/fbe/user_model/bank_dom.h @@ -0,0 +1,238 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: user_model.fbe +// Version: 1.7.0.0 + +#pragma once + +#if defined(__clang__) +#pragma clang system_header +#elif defined(__GNUC__) +#pragma GCC system_header +#elif defined(_MSC_VER) +#pragma system_header +#endif + +#include "fbe.h" + +namespace bank_dom { +using namespace FBE; +} // namespace bank_dom + +namespace FBE { +using namespace ::bank_dom; +} // namespace FBE + +namespace bank_dom { + +struct Transaction +{ + std::string from; + std::string to; + uint32_t amount; + uint64_t time; + + size_t fbe_type() const noexcept { return 1; } + + Transaction(); + Transaction(const std::string& arg_from, const std::string& arg_to, uint32_t arg_amount, uint64_t arg_time); + Transaction(const Transaction& other) = default; + Transaction(Transaction&& other) = default; + ~Transaction() = default; + + Transaction& operator=(const Transaction& other) = default; + Transaction& operator=(Transaction&& other) = default; + + bool operator==(const Transaction& other) const noexcept; + bool operator!=(const Transaction& other) const noexcept { return !operator==(other); } + bool operator<(const Transaction& other) const noexcept; + bool operator<=(const Transaction& other) const noexcept { return operator<(other) || operator==(other); } + bool operator>(const Transaction& other) const noexcept { return !operator<=(other); } + bool operator>=(const Transaction& other) const noexcept { return !operator<(other); } + + std::string string() const { std::stringstream ss; ss << *this; return ss.str(); } + + friend std::ostream& operator<<(std::ostream& stream, const Transaction& value); + + void swap(Transaction& other) noexcept; + friend void swap(Transaction& value1, Transaction& value2) noexcept { value1.swap(value2); } +}; + +} // namespace bank_dom + +namespace std { + +template<> +struct hash +{ + typedef bank_dom::Transaction argument_type; + typedef size_t result_type; + + result_type operator() (const argument_type& value) const + { + result_type result = 17; + return result; + } +}; + +} // namespace std + +namespace bank_dom { + +struct Logs +{ + std::vector<::bank_dom::Transaction> data; + + size_t fbe_type() const noexcept { return 2; } + + Logs(); + explicit Logs(const std::vector<::bank_dom::Transaction>& arg_data); + Logs(const Logs& other) = default; + Logs(Logs&& other) = default; + ~Logs() = default; + + Logs& operator=(const Logs& other) = default; + Logs& operator=(Logs&& other) = default; + + bool operator==(const Logs& other) const noexcept; + bool operator!=(const Logs& other) const noexcept { return !operator==(other); } + bool operator<(const Logs& other) const noexcept; + bool operator<=(const Logs& other) const noexcept { return operator<(other) || operator==(other); } + bool operator>(const Logs& other) const noexcept { return !operator<=(other); } + bool operator>=(const Logs& other) const noexcept { return !operator<(other); } + + std::string string() const { std::stringstream ss; ss << *this; return ss.str(); } + + friend std::ostream& operator<<(std::ostream& stream, const Logs& value); + + void swap(Logs& other) noexcept; + friend void swap(Logs& value1, Logs& value2) noexcept { value1.swap(value2); } +}; + +} // namespace bank_dom + +namespace std { + +template<> +struct hash +{ + typedef bank_dom::Logs argument_type; + typedef size_t result_type; + + result_type operator() (const argument_type& value) const + { + result_type result = 17; + return result; + } +}; + +} // namespace std + +namespace bank_dom { + +struct User +{ + uint32_t balance; + uint64_t password; + std::optional<::bank_dom::Logs> logs; + + size_t fbe_type() const noexcept { return 3; } + + User(); + User(uint32_t arg_balance, uint64_t arg_password, const std::optional<::bank_dom::Logs>& arg_logs); + User(const User& other) = default; + User(User&& other) = default; + ~User() = default; + + User& operator=(const User& other) = default; + User& operator=(User&& other) = default; + + bool operator==(const User& other) const noexcept; + bool operator!=(const User& other) const noexcept { return !operator==(other); } + bool operator<(const User& other) const noexcept; + bool operator<=(const User& other) const noexcept { return operator<(other) || operator==(other); } + bool operator>(const User& other) const noexcept { return !operator<=(other); } + bool operator>=(const User& other) const noexcept { return !operator<(other); } + + std::string string() const { std::stringstream ss; ss << *this; return ss.str(); } + + friend std::ostream& operator<<(std::ostream& stream, const User& value); + + void swap(User& other) noexcept; + friend void swap(User& value1, User& value2) noexcept { value1.swap(value2); } +}; + +} // namespace bank_dom + +namespace std { + +template<> +struct hash +{ + typedef bank_dom::User argument_type; + typedef size_t result_type; + + result_type operator() (const argument_type& value) const + { + result_type result = 17; + return result; + } +}; + +} // namespace std + +namespace bank_dom { + +struct Global +{ + std::vector keys; + std::vector<::bank_dom::User> users; + + size_t fbe_type() const noexcept { return 4; } + + Global(); + Global(const std::vector& arg_keys, const std::vector<::bank_dom::User>& arg_users); + Global(const Global& other) = default; + Global(Global&& other) = default; + ~Global() = default; + + Global& operator=(const Global& other) = default; + Global& operator=(Global&& other) = default; + + bool operator==(const Global& other) const noexcept; + bool operator!=(const Global& other) const noexcept { return !operator==(other); } + bool operator<(const Global& other) const noexcept; + bool operator<=(const Global& other) const noexcept { return operator<(other) || operator==(other); } + bool operator>(const Global& other) const noexcept { return !operator<=(other); } + bool operator>=(const Global& other) const noexcept { return !operator<(other); } + + std::string string() const { std::stringstream ss; ss << *this; return ss.str(); } + + friend std::ostream& operator<<(std::ostream& stream, const Global& value); + + void swap(Global& other) noexcept; + friend void swap(Global& value1, Global& value2) noexcept { value1.swap(value2); } +}; + +} // namespace bank_dom + +namespace std { + +template<> +struct hash +{ + typedef bank_dom::Global argument_type; + typedef size_t result_type; + + result_type operator() (const argument_type& value) const + { + result_type result = 17; + return result; + } +}; + +} // namespace std + +namespace bank_dom { + +} // namespace bank_dom diff --git a/fbe/user_model/bank_dom_final_models.cpp b/fbe/user_model/bank_dom_final_models.cpp new file mode 100644 index 0000000..cc15906 --- /dev/null +++ b/fbe/user_model/bank_dom_final_models.cpp @@ -0,0 +1,638 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: user_model.fbe +// Version: 1.7.0.0 + +#include "bank_dom_final_models.h" + +namespace FBE { + +FinalModel<::bank_dom::Transaction>::FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) + , from(buffer, 0) + , to(buffer, 0) + , amount(buffer, 0) + , time(buffer, 0) +{} + +size_t FinalModel<::bank_dom::Transaction>::fbe_allocation_size(const ::bank_dom::Transaction& fbe_value) const noexcept +{ + size_t fbe_result = 0 + + from.fbe_allocation_size(fbe_value.from) + + to.fbe_allocation_size(fbe_value.to) + + amount.fbe_allocation_size(fbe_value.amount) + + time.fbe_allocation_size(fbe_value.time) + ; + return fbe_result; +} + +size_t FinalModel<::bank_dom::Transaction>::verify() const noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = verify_fields(); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::Transaction>::verify_fields() const noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_field_size; + + from.fbe_offset(fbe_current_offset); + fbe_field_size = from.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + to.fbe_offset(fbe_current_offset); + fbe_field_size = to.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + amount.fbe_offset(fbe_current_offset); + fbe_field_size = amount.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + time.fbe_offset(fbe_current_offset); + fbe_field_size = time.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + return fbe_current_offset; +} + +size_t FinalModel<::bank_dom::Transaction>::get(::bank_dom::Transaction& fbe_value) const noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = get_fields(fbe_value); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::Transaction>::get_fields(::bank_dom::Transaction& fbe_value) const noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_current_size = 0; + size_t fbe_field_size; + + from.fbe_offset(fbe_current_offset); + fbe_field_size = from.get(fbe_value.from); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + to.fbe_offset(fbe_current_offset); + fbe_field_size = to.get(fbe_value.to); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + amount.fbe_offset(fbe_current_offset); + fbe_field_size = amount.get(fbe_value.amount); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + time.fbe_offset(fbe_current_offset); + fbe_field_size = time.get(fbe_value.time); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + return fbe_current_size; +} + +size_t FinalModel<::bank_dom::Transaction>::set(const ::bank_dom::Transaction& fbe_value) noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = set_fields(fbe_value); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::Transaction>::set_fields(const ::bank_dom::Transaction& fbe_value) noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_current_size = 0; + size_t fbe_field_size; + + from.fbe_offset(fbe_current_offset); + fbe_field_size = from.set(fbe_value.from); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + to.fbe_offset(fbe_current_offset); + fbe_field_size = to.set(fbe_value.to); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + amount.fbe_offset(fbe_current_offset); + fbe_field_size = amount.set(fbe_value.amount); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + time.fbe_offset(fbe_current_offset); + fbe_field_size = time.set(fbe_value.time); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + return fbe_current_size; +} + +namespace bank_dom { + +bool TransactionFinalModel::verify() +{ + if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size()) + return false; + + size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)); + size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)); + if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type())) + return false; + + return ((8 + _model.verify()) == fbe_struct_size); +} + +size_t TransactionFinalModel::serialize(const ::bank_dom::Transaction& value) +{ + size_t fbe_initial_size = this->buffer().size(); + + uint32_t fbe_struct_type = (uint32_t)fbe_type(); + uint32_t fbe_struct_size = (uint32_t)(8 + _model.fbe_allocation_size(value)); + uint32_t fbe_struct_offset = (uint32_t)(this->buffer().allocate(fbe_struct_size) - this->buffer().offset()); + assert(((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) <= this->buffer().size()) && "Model is broken!"); + if ((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) > this->buffer().size()) + return 0; + + fbe_struct_size = (uint32_t)(8 + _model.set(value)); + this->buffer().resize(fbe_initial_size + fbe_struct_size); + + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)) = fbe_struct_size; + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)) = fbe_struct_type; + + return fbe_struct_size; +} + +size_t TransactionFinalModel::deserialize(::bank_dom::Transaction& value) const noexcept +{ + assert(((this->buffer().offset() + _model.fbe_offset()) <= this->buffer().size()) && "Model is broken!"); + if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size()) + return 0; + + size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)); + size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)); + assert(((fbe_struct_size > 0) && (fbe_struct_type == fbe_type())) && "Model is broken!"); + if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type())) + return 8; + + return 8 + _model.get(value); +} + +} // namespace bank_dom + +FinalModel<::bank_dom::Logs>::FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) + , data(buffer, 0) +{} + +size_t FinalModel<::bank_dom::Logs>::fbe_allocation_size(const ::bank_dom::Logs& fbe_value) const noexcept +{ + size_t fbe_result = 0 + + data.fbe_allocation_size(fbe_value.data) + ; + return fbe_result; +} + +size_t FinalModel<::bank_dom::Logs>::verify() const noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = verify_fields(); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::Logs>::verify_fields() const noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_field_size; + + data.fbe_offset(fbe_current_offset); + fbe_field_size = data.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + return fbe_current_offset; +} + +size_t FinalModel<::bank_dom::Logs>::get(::bank_dom::Logs& fbe_value) const noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = get_fields(fbe_value); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::Logs>::get_fields(::bank_dom::Logs& fbe_value) const noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_current_size = 0; + size_t fbe_field_size; + + data.fbe_offset(fbe_current_offset); + fbe_field_size = data.get(fbe_value.data); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + return fbe_current_size; +} + +size_t FinalModel<::bank_dom::Logs>::set(const ::bank_dom::Logs& fbe_value) noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = set_fields(fbe_value); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::Logs>::set_fields(const ::bank_dom::Logs& fbe_value) noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_current_size = 0; + size_t fbe_field_size; + + data.fbe_offset(fbe_current_offset); + fbe_field_size = data.set(fbe_value.data); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + return fbe_current_size; +} + +namespace bank_dom { + +bool LogsFinalModel::verify() +{ + if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size()) + return false; + + size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)); + size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)); + if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type())) + return false; + + return ((8 + _model.verify()) == fbe_struct_size); +} + +size_t LogsFinalModel::serialize(const ::bank_dom::Logs& value) +{ + size_t fbe_initial_size = this->buffer().size(); + + uint32_t fbe_struct_type = (uint32_t)fbe_type(); + uint32_t fbe_struct_size = (uint32_t)(8 + _model.fbe_allocation_size(value)); + uint32_t fbe_struct_offset = (uint32_t)(this->buffer().allocate(fbe_struct_size) - this->buffer().offset()); + assert(((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) <= this->buffer().size()) && "Model is broken!"); + if ((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) > this->buffer().size()) + return 0; + + fbe_struct_size = (uint32_t)(8 + _model.set(value)); + this->buffer().resize(fbe_initial_size + fbe_struct_size); + + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)) = fbe_struct_size; + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)) = fbe_struct_type; + + return fbe_struct_size; +} + +size_t LogsFinalModel::deserialize(::bank_dom::Logs& value) const noexcept +{ + assert(((this->buffer().offset() + _model.fbe_offset()) <= this->buffer().size()) && "Model is broken!"); + if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size()) + return 0; + + size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)); + size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)); + assert(((fbe_struct_size > 0) && (fbe_struct_type == fbe_type())) && "Model is broken!"); + if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type())) + return 8; + + return 8 + _model.get(value); +} + +} // namespace bank_dom + +FinalModel<::bank_dom::User>::FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) + , balance(buffer, 0) + , password(buffer, 0) + , logs(buffer, 0) +{} + +size_t FinalModel<::bank_dom::User>::fbe_allocation_size(const ::bank_dom::User& fbe_value) const noexcept +{ + size_t fbe_result = 0 + + balance.fbe_allocation_size(fbe_value.balance) + + password.fbe_allocation_size(fbe_value.password) + + logs.fbe_allocation_size(fbe_value.logs) + ; + return fbe_result; +} + +size_t FinalModel<::bank_dom::User>::verify() const noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = verify_fields(); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::User>::verify_fields() const noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_field_size; + + balance.fbe_offset(fbe_current_offset); + fbe_field_size = balance.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + password.fbe_offset(fbe_current_offset); + fbe_field_size = password.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + logs.fbe_offset(fbe_current_offset); + fbe_field_size = logs.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + return fbe_current_offset; +} + +size_t FinalModel<::bank_dom::User>::get(::bank_dom::User& fbe_value) const noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = get_fields(fbe_value); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::User>::get_fields(::bank_dom::User& fbe_value) const noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_current_size = 0; + size_t fbe_field_size; + + balance.fbe_offset(fbe_current_offset); + fbe_field_size = balance.get(fbe_value.balance); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + password.fbe_offset(fbe_current_offset); + fbe_field_size = password.get(fbe_value.password); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + logs.fbe_offset(fbe_current_offset); + fbe_field_size = logs.get(fbe_value.logs); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + return fbe_current_size; +} + +size_t FinalModel<::bank_dom::User>::set(const ::bank_dom::User& fbe_value) noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = set_fields(fbe_value); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::User>::set_fields(const ::bank_dom::User& fbe_value) noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_current_size = 0; + size_t fbe_field_size; + + balance.fbe_offset(fbe_current_offset); + fbe_field_size = balance.set(fbe_value.balance); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + password.fbe_offset(fbe_current_offset); + fbe_field_size = password.set(fbe_value.password); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + logs.fbe_offset(fbe_current_offset); + fbe_field_size = logs.set(fbe_value.logs); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + return fbe_current_size; +} + +namespace bank_dom { + +bool UserFinalModel::verify() +{ + if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size()) + return false; + + size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)); + size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)); + if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type())) + return false; + + return ((8 + _model.verify()) == fbe_struct_size); +} + +size_t UserFinalModel::serialize(const ::bank_dom::User& value) +{ + size_t fbe_initial_size = this->buffer().size(); + + uint32_t fbe_struct_type = (uint32_t)fbe_type(); + uint32_t fbe_struct_size = (uint32_t)(8 + _model.fbe_allocation_size(value)); + uint32_t fbe_struct_offset = (uint32_t)(this->buffer().allocate(fbe_struct_size) - this->buffer().offset()); + assert(((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) <= this->buffer().size()) && "Model is broken!"); + if ((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) > this->buffer().size()) + return 0; + + fbe_struct_size = (uint32_t)(8 + _model.set(value)); + this->buffer().resize(fbe_initial_size + fbe_struct_size); + + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)) = fbe_struct_size; + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)) = fbe_struct_type; + + return fbe_struct_size; +} + +size_t UserFinalModel::deserialize(::bank_dom::User& value) const noexcept +{ + assert(((this->buffer().offset() + _model.fbe_offset()) <= this->buffer().size()) && "Model is broken!"); + if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size()) + return 0; + + size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)); + size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)); + assert(((fbe_struct_size > 0) && (fbe_struct_type == fbe_type())) && "Model is broken!"); + if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type())) + return 8; + + return 8 + _model.get(value); +} + +} // namespace bank_dom + +FinalModel<::bank_dom::Global>::FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) + , keys(buffer, 0) + , users(buffer, 0) +{} + +size_t FinalModel<::bank_dom::Global>::fbe_allocation_size(const ::bank_dom::Global& fbe_value) const noexcept +{ + size_t fbe_result = 0 + + keys.fbe_allocation_size(fbe_value.keys) + + users.fbe_allocation_size(fbe_value.users) + ; + return fbe_result; +} + +size_t FinalModel<::bank_dom::Global>::verify() const noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = verify_fields(); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::Global>::verify_fields() const noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_field_size; + + keys.fbe_offset(fbe_current_offset); + fbe_field_size = keys.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + users.fbe_offset(fbe_current_offset); + fbe_field_size = users.verify(); + if (fbe_field_size == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_current_offset += fbe_field_size; + + return fbe_current_offset; +} + +size_t FinalModel<::bank_dom::Global>::get(::bank_dom::Global& fbe_value) const noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = get_fields(fbe_value); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::Global>::get_fields(::bank_dom::Global& fbe_value) const noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_current_size = 0; + size_t fbe_field_size; + + keys.fbe_offset(fbe_current_offset); + fbe_field_size = keys.get(fbe_value.keys); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + users.fbe_offset(fbe_current_offset); + fbe_field_size = users.get(fbe_value.users); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + return fbe_current_size; +} + +size_t FinalModel<::bank_dom::Global>::set(const ::bank_dom::Global& fbe_value) noexcept +{ + _buffer.shift(fbe_offset()); + size_t fbe_result = set_fields(fbe_value); + _buffer.unshift(fbe_offset()); + return fbe_result; +} + +size_t FinalModel<::bank_dom::Global>::set_fields(const ::bank_dom::Global& fbe_value) noexcept +{ + size_t fbe_current_offset = 0; + size_t fbe_current_size = 0; + size_t fbe_field_size; + + keys.fbe_offset(fbe_current_offset); + fbe_field_size = keys.set(fbe_value.keys); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + users.fbe_offset(fbe_current_offset); + fbe_field_size = users.set(fbe_value.users); + fbe_current_offset += fbe_field_size; + fbe_current_size += fbe_field_size; + + return fbe_current_size; +} + +namespace bank_dom { + +bool GlobalFinalModel::verify() +{ + if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size()) + return false; + + size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)); + size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)); + if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type())) + return false; + + return ((8 + _model.verify()) == fbe_struct_size); +} + +size_t GlobalFinalModel::serialize(const ::bank_dom::Global& value) +{ + size_t fbe_initial_size = this->buffer().size(); + + uint32_t fbe_struct_type = (uint32_t)fbe_type(); + uint32_t fbe_struct_size = (uint32_t)(8 + _model.fbe_allocation_size(value)); + uint32_t fbe_struct_offset = (uint32_t)(this->buffer().allocate(fbe_struct_size) - this->buffer().offset()); + assert(((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) <= this->buffer().size()) && "Model is broken!"); + if ((this->buffer().offset() + fbe_struct_offset + fbe_struct_size) > this->buffer().size()) + return 0; + + fbe_struct_size = (uint32_t)(8 + _model.set(value)); + this->buffer().resize(fbe_initial_size + fbe_struct_size); + + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)) = fbe_struct_size; + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)) = fbe_struct_type; + + return fbe_struct_size; +} + +size_t GlobalFinalModel::deserialize(::bank_dom::Global& value) const noexcept +{ + assert(((this->buffer().offset() + _model.fbe_offset()) <= this->buffer().size()) && "Model is broken!"); + if ((this->buffer().offset() + _model.fbe_offset()) > this->buffer().size()) + return 0; + + size_t fbe_struct_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 8)); + size_t fbe_struct_type = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + _model.fbe_offset() - 4)); + assert(((fbe_struct_size > 0) && (fbe_struct_type == fbe_type())) && "Model is broken!"); + if ((fbe_struct_size == 0) || (fbe_struct_type != fbe_type())) + return 8; + + return 8 + _model.get(value); +} + +} // namespace bank_dom + +} // namespace FBE diff --git a/fbe/user_model/bank_dom_final_models.h b/fbe/user_model/bank_dom_final_models.h new file mode 100644 index 0000000..335df6f --- /dev/null +++ b/fbe/user_model/bank_dom_final_models.h @@ -0,0 +1,320 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: user_model.fbe +// Version: 1.7.0.0 + +#pragma once + +#if defined(__clang__) +#pragma clang system_header +#elif defined(__GNUC__) +#pragma GCC system_header +#elif defined(_MSC_VER) +#pragma system_header +#endif + +#include "fbe_final_models.h" + +#include "bank_dom.h" + +namespace FBE { + +// Fast Binary Encoding ::bank_dom::Transaction final model +template <> +class FinalModel<::bank_dom::Transaction> +{ +public: + FinalModel(FBEBuffer& buffer, size_t offset) noexcept; + + // Get the allocation size + size_t fbe_allocation_size(const ::bank_dom::Transaction& fbe_value) const noexcept; + // Get the final offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the final offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + // Get the final type + static constexpr size_t fbe_type() noexcept { return 1; } + + // Shift the current final offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current final offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the struct value is valid + size_t verify() const noexcept; + // Check if the struct fields are valid + size_t verify_fields() const noexcept; + + // Get the struct value + size_t get(::bank_dom::Transaction& fbe_value) const noexcept; + // Get the struct fields values + size_t get_fields(::bank_dom::Transaction& fbe_value) const noexcept; + + // Set the struct value + size_t set(const ::bank_dom::Transaction& fbe_value) noexcept; + // Set the struct fields values + size_t set_fields(const ::bank_dom::Transaction& fbe_value) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; + +public: + FinalModel from; + FinalModel to; + FinalModel amount; + FinalModel time; +}; + +namespace bank_dom { + +// Fast Binary Encoding Transaction final model +class TransactionFinalModel : public FBE::Model +{ +public: + TransactionFinalModel() : _model(this->buffer(), 8) {} + TransactionFinalModel(const std::shared_ptr& buffer) : FBE::Model(buffer), _model(this->buffer(), 8) {} + + // Get the model type + static constexpr size_t fbe_type() noexcept { return FinalModel<::bank_dom::Transaction>::fbe_type(); } + + // Check if the struct value is valid + bool verify(); + + // Serialize the struct value + size_t serialize(const ::bank_dom::Transaction& value); + // Deserialize the struct value + size_t deserialize(::bank_dom::Transaction& value) const noexcept; + + // Move to the next struct value + void next(size_t prev) noexcept { _model.fbe_shift(prev); } + +private: + FinalModel<::bank_dom::Transaction> _model; +}; + +} // namespace bank_dom + +// Fast Binary Encoding ::bank_dom::Logs final model +template <> +class FinalModel<::bank_dom::Logs> +{ +public: + FinalModel(FBEBuffer& buffer, size_t offset) noexcept; + + // Get the allocation size + size_t fbe_allocation_size(const ::bank_dom::Logs& fbe_value) const noexcept; + // Get the final offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the final offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + // Get the final type + static constexpr size_t fbe_type() noexcept { return 2; } + + // Shift the current final offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current final offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the struct value is valid + size_t verify() const noexcept; + // Check if the struct fields are valid + size_t verify_fields() const noexcept; + + // Get the struct value + size_t get(::bank_dom::Logs& fbe_value) const noexcept; + // Get the struct fields values + size_t get_fields(::bank_dom::Logs& fbe_value) const noexcept; + + // Set the struct value + size_t set(const ::bank_dom::Logs& fbe_value) noexcept; + // Set the struct fields values + size_t set_fields(const ::bank_dom::Logs& fbe_value) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; + +public: + FinalModelVector<::bank_dom::Transaction> data; +}; + +namespace bank_dom { + +// Fast Binary Encoding Logs final model +class LogsFinalModel : public FBE::Model +{ +public: + LogsFinalModel() : _model(this->buffer(), 8) {} + LogsFinalModel(const std::shared_ptr& buffer) : FBE::Model(buffer), _model(this->buffer(), 8) {} + + // Get the model type + static constexpr size_t fbe_type() noexcept { return FinalModel<::bank_dom::Logs>::fbe_type(); } + + // Check if the struct value is valid + bool verify(); + + // Serialize the struct value + size_t serialize(const ::bank_dom::Logs& value); + // Deserialize the struct value + size_t deserialize(::bank_dom::Logs& value) const noexcept; + + // Move to the next struct value + void next(size_t prev) noexcept { _model.fbe_shift(prev); } + +private: + FinalModel<::bank_dom::Logs> _model; +}; + +} // namespace bank_dom + +// Fast Binary Encoding ::bank_dom::User final model +template <> +class FinalModel<::bank_dom::User> +{ +public: + FinalModel(FBEBuffer& buffer, size_t offset) noexcept; + + // Get the allocation size + size_t fbe_allocation_size(const ::bank_dom::User& fbe_value) const noexcept; + // Get the final offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the final offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + // Get the final type + static constexpr size_t fbe_type() noexcept { return 3; } + + // Shift the current final offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current final offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the struct value is valid + size_t verify() const noexcept; + // Check if the struct fields are valid + size_t verify_fields() const noexcept; + + // Get the struct value + size_t get(::bank_dom::User& fbe_value) const noexcept; + // Get the struct fields values + size_t get_fields(::bank_dom::User& fbe_value) const noexcept; + + // Set the struct value + size_t set(const ::bank_dom::User& fbe_value) noexcept; + // Set the struct fields values + size_t set_fields(const ::bank_dom::User& fbe_value) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; + +public: + FinalModel balance; + FinalModel password; + FinalModel> logs; +}; + +namespace bank_dom { + +// Fast Binary Encoding User final model +class UserFinalModel : public FBE::Model +{ +public: + UserFinalModel() : _model(this->buffer(), 8) {} + UserFinalModel(const std::shared_ptr& buffer) : FBE::Model(buffer), _model(this->buffer(), 8) {} + + // Get the model type + static constexpr size_t fbe_type() noexcept { return FinalModel<::bank_dom::User>::fbe_type(); } + + // Check if the struct value is valid + bool verify(); + + // Serialize the struct value + size_t serialize(const ::bank_dom::User& value); + // Deserialize the struct value + size_t deserialize(::bank_dom::User& value) const noexcept; + + // Move to the next struct value + void next(size_t prev) noexcept { _model.fbe_shift(prev); } + +private: + FinalModel<::bank_dom::User> _model; +}; + +} // namespace bank_dom + +// Fast Binary Encoding ::bank_dom::Global final model +template <> +class FinalModel<::bank_dom::Global> +{ +public: + FinalModel(FBEBuffer& buffer, size_t offset) noexcept; + + // Get the allocation size + size_t fbe_allocation_size(const ::bank_dom::Global& fbe_value) const noexcept; + // Get the final offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the final offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + // Get the final type + static constexpr size_t fbe_type() noexcept { return 4; } + + // Shift the current final offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current final offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the struct value is valid + size_t verify() const noexcept; + // Check if the struct fields are valid + size_t verify_fields() const noexcept; + + // Get the struct value + size_t get(::bank_dom::Global& fbe_value) const noexcept; + // Get the struct fields values + size_t get_fields(::bank_dom::Global& fbe_value) const noexcept; + + // Set the struct value + size_t set(const ::bank_dom::Global& fbe_value) noexcept; + // Set the struct fields values + size_t set_fields(const ::bank_dom::Global& fbe_value) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; + +public: + FinalModelVector keys; + FinalModelVector<::bank_dom::User> users; +}; + +namespace bank_dom { + +// Fast Binary Encoding Global final model +class GlobalFinalModel : public FBE::Model +{ +public: + GlobalFinalModel() : _model(this->buffer(), 8) {} + GlobalFinalModel(const std::shared_ptr& buffer) : FBE::Model(buffer), _model(this->buffer(), 8) {} + + // Get the model type + static constexpr size_t fbe_type() noexcept { return FinalModel<::bank_dom::Global>::fbe_type(); } + + // Check if the struct value is valid + bool verify(); + + // Serialize the struct value + size_t serialize(const ::bank_dom::Global& value); + // Deserialize the struct value + size_t deserialize(::bank_dom::Global& value) const noexcept; + + // Move to the next struct value + void next(size_t prev) noexcept { _model.fbe_shift(prev); } + +private: + FinalModel<::bank_dom::Global> _model; +}; + +} // namespace bank_dom + +} // namespace FBE diff --git a/fbe/user_model/bank_dom_models.cpp b/fbe/user_model/bank_dom_models.cpp new file mode 100644 index 0000000..9d18299 --- /dev/null +++ b/fbe/user_model/bank_dom_models.cpp @@ -0,0 +1,930 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: user_model.fbe +// Version: 1.7.0.0 + +#include "bank_dom_models.h" + +namespace FBE { + +FieldModel<::bank_dom::Transaction>::FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) + , from(buffer, 4 + 4) + , to(buffer, from.fbe_offset() + from.fbe_size()) + , amount(buffer, to.fbe_offset() + to.fbe_size()) + , time(buffer, amount.fbe_offset() + amount.fbe_size()) +{} + +size_t FieldModel<::bank_dom::Transaction>::fbe_body() const noexcept +{ + size_t fbe_result = 4 + 4 + + from.fbe_size() + + to.fbe_size() + + amount.fbe_size() + + time.fbe_size() + ; + return fbe_result; +} + +size_t FieldModel<::bank_dom::Transaction>::fbe_extra() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4) > _buffer.size())) + return 0; + + _buffer.shift(fbe_struct_offset); + + size_t fbe_result = fbe_body() + + from.fbe_extra() + + to.fbe_extra() + + amount.fbe_extra() + + time.fbe_extra() + ; + + _buffer.unshift(fbe_struct_offset); + + return fbe_result; +} + +bool FieldModel<::bank_dom::Transaction>::verify(bool fbe_verify_type) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return true; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size())) + return false; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)); + if (fbe_struct_size < (4 + 4)) + return false; + + uint32_t fbe_struct_type = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4)); + if (fbe_verify_type && (fbe_struct_type != fbe_type())) + return false; + + _buffer.shift(fbe_struct_offset); + bool fbe_result = verify_fields(fbe_struct_size); + _buffer.unshift(fbe_struct_offset); + return fbe_result; +} + +bool FieldModel<::bank_dom::Transaction>::verify_fields(size_t fbe_struct_size) const noexcept +{ + size_t fbe_current_size = 4 + 4; + + if ((fbe_current_size + from.fbe_size()) > fbe_struct_size) + return true; + if (!from.verify()) + return false; + fbe_current_size += from.fbe_size(); + + if ((fbe_current_size + to.fbe_size()) > fbe_struct_size) + return true; + if (!to.verify()) + return false; + fbe_current_size += to.fbe_size(); + + if ((fbe_current_size + amount.fbe_size()) > fbe_struct_size) + return true; + if (!amount.verify()) + return false; + fbe_current_size += amount.fbe_size(); + + if ((fbe_current_size + time.fbe_size()) > fbe_struct_size) + return true; + if (!time.verify()) + return false; + fbe_current_size += time.fbe_size(); + + return true; +} + +size_t FieldModel<::bank_dom::Transaction>::get_begin() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + 4 + 4) <= _buffer.size())) && "Model is broken!"); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size())) + return 0; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)); + assert((fbe_struct_size >= (4 + 4)) && "Model is broken!"); + if (fbe_struct_size < (4 + 4)) + return 0; + + _buffer.shift(fbe_struct_offset); + return fbe_struct_offset; +} + +void FieldModel<::bank_dom::Transaction>::get_end(size_t fbe_begin) const noexcept +{ + _buffer.unshift(fbe_begin); +} + +void FieldModel<::bank_dom::Transaction>::get(::bank_dom::Transaction& fbe_value) const noexcept +{ + size_t fbe_begin = get_begin(); + if (fbe_begin == 0) + return; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset())); + get_fields(fbe_value, fbe_struct_size); + get_end(fbe_begin); +} + +void FieldModel<::bank_dom::Transaction>::get_fields(::bank_dom::Transaction& fbe_value, size_t fbe_struct_size) const noexcept +{ + size_t fbe_current_size = 4 + 4; + + if ((fbe_current_size + from.fbe_size()) <= fbe_struct_size) + from.get(fbe_value.from, ""); + else + fbe_value.from = ""; + fbe_current_size += from.fbe_size(); + + if ((fbe_current_size + to.fbe_size()) <= fbe_struct_size) + to.get(fbe_value.to, ""); + else + fbe_value.to = ""; + fbe_current_size += to.fbe_size(); + + if ((fbe_current_size + amount.fbe_size()) <= fbe_struct_size) + amount.get(fbe_value.amount, (uint32_t)0ull); + else + fbe_value.amount = (uint32_t)0ull; + fbe_current_size += amount.fbe_size(); + + if ((fbe_current_size + time.fbe_size()) <= fbe_struct_size) + time.get(fbe_value.time); + else + fbe_value.time = (uint64_t)0ull; + fbe_current_size += time.fbe_size(); +} + +size_t FieldModel<::bank_dom::Transaction>::set_begin() +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_size = (uint32_t)fbe_body(); + uint32_t fbe_struct_offset = (uint32_t)(_buffer.allocate(fbe_struct_size) - _buffer.offset()); + assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) <= _buffer.size())) && "Model is broken!"); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) > _buffer.size())) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_struct_offset; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)) = fbe_struct_size; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4)) = (uint32_t)fbe_type(); + + _buffer.shift(fbe_struct_offset); + return fbe_struct_offset; +} + +void FieldModel<::bank_dom::Transaction>::set_end(size_t fbe_begin) +{ + _buffer.unshift(fbe_begin); +} + +void FieldModel<::bank_dom::Transaction>::set(const ::bank_dom::Transaction& fbe_value) noexcept +{ + size_t fbe_begin = set_begin(); + if (fbe_begin == 0) + return; + + set_fields(fbe_value); + set_end(fbe_begin); +} + +void FieldModel<::bank_dom::Transaction>::set_fields(const ::bank_dom::Transaction& fbe_value) noexcept +{ + from.set(fbe_value.from); + to.set(fbe_value.to); + amount.set(fbe_value.amount); + time.set(fbe_value.time); +} + +namespace bank_dom { + +bool TransactionModel::verify() +{ + if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size()) + return false; + + uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)); + if (fbe_full_size < model.fbe_size()) + return false; + + return model.verify(); +} + +size_t TransactionModel::create_begin() +{ + size_t fbe_begin = this->buffer().allocate(4 + model.fbe_size()); + return fbe_begin; +} + +size_t TransactionModel::create_end(size_t fbe_begin) +{ + size_t fbe_end = this->buffer().size(); + uint32_t fbe_full_size = (uint32_t)(fbe_end - fbe_begin); + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)) = fbe_full_size; + return fbe_full_size; +} + +size_t TransactionModel::serialize(const ::bank_dom::Transaction& value) +{ + size_t fbe_begin = create_begin(); + model.set(value); + size_t fbe_full_size = create_end(fbe_begin); + return fbe_full_size; +} + +size_t TransactionModel::deserialize(::bank_dom::Transaction& value) const noexcept +{ + if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size()) + return 0; + + uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)); + assert((fbe_full_size >= model.fbe_size()) && "Model is broken!"); + if (fbe_full_size < model.fbe_size()) + return 0; + + model.get(value); + return fbe_full_size; +} + +} // namespace bank_dom + +FieldModel<::bank_dom::Logs>::FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) + , data(buffer, 4 + 4) +{} + +size_t FieldModel<::bank_dom::Logs>::fbe_body() const noexcept +{ + size_t fbe_result = 4 + 4 + + data.fbe_size() + ; + return fbe_result; +} + +size_t FieldModel<::bank_dom::Logs>::fbe_extra() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4) > _buffer.size())) + return 0; + + _buffer.shift(fbe_struct_offset); + + size_t fbe_result = fbe_body() + + data.fbe_extra() + ; + + _buffer.unshift(fbe_struct_offset); + + return fbe_result; +} + +bool FieldModel<::bank_dom::Logs>::verify(bool fbe_verify_type) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return true; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size())) + return false; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)); + if (fbe_struct_size < (4 + 4)) + return false; + + uint32_t fbe_struct_type = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4)); + if (fbe_verify_type && (fbe_struct_type != fbe_type())) + return false; + + _buffer.shift(fbe_struct_offset); + bool fbe_result = verify_fields(fbe_struct_size); + _buffer.unshift(fbe_struct_offset); + return fbe_result; +} + +bool FieldModel<::bank_dom::Logs>::verify_fields(size_t fbe_struct_size) const noexcept +{ + size_t fbe_current_size = 4 + 4; + + if ((fbe_current_size + data.fbe_size()) > fbe_struct_size) + return true; + if (!data.verify()) + return false; + fbe_current_size += data.fbe_size(); + + return true; +} + +size_t FieldModel<::bank_dom::Logs>::get_begin() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + 4 + 4) <= _buffer.size())) && "Model is broken!"); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size())) + return 0; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)); + assert((fbe_struct_size >= (4 + 4)) && "Model is broken!"); + if (fbe_struct_size < (4 + 4)) + return 0; + + _buffer.shift(fbe_struct_offset); + return fbe_struct_offset; +} + +void FieldModel<::bank_dom::Logs>::get_end(size_t fbe_begin) const noexcept +{ + _buffer.unshift(fbe_begin); +} + +void FieldModel<::bank_dom::Logs>::get(::bank_dom::Logs& fbe_value) const noexcept +{ + size_t fbe_begin = get_begin(); + if (fbe_begin == 0) + return; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset())); + get_fields(fbe_value, fbe_struct_size); + get_end(fbe_begin); +} + +void FieldModel<::bank_dom::Logs>::get_fields(::bank_dom::Logs& fbe_value, size_t fbe_struct_size) const noexcept +{ + size_t fbe_current_size = 4 + 4; + + if ((fbe_current_size + data.fbe_size()) <= fbe_struct_size) + data.get(fbe_value.data); + else + fbe_value.data.clear(); + fbe_current_size += data.fbe_size(); +} + +size_t FieldModel<::bank_dom::Logs>::set_begin() +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_size = (uint32_t)fbe_body(); + uint32_t fbe_struct_offset = (uint32_t)(_buffer.allocate(fbe_struct_size) - _buffer.offset()); + assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) <= _buffer.size())) && "Model is broken!"); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) > _buffer.size())) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_struct_offset; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)) = fbe_struct_size; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4)) = (uint32_t)fbe_type(); + + _buffer.shift(fbe_struct_offset); + return fbe_struct_offset; +} + +void FieldModel<::bank_dom::Logs>::set_end(size_t fbe_begin) +{ + _buffer.unshift(fbe_begin); +} + +void FieldModel<::bank_dom::Logs>::set(const ::bank_dom::Logs& fbe_value) noexcept +{ + size_t fbe_begin = set_begin(); + if (fbe_begin == 0) + return; + + set_fields(fbe_value); + set_end(fbe_begin); +} + +void FieldModel<::bank_dom::Logs>::set_fields(const ::bank_dom::Logs& fbe_value) noexcept +{ + data.set(fbe_value.data); +} + +namespace bank_dom { + +bool LogsModel::verify() +{ + if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size()) + return false; + + uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)); + if (fbe_full_size < model.fbe_size()) + return false; + + return model.verify(); +} + +size_t LogsModel::create_begin() +{ + size_t fbe_begin = this->buffer().allocate(4 + model.fbe_size()); + return fbe_begin; +} + +size_t LogsModel::create_end(size_t fbe_begin) +{ + size_t fbe_end = this->buffer().size(); + uint32_t fbe_full_size = (uint32_t)(fbe_end - fbe_begin); + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)) = fbe_full_size; + return fbe_full_size; +} + +size_t LogsModel::serialize(const ::bank_dom::Logs& value) +{ + size_t fbe_begin = create_begin(); + model.set(value); + size_t fbe_full_size = create_end(fbe_begin); + return fbe_full_size; +} + +size_t LogsModel::deserialize(::bank_dom::Logs& value) const noexcept +{ + if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size()) + return 0; + + uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)); + assert((fbe_full_size >= model.fbe_size()) && "Model is broken!"); + if (fbe_full_size < model.fbe_size()) + return 0; + + model.get(value); + return fbe_full_size; +} + +} // namespace bank_dom + +FieldModel<::bank_dom::User>::FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) + , balance(buffer, 4 + 4) + , password(buffer, balance.fbe_offset() + balance.fbe_size()) + , logs(buffer, password.fbe_offset() + password.fbe_size()) +{} + +size_t FieldModel<::bank_dom::User>::fbe_body() const noexcept +{ + size_t fbe_result = 4 + 4 + + balance.fbe_size() + + password.fbe_size() + + logs.fbe_size() + ; + return fbe_result; +} + +size_t FieldModel<::bank_dom::User>::fbe_extra() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4) > _buffer.size())) + return 0; + + _buffer.shift(fbe_struct_offset); + + size_t fbe_result = fbe_body() + + balance.fbe_extra() + + password.fbe_extra() + + logs.fbe_extra() + ; + + _buffer.unshift(fbe_struct_offset); + + return fbe_result; +} + +bool FieldModel<::bank_dom::User>::verify(bool fbe_verify_type) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return true; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size())) + return false; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)); + if (fbe_struct_size < (4 + 4)) + return false; + + uint32_t fbe_struct_type = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4)); + if (fbe_verify_type && (fbe_struct_type != fbe_type())) + return false; + + _buffer.shift(fbe_struct_offset); + bool fbe_result = verify_fields(fbe_struct_size); + _buffer.unshift(fbe_struct_offset); + return fbe_result; +} + +bool FieldModel<::bank_dom::User>::verify_fields(size_t fbe_struct_size) const noexcept +{ + size_t fbe_current_size = 4 + 4; + + if ((fbe_current_size + balance.fbe_size()) > fbe_struct_size) + return true; + if (!balance.verify()) + return false; + fbe_current_size += balance.fbe_size(); + + if ((fbe_current_size + password.fbe_size()) > fbe_struct_size) + return true; + if (!password.verify()) + return false; + fbe_current_size += password.fbe_size(); + + if ((fbe_current_size + logs.fbe_size()) > fbe_struct_size) + return true; + if (!logs.verify()) + return false; + fbe_current_size += logs.fbe_size(); + + return true; +} + +size_t FieldModel<::bank_dom::User>::get_begin() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + 4 + 4) <= _buffer.size())) && "Model is broken!"); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size())) + return 0; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)); + assert((fbe_struct_size >= (4 + 4)) && "Model is broken!"); + if (fbe_struct_size < (4 + 4)) + return 0; + + _buffer.shift(fbe_struct_offset); + return fbe_struct_offset; +} + +void FieldModel<::bank_dom::User>::get_end(size_t fbe_begin) const noexcept +{ + _buffer.unshift(fbe_begin); +} + +void FieldModel<::bank_dom::User>::get(::bank_dom::User& fbe_value) const noexcept +{ + size_t fbe_begin = get_begin(); + if (fbe_begin == 0) + return; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset())); + get_fields(fbe_value, fbe_struct_size); + get_end(fbe_begin); +} + +void FieldModel<::bank_dom::User>::get_fields(::bank_dom::User& fbe_value, size_t fbe_struct_size) const noexcept +{ + size_t fbe_current_size = 4 + 4; + + if ((fbe_current_size + balance.fbe_size()) <= fbe_struct_size) + balance.get(fbe_value.balance, (uint32_t)0ull); + else + fbe_value.balance = (uint32_t)0ull; + fbe_current_size += balance.fbe_size(); + + if ((fbe_current_size + password.fbe_size()) <= fbe_struct_size) + password.get(fbe_value.password, (uint64_t)0ull); + else + fbe_value.password = (uint64_t)0ull; + fbe_current_size += password.fbe_size(); + + if ((fbe_current_size + logs.fbe_size()) <= fbe_struct_size) + logs.get(fbe_value.logs, std::nullopt); + else + fbe_value.logs = std::nullopt; + fbe_current_size += logs.fbe_size(); +} + +size_t FieldModel<::bank_dom::User>::set_begin() +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_size = (uint32_t)fbe_body(); + uint32_t fbe_struct_offset = (uint32_t)(_buffer.allocate(fbe_struct_size) - _buffer.offset()); + assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) <= _buffer.size())) && "Model is broken!"); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) > _buffer.size())) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_struct_offset; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)) = fbe_struct_size; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4)) = (uint32_t)fbe_type(); + + _buffer.shift(fbe_struct_offset); + return fbe_struct_offset; +} + +void FieldModel<::bank_dom::User>::set_end(size_t fbe_begin) +{ + _buffer.unshift(fbe_begin); +} + +void FieldModel<::bank_dom::User>::set(const ::bank_dom::User& fbe_value) noexcept +{ + size_t fbe_begin = set_begin(); + if (fbe_begin == 0) + return; + + set_fields(fbe_value); + set_end(fbe_begin); +} + +void FieldModel<::bank_dom::User>::set_fields(const ::bank_dom::User& fbe_value) noexcept +{ + balance.set(fbe_value.balance); + password.set(fbe_value.password); + logs.set(fbe_value.logs); +} + +namespace bank_dom { + +bool UserModel::verify() +{ + if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size()) + return false; + + uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)); + if (fbe_full_size < model.fbe_size()) + return false; + + return model.verify(); +} + +size_t UserModel::create_begin() +{ + size_t fbe_begin = this->buffer().allocate(4 + model.fbe_size()); + return fbe_begin; +} + +size_t UserModel::create_end(size_t fbe_begin) +{ + size_t fbe_end = this->buffer().size(); + uint32_t fbe_full_size = (uint32_t)(fbe_end - fbe_begin); + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)) = fbe_full_size; + return fbe_full_size; +} + +size_t UserModel::serialize(const ::bank_dom::User& value) +{ + size_t fbe_begin = create_begin(); + model.set(value); + size_t fbe_full_size = create_end(fbe_begin); + return fbe_full_size; +} + +size_t UserModel::deserialize(::bank_dom::User& value) const noexcept +{ + if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size()) + return 0; + + uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)); + assert((fbe_full_size >= model.fbe_size()) && "Model is broken!"); + if (fbe_full_size < model.fbe_size()) + return 0; + + model.get(value); + return fbe_full_size; +} + +} // namespace bank_dom + +FieldModel<::bank_dom::Global>::FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) + , keys(buffer, 4 + 4) + , users(buffer, keys.fbe_offset() + keys.fbe_size()) +{} + +size_t FieldModel<::bank_dom::Global>::fbe_body() const noexcept +{ + size_t fbe_result = 4 + 4 + + keys.fbe_size() + + users.fbe_size() + ; + return fbe_result; +} + +size_t FieldModel<::bank_dom::Global>::fbe_extra() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4) > _buffer.size())) + return 0; + + _buffer.shift(fbe_struct_offset); + + size_t fbe_result = fbe_body() + + keys.fbe_extra() + + users.fbe_extra() + ; + + _buffer.unshift(fbe_struct_offset); + + return fbe_result; +} + +bool FieldModel<::bank_dom::Global>::verify(bool fbe_verify_type) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return true; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size())) + return false; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)); + if (fbe_struct_size < (4 + 4)) + return false; + + uint32_t fbe_struct_type = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4)); + if (fbe_verify_type && (fbe_struct_type != fbe_type())) + return false; + + _buffer.shift(fbe_struct_offset); + bool fbe_result = verify_fields(fbe_struct_size); + _buffer.unshift(fbe_struct_offset); + return fbe_result; +} + +bool FieldModel<::bank_dom::Global>::verify_fields(size_t fbe_struct_size) const noexcept +{ + size_t fbe_current_size = 4 + 4; + + if ((fbe_current_size + keys.fbe_size()) > fbe_struct_size) + return true; + if (!keys.verify()) + return false; + fbe_current_size += keys.fbe_size(); + + if ((fbe_current_size + users.fbe_size()) > fbe_struct_size) + return true; + if (!users.verify()) + return false; + fbe_current_size += users.fbe_size(); + + return true; +} + +size_t FieldModel<::bank_dom::Global>::get_begin() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + 4 + 4) <= _buffer.size())) && "Model is broken!"); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + 4 + 4) > _buffer.size())) + return 0; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)); + assert((fbe_struct_size >= (4 + 4)) && "Model is broken!"); + if (fbe_struct_size < (4 + 4)) + return 0; + + _buffer.shift(fbe_struct_offset); + return fbe_struct_offset; +} + +void FieldModel<::bank_dom::Global>::get_end(size_t fbe_begin) const noexcept +{ + _buffer.unshift(fbe_begin); +} + +void FieldModel<::bank_dom::Global>::get(::bank_dom::Global& fbe_value) const noexcept +{ + size_t fbe_begin = get_begin(); + if (fbe_begin == 0) + return; + + uint32_t fbe_struct_size = *((const uint32_t*)(_buffer.data() + _buffer.offset())); + get_fields(fbe_value, fbe_struct_size); + get_end(fbe_begin); +} + +void FieldModel<::bank_dom::Global>::get_fields(::bank_dom::Global& fbe_value, size_t fbe_struct_size) const noexcept +{ + size_t fbe_current_size = 4 + 4; + + if ((fbe_current_size + keys.fbe_size()) <= fbe_struct_size) + keys.get(fbe_value.keys); + else + fbe_value.keys.clear(); + fbe_current_size += keys.fbe_size(); + + if ((fbe_current_size + users.fbe_size()) <= fbe_struct_size) + users.get(fbe_value.users); + else + fbe_value.users.clear(); + fbe_current_size += users.fbe_size(); +} + +size_t FieldModel<::bank_dom::Global>::set_begin() +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_struct_size = (uint32_t)fbe_body(); + uint32_t fbe_struct_offset = (uint32_t)(_buffer.allocate(fbe_struct_size) - _buffer.offset()); + assert(((fbe_struct_offset > 0) && ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) <= _buffer.size())) && "Model is broken!"); + if ((fbe_struct_offset == 0) || ((_buffer.offset() + fbe_struct_offset + fbe_struct_size) > _buffer.size())) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_struct_offset; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset)) = fbe_struct_size; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_struct_offset + 4)) = (uint32_t)fbe_type(); + + _buffer.shift(fbe_struct_offset); + return fbe_struct_offset; +} + +void FieldModel<::bank_dom::Global>::set_end(size_t fbe_begin) +{ + _buffer.unshift(fbe_begin); +} + +void FieldModel<::bank_dom::Global>::set(const ::bank_dom::Global& fbe_value) noexcept +{ + size_t fbe_begin = set_begin(); + if (fbe_begin == 0) + return; + + set_fields(fbe_value); + set_end(fbe_begin); +} + +void FieldModel<::bank_dom::Global>::set_fields(const ::bank_dom::Global& fbe_value) noexcept +{ + keys.set(fbe_value.keys); + users.set(fbe_value.users); +} + +namespace bank_dom { + +bool GlobalModel::verify() +{ + if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size()) + return false; + + uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)); + if (fbe_full_size < model.fbe_size()) + return false; + + return model.verify(); +} + +size_t GlobalModel::create_begin() +{ + size_t fbe_begin = this->buffer().allocate(4 + model.fbe_size()); + return fbe_begin; +} + +size_t GlobalModel::create_end(size_t fbe_begin) +{ + size_t fbe_end = this->buffer().size(); + uint32_t fbe_full_size = (uint32_t)(fbe_end - fbe_begin); + *((uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)) = fbe_full_size; + return fbe_full_size; +} + +size_t GlobalModel::serialize(const ::bank_dom::Global& value) +{ + size_t fbe_begin = create_begin(); + model.set(value); + size_t fbe_full_size = create_end(fbe_begin); + return fbe_full_size; +} + +size_t GlobalModel::deserialize(::bank_dom::Global& value) const noexcept +{ + if ((this->buffer().offset() + model.fbe_offset() - 4) > this->buffer().size()) + return 0; + + uint32_t fbe_full_size = *((const uint32_t*)(this->buffer().data() + this->buffer().offset() + model.fbe_offset() - 4)); + assert((fbe_full_size >= model.fbe_size()) && "Model is broken!"); + if (fbe_full_size < model.fbe_size()) + return 0; + + model.get(value); + return fbe_full_size; +} + +} // namespace bank_dom + +} // namespace FBE diff --git a/fbe/user_model/bank_dom_models.h b/fbe/user_model/bank_dom_models.h new file mode 100644 index 0000000..311a1a1 --- /dev/null +++ b/fbe/user_model/bank_dom_models.h @@ -0,0 +1,396 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: user_model.fbe +// Version: 1.7.0.0 + +#pragma once + +#if defined(__clang__) +#pragma clang system_header +#elif defined(__GNUC__) +#pragma GCC system_header +#elif defined(_MSC_VER) +#pragma system_header +#endif + +#include "fbe_models.h" + +#include "bank_dom.h" + +namespace FBE { + +// Fast Binary Encoding ::bank_dom::Transaction field model +template <> +class FieldModel<::bank_dom::Transaction> +{ +public: + FieldModel(FBEBuffer& buffer, size_t offset) noexcept; + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 4; } + // Get the field body size + size_t fbe_body() const noexcept; + // Get the field extra size + size_t fbe_extra() const noexcept; + // Get the field type + static constexpr size_t fbe_type() noexcept { return 1; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the struct value is valid + bool verify(bool fbe_verify_type = true) const noexcept; + // Check if the struct fields are valid + bool verify_fields(size_t fbe_struct_size) const noexcept; + + // Get the struct value (begin phase) + size_t get_begin() const noexcept; + // Get the struct value (end phase) + void get_end(size_t fbe_begin) const noexcept; + + // Get the struct value + void get(::bank_dom::Transaction& fbe_value) const noexcept; + // Get the struct fields values + void get_fields(::bank_dom::Transaction& fbe_value, size_t fbe_struct_size) const noexcept; + + // Set the struct value (begin phase) + size_t set_begin(); + // Set the struct value (end phase) + void set_end(size_t fbe_begin); + + // Set the struct value + void set(const ::bank_dom::Transaction& fbe_value) noexcept; + // Set the struct fields values + void set_fields(const ::bank_dom::Transaction& fbe_value) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; + +public: + FieldModel from; + FieldModel to; + FieldModel amount; + FieldModel time; +}; + +namespace bank_dom { + +// Fast Binary Encoding Transaction model +class TransactionModel : public FBE::Model +{ +public: + TransactionModel() : model(this->buffer(), 4) {} + TransactionModel(const std::shared_ptr& buffer) : FBE::Model(buffer), model(this->buffer(), 4) {} + + // Get the model size + size_t fbe_size() const noexcept { return model.fbe_size() + model.fbe_extra(); } + // Get the model type + static constexpr size_t fbe_type() noexcept { return FieldModel<::bank_dom::Transaction>::fbe_type(); } + + // Check if the struct value is valid + bool verify(); + + // Create a new model (begin phase) + size_t create_begin(); + // Create a new model (end phase) + size_t create_end(size_t fbe_begin); + + // Serialize the struct value + size_t serialize(const ::bank_dom::Transaction& value); + // Deserialize the struct value + size_t deserialize(::bank_dom::Transaction& value) const noexcept; + + // Move to the next struct value + void next(size_t prev) noexcept { model.fbe_shift(prev); } + +public: + FieldModel<::bank_dom::Transaction> model; +}; + +} // namespace bank_dom + +// Fast Binary Encoding ::bank_dom::Logs field model +template <> +class FieldModel<::bank_dom::Logs> +{ +public: + FieldModel(FBEBuffer& buffer, size_t offset) noexcept; + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 4; } + // Get the field body size + size_t fbe_body() const noexcept; + // Get the field extra size + size_t fbe_extra() const noexcept; + // Get the field type + static constexpr size_t fbe_type() noexcept { return 2; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the struct value is valid + bool verify(bool fbe_verify_type = true) const noexcept; + // Check if the struct fields are valid + bool verify_fields(size_t fbe_struct_size) const noexcept; + + // Get the struct value (begin phase) + size_t get_begin() const noexcept; + // Get the struct value (end phase) + void get_end(size_t fbe_begin) const noexcept; + + // Get the struct value + void get(::bank_dom::Logs& fbe_value) const noexcept; + // Get the struct fields values + void get_fields(::bank_dom::Logs& fbe_value, size_t fbe_struct_size) const noexcept; + + // Set the struct value (begin phase) + size_t set_begin(); + // Set the struct value (end phase) + void set_end(size_t fbe_begin); + + // Set the struct value + void set(const ::bank_dom::Logs& fbe_value) noexcept; + // Set the struct fields values + void set_fields(const ::bank_dom::Logs& fbe_value) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; + +public: + FieldModelVector<::bank_dom::Transaction> data; +}; + +namespace bank_dom { + +// Fast Binary Encoding Logs model +class LogsModel : public FBE::Model +{ +public: + LogsModel() : model(this->buffer(), 4) {} + LogsModel(const std::shared_ptr& buffer) : FBE::Model(buffer), model(this->buffer(), 4) {} + + // Get the model size + size_t fbe_size() const noexcept { return model.fbe_size() + model.fbe_extra(); } + // Get the model type + static constexpr size_t fbe_type() noexcept { return FieldModel<::bank_dom::Logs>::fbe_type(); } + + // Check if the struct value is valid + bool verify(); + + // Create a new model (begin phase) + size_t create_begin(); + // Create a new model (end phase) + size_t create_end(size_t fbe_begin); + + // Serialize the struct value + size_t serialize(const ::bank_dom::Logs& value); + // Deserialize the struct value + size_t deserialize(::bank_dom::Logs& value) const noexcept; + + // Move to the next struct value + void next(size_t prev) noexcept { model.fbe_shift(prev); } + +public: + FieldModel<::bank_dom::Logs> model; +}; + +} // namespace bank_dom + +// Fast Binary Encoding ::bank_dom::User field model +template <> +class FieldModel<::bank_dom::User> +{ +public: + FieldModel(FBEBuffer& buffer, size_t offset) noexcept; + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 4; } + // Get the field body size + size_t fbe_body() const noexcept; + // Get the field extra size + size_t fbe_extra() const noexcept; + // Get the field type + static constexpr size_t fbe_type() noexcept { return 3; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the struct value is valid + bool verify(bool fbe_verify_type = true) const noexcept; + // Check if the struct fields are valid + bool verify_fields(size_t fbe_struct_size) const noexcept; + + // Get the struct value (begin phase) + size_t get_begin() const noexcept; + // Get the struct value (end phase) + void get_end(size_t fbe_begin) const noexcept; + + // Get the struct value + void get(::bank_dom::User& fbe_value) const noexcept; + // Get the struct fields values + void get_fields(::bank_dom::User& fbe_value, size_t fbe_struct_size) const noexcept; + + // Set the struct value (begin phase) + size_t set_begin(); + // Set the struct value (end phase) + void set_end(size_t fbe_begin); + + // Set the struct value + void set(const ::bank_dom::User& fbe_value) noexcept; + // Set the struct fields values + void set_fields(const ::bank_dom::User& fbe_value) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; + +public: + FieldModel balance; + FieldModel password; + FieldModel> logs; +}; + +namespace bank_dom { + +// Fast Binary Encoding User model +class UserModel : public FBE::Model +{ +public: + UserModel() : model(this->buffer(), 4) {} + UserModel(const std::shared_ptr& buffer) : FBE::Model(buffer), model(this->buffer(), 4) {} + + // Get the model size + size_t fbe_size() const noexcept { return model.fbe_size() + model.fbe_extra(); } + // Get the model type + static constexpr size_t fbe_type() noexcept { return FieldModel<::bank_dom::User>::fbe_type(); } + + // Check if the struct value is valid + bool verify(); + + // Create a new model (begin phase) + size_t create_begin(); + // Create a new model (end phase) + size_t create_end(size_t fbe_begin); + + // Serialize the struct value + size_t serialize(const ::bank_dom::User& value); + // Deserialize the struct value + size_t deserialize(::bank_dom::User& value) const noexcept; + + // Move to the next struct value + void next(size_t prev) noexcept { model.fbe_shift(prev); } + +public: + FieldModel<::bank_dom::User> model; +}; + +} // namespace bank_dom + +// Fast Binary Encoding ::bank_dom::Global field model +template <> +class FieldModel<::bank_dom::Global> +{ +public: + FieldModel(FBEBuffer& buffer, size_t offset) noexcept; + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 4; } + // Get the field body size + size_t fbe_body() const noexcept; + // Get the field extra size + size_t fbe_extra() const noexcept; + // Get the field type + static constexpr size_t fbe_type() noexcept { return 4; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the struct value is valid + bool verify(bool fbe_verify_type = true) const noexcept; + // Check if the struct fields are valid + bool verify_fields(size_t fbe_struct_size) const noexcept; + + // Get the struct value (begin phase) + size_t get_begin() const noexcept; + // Get the struct value (end phase) + void get_end(size_t fbe_begin) const noexcept; + + // Get the struct value + void get(::bank_dom::Global& fbe_value) const noexcept; + // Get the struct fields values + void get_fields(::bank_dom::Global& fbe_value, size_t fbe_struct_size) const noexcept; + + // Set the struct value (begin phase) + size_t set_begin(); + // Set the struct value (end phase) + void set_end(size_t fbe_begin); + + // Set the struct value + void set(const ::bank_dom::Global& fbe_value) noexcept; + // Set the struct fields values + void set_fields(const ::bank_dom::Global& fbe_value) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; + +public: + FieldModelVector keys; + FieldModelVector<::bank_dom::User> users; +}; + +namespace bank_dom { + +// Fast Binary Encoding Global model +class GlobalModel : public FBE::Model +{ +public: + GlobalModel() : model(this->buffer(), 4) {} + GlobalModel(const std::shared_ptr& buffer) : FBE::Model(buffer), model(this->buffer(), 4) {} + + // Get the model size + size_t fbe_size() const noexcept { return model.fbe_size() + model.fbe_extra(); } + // Get the model type + static constexpr size_t fbe_type() noexcept { return FieldModel<::bank_dom::Global>::fbe_type(); } + + // Check if the struct value is valid + bool verify(); + + // Create a new model (begin phase) + size_t create_begin(); + // Create a new model (end phase) + size_t create_end(size_t fbe_begin); + + // Serialize the struct value + size_t serialize(const ::bank_dom::Global& value); + // Deserialize the struct value + size_t deserialize(::bank_dom::Global& value) const noexcept; + + // Move to the next struct value + void next(size_t prev) noexcept { model.fbe_shift(prev); } + +public: + FieldModel<::bank_dom::Global> model; +}; + +} // namespace bank_dom + +} // namespace FBE diff --git a/fbe/user_model/fbe.cpp b/fbe/user_model/fbe.cpp new file mode 100644 index 0000000..59d516a --- /dev/null +++ b/fbe/user_model/fbe.cpp @@ -0,0 +1,401 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: FBE +// Version: 1.7.0.0 + +#include "fbe.h" + +namespace FBE { + +std::string buffer_t::base64encode() const +{ + const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + std::string result; + + int val = 0; + int valb = -6; + for (auto c : _data) + { + val = (val << 8) + c; + valb += 8; + while (valb >= 0) + { + result.push_back(base64[(val >> valb) & 0x3F]); + valb -= 6; + } + } + + if (valb > -6) + result.push_back(base64[((val << 8) >> (valb + 8)) & 0x3F]); + + while (result.size() % 4) + result.push_back('='); + + return result; +} + +buffer_t buffer_t::base64decode(const std::string& str) +{ + const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + buffer_t result; + + std::vector pattern(256, -1); + for (int i = 0; i < 64; ++i) + pattern[base64[i]] = i; + + int val = 0; + int valb = -8; + for (auto c : str) + { + if (pattern[c] == -1) + break; + + val = (val << 6) + pattern[c]; + valb += 6; + + if (valb >= 0) + { + result.push_back((uint8_t)((val >> valb) & 0xFF)); + valb -= 8; + } + } + + return result; +} + +uint64_t utc() +{ +#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) + struct timespec timestamp; + if (clock_gettime(CLOCK_REALTIME, ×tamp) != 0) + throw std::runtime_error("Cannot get value of CLOCK_REALTIME timer!"); + return (timestamp.tv_sec * 1000000000) + timestamp.tv_nsec; +#elif defined(_WIN32) || defined(_WIN64) + FILETIME ft; + GetSystemTimePreciseAsFileTime(&ft); + + ULARGE_INTEGER result; + result.LowPart = ft.dwLowDateTime; + result.HighPart = ft.dwHighDateTime; + return (result.QuadPart - 116444736000000000ull) * 100; +#endif +} + +uint8_t unhex(char ch) +{ + if ((ch >= '0') && (ch <= '9')) + return ch - '0'; + else if ((ch >= 'a') && (ch <= 'f')) + return 10 + ch - 'a'; + else if ((ch >= 'A') && (ch <= 'F')) + return 10 + ch - 'A'; + else + return 255; +} + +uuid_t::uuid_t(const std::string& uuid) +{ + char v1 = 0; + char v2 = 0; + bool pack = false; + size_t index = 0; + + // Parse UUID string + for (auto ch : uuid) + { + if ((ch == '-') || (ch == '{') || (ch == '}')) + continue; + + if (pack) + { + v2 = ch; + pack = false; + uint8_t ui1 = unhex(v1); + uint8_t ui2 = unhex(v2); + if ((ui1 > 15) || (ui2 > 15)) + throw std::invalid_argument("Invalid UUID string: " + uuid); + _data[index++] = ui1 * 16 + ui2; + if (index >= 16) + break; + } + else + { + v1 = ch; + pack = true; + } + } + + // Fill remaining data with zeros + for (; index < 16; ++index) + _data[index++] = 0; +} + +std::string uuid_t::string() const +{ + const char* digits = "0123456789abcdef"; + + std::string result(36, '0'); + + int index = 0; + for (auto value : _data) + { + result[index++] = digits[(value >> 4) & 0x0F]; + result[index++] = digits[(value >> 0) & 0x0F]; + if ((index == 8) || (index == 13) || (index == 18) || (index == 23)) + result[index++] = '-'; + } + + return result; +} + +uuid_t uuid_t::sequential() +{ + uuid_t result; +#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) + ::uuid_t uuid; + uuid_generate_time(uuid); + result._data[0] = uuid[0]; + result._data[1] = uuid[1]; + result._data[2] = uuid[2]; + result._data[3] = uuid[3]; + result._data[4] = uuid[4]; + result._data[5] = uuid[5]; + result._data[6] = uuid[6]; + result._data[7] = uuid[7]; + result._data[8] = uuid[8]; + result._data[9] = uuid[9]; + result._data[10] = uuid[10]; + result._data[11] = uuid[11]; + result._data[12] = uuid[12]; + result._data[13] = uuid[13]; + result._data[14] = uuid[14]; + result._data[15] = uuid[15]; +#elif defined(_WIN32) || defined(_WIN64) + ::UUID uuid; + if (UuidCreateSequential(&uuid) != RPC_S_OK) + throw std::runtime_error("Cannot generate sequential UUID!"); + + result._data[0] = (uuid.Data1 >> 24) & 0xFF; + result._data[1] = (uuid.Data1 >> 16) & 0xFF; + result._data[2] = (uuid.Data1 >> 8) & 0xFF; + result._data[3] = (uuid.Data1 >> 0) & 0xFF; + result._data[4] = (uuid.Data2 >> 8) & 0xFF; + result._data[5] = (uuid.Data2 >> 0) & 0xFF; + + result._data[6] = (uuid.Data3 >> 8) & 0xFF; + result._data[7] = (uuid.Data3 >> 0) & 0xFF; + + result._data[8] = uuid.Data4[0]; + result._data[9] = uuid.Data4[1]; + + result._data[10] = uuid.Data4[2]; + result._data[11] = uuid.Data4[3]; + result._data[12] = uuid.Data4[4]; + result._data[13] = uuid.Data4[5]; + result._data[14] = uuid.Data4[6]; + result._data[15] = uuid.Data4[7]; +#endif + return result; +} + +uuid_t uuid_t::random() +{ + uuid_t result; +#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) + ::uuid_t uuid; + uuid_generate_random(uuid); + result._data[0] = uuid[0]; + result._data[1] = uuid[1]; + result._data[2] = uuid[2]; + result._data[3] = uuid[3]; + result._data[4] = uuid[4]; + result._data[5] = uuid[5]; + result._data[6] = uuid[6]; + result._data[7] = uuid[7]; + result._data[8] = uuid[8]; + result._data[9] = uuid[9]; + result._data[10] = uuid[10]; + result._data[11] = uuid[11]; + result._data[12] = uuid[12]; + result._data[13] = uuid[13]; + result._data[14] = uuid[14]; + result._data[15] = uuid[15]; +#elif defined(_WIN32) || defined(_WIN64) + ::UUID uuid; + if (UuidCreate(&uuid) != RPC_S_OK) + throw std::runtime_error("Cannot generate random UUID!"); + + result._data[0] = (uuid.Data1 >> 24) & 0xFF; + result._data[1] = (uuid.Data1 >> 16) & 0xFF; + result._data[2] = (uuid.Data1 >> 8) & 0xFF; + result._data[3] = (uuid.Data1 >> 0) & 0xFF; + result._data[4] = (uuid.Data2 >> 8) & 0xFF; + result._data[5] = (uuid.Data2 >> 0) & 0xFF; + + result._data[6] = (uuid.Data3 >> 8) & 0xFF; + result._data[7] = (uuid.Data3 >> 0) & 0xFF; + + result._data[8] = uuid.Data4[0]; + result._data[9] = uuid.Data4[1]; + + result._data[10] = uuid.Data4[2]; + result._data[11] = uuid.Data4[3]; + result._data[12] = uuid.Data4[4]; + result._data[13] = uuid.Data4[5]; + result._data[14] = uuid.Data4[6]; + result._data[15] = uuid.Data4[7]; +#endif + return result; +} + +#if defined(LOGGING_PROTOCOL) +CppLogging::Record& operator<<(CppLogging::Record& record, const uuid_t& uuid) +{ + const char* digits = "0123456789abcdef"; + + std::array result; + + int index = 0; + for (auto value : uuid.data()) + { + result[index++] = digits[(value >> 4) & 0x0F]; + result[index++] = digits[(value >> 0) & 0x0F]; + if ((index == 8) || (index == 13) || (index == 18) || (index == 23)) + result[index++] = '-'; + } + + return record.StoreCustom(std::string_view(result.data(), result.size())); +} +#endif + +void FBEBuffer::attach(const void* data, size_t size, size_t offset) +{ + assert((data != nullptr) && "Invalid buffer!"); + if (data == nullptr) + throw std::invalid_argument("Invalid buffer!"); + assert((size > 0) && "Invalid size!"); + if (size == 0) + throw std::invalid_argument("Invalid size!"); + assert((offset <= size) && "Invalid offset!"); + if (offset > size) + throw std::invalid_argument("Invalid offset!"); + + _data = (uint8_t*)data; + _capacity = 0; + _size = size; + _offset = offset; +} + +void FBEBuffer::attach(const std::vector& buffer, size_t offset) +{ + assert((buffer.data() != nullptr) && "Invalid buffer!"); + if (buffer.data() == nullptr) + throw std::invalid_argument("Invalid buffer!"); + assert((buffer.size() > 0) && "Invalid size!"); + if (buffer.size() == 0) + throw std::invalid_argument("Invalid size!"); + assert((offset <= buffer.size()) && "Invalid offset!"); + if (offset > buffer.size()) + throw std::invalid_argument("Invalid offset!"); + + _data = (uint8_t*)buffer.data(); + _capacity = 0; + _size = buffer.size(); + _offset = offset; +} + +void FBEBuffer::clone(const void* data, size_t size, size_t offset) +{ + assert((offset <= size) && "Invalid offset!"); + if (offset > size) + throw std::invalid_argument("Invalid offset!"); + + reserve(size); + std::memcpy(_data, data, size); + _capacity = size; + _size = size; + _offset = offset; +} + +void FBEBuffer::clone(const std::vector& buffer, size_t offset) +{ + assert((offset <= buffer.size()) && "Invalid offset!"); + if (offset > buffer.size()) + throw std::invalid_argument("Invalid offset!"); + + size_t size = buffer.size(); + + reserve(size); + std::memcpy(_data, buffer.data(), size); + _capacity = size; + _size = size; + _offset = offset; +} + +size_t FBEBuffer::allocate(size_t size) +{ + size_t offset = _size; + + // Calculate a new buffer size + size_t total = _size + size; + + if (total <= _capacity) + { + _size = total; + return offset; + } + + _capacity = std::max(total, 2 * _capacity); + uint8_t* data = (uint8_t*)std::malloc(_capacity); + std::memcpy(data, _data, _size); + std::free(_data); + _data = data; + _size = total; + return offset; +} + +void FBEBuffer::remove(size_t offset, size_t size) +{ + assert(((offset + size) <= _size) && "Invalid offset & size!"); + if ((offset + size) > _size) + throw std::invalid_argument("Invalid offset & size!"); + + std::memcpy(_data + offset, _data + offset + size, _size - size - offset); + _size -= size; + if (_offset >= (offset + size)) + _offset -= size; + else if (_offset >= offset) + { + _offset -= _offset - offset; + if (_offset > _size) + _offset = _size; + } +} + +void FBEBuffer::reserve(size_t capacity) +{ + if (capacity > _capacity) + { + _capacity = std::max(capacity, 2 * _capacity); + uint8_t* data = (uint8_t*)std::malloc(_capacity); + std::memcpy(data, _data, _size); + std::free(_data); + _data = data; + } +} + +void FBEBuffer::resize(size_t size) +{ + reserve(size); + _size = size; + if (_offset > _size) + _offset = _size; +} + +void FBEBuffer::reset() +{ + _size = 0; + _offset = 0; +} + +} // namespace FBE diff --git a/fbe/user_model/fbe.h b/fbe/user_model/fbe.h new file mode 100644 index 0000000..b6d11be --- /dev/null +++ b/fbe/user_model/fbe.h @@ -0,0 +1,650 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: FBE +// Version: 1.7.0.0 + +#pragma once + +#if defined(__clang__) +#pragma clang system_header +#elif defined(__GNUC__) +#pragma GCC system_header +#elif defined(_MSC_VER) +#pragma system_header +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__) +#include +#include +#undef HOST_NOT_FOUND +#elif defined(_WIN32) || defined(_WIN64) +#include +#undef DELETE +#undef ERROR +#undef HOST_NOT_FOUND +#undef Yield +#undef min +#undef max +#undef uuid_t +#endif + +namespace FBE { + +//! Bytes buffer type +/*! + Represents bytes buffer which is a lightweight wrapper around std::vector + with similar interface. +*/ +class buffer_t +{ +public: + typedef std::vector::iterator iterator; + typedef std::vector::const_iterator const_iterator; + typedef std::vector::reverse_iterator reverse_iterator; + typedef std::vector::const_reverse_iterator const_reverse_iterator; + + buffer_t() = default; + buffer_t(size_t capacity) { reserve(capacity); } + buffer_t(const std::string& str) { assign(str); } + buffer_t(size_t size, uint8_t value) { assign(size, value); } + buffer_t(const uint8_t* data, size_t size) { assign(data, size); } + buffer_t(const std::vector& other) : _data(other) {} + buffer_t(std::vector&& other) : _data(std::move(other)) {} + buffer_t(const buffer_t& other) = default; + buffer_t(buffer_t&& other) = default; + ~buffer_t() = default; + + buffer_t& operator=(const std::string& str) { assign(str); return *this; } + buffer_t& operator=(const std::vector& other) { _data = other; return *this; } + buffer_t& operator=(std::vector&& other) { _data = std::move(other); return *this; } + buffer_t& operator=(const buffer_t& other) = default; + buffer_t& operator=(buffer_t&& other) = default; + + uint8_t& operator[](size_t index) { return _data[index]; } + const uint8_t& operator[](size_t index) const { return _data[index]; } + + bool empty() const { return _data.empty(); } + size_t capacity() const { return _data.capacity(); } + size_t size() const { return _data.size(); } + size_t max_size() const { return _data.max_size(); } + + std::vector& buffer() noexcept { return _data; } + const std::vector& buffer() const noexcept { return _data; } + uint8_t* data() noexcept { return _data.data(); } + const uint8_t* data() const noexcept { return _data.data(); } + uint8_t& at(size_t index) { return _data.at(index); } + const uint8_t& at(size_t index) const { return _data.at(index); } + uint8_t& front() { return _data.front(); } + const uint8_t& front() const { return _data.front(); } + uint8_t& back() { return _data.back(); } + const uint8_t& back() const { return _data.back(); } + + void reserve(size_t capacity) { _data.reserve(capacity); } + void resize(size_t size, uint8_t value = 0) { _data.resize(size, value); } + void shrink_to_fit() { _data.shrink_to_fit(); } + + void assign(const std::string& str) { assign((const uint8_t*)str.c_str(), str.size()); } + void assign(const std::vector& vec) { assign(vec.begin(), vec.end()); } + void assign(size_t size, uint8_t value) { _data.assign(size, value); } + void assign(const uint8_t* data, size_t size) { _data.assign(data, data + size); } + template + void assign(InputIterator first, InputIterator last) { _data.assign(first, last); } + iterator insert(const_iterator position, uint8_t value) { return _data.insert(position, value); } + iterator insert(const_iterator position, const std::string& str) { return insert(position, (const uint8_t*)str.c_str(), str.size()); } + iterator insert(const_iterator position, const std::vector& vec) { return insert(position, vec.begin(), vec.end()); } + iterator insert(const_iterator position, size_t size, uint8_t value) { return _data.insert(position, size, value); } + iterator insert(const_iterator position, const uint8_t* data, size_t size) { return _data.insert(position, data, data + size); } + template + iterator insert(const_iterator position, InputIterator first, InputIterator last) { return _data.insert(position, first, last); } + iterator erase(const_iterator position) { return _data.erase(position); } + iterator erase(const_iterator first, const_iterator last) { return _data.erase(first, last); } + void clear() noexcept { _data.clear(); } + + void push_back(uint8_t value) { _data.push_back(value); } + void pop_back() { _data.pop_back(); } + + template + iterator emplace(const_iterator position, Args&&... args) { return _data.emplace(position, args...); } + template + void emplace_back(Args&&... args) { _data.emplace_back(args...); } + + iterator begin() noexcept { return _data.begin(); } + const_iterator begin() const noexcept { return _data.begin(); } + const_iterator cbegin() const noexcept { return _data.cbegin(); } + reverse_iterator rbegin() noexcept { return _data.rbegin(); } + const_reverse_iterator rbegin() const noexcept { return _data.rbegin(); } + const_reverse_iterator crbegin() const noexcept { return _data.crbegin(); } + iterator end() noexcept { return _data.end(); } + const_iterator end() const noexcept { return _data.end(); } + const_iterator cend() const noexcept { return _data.cend(); } + reverse_iterator rend() noexcept { return _data.rend(); } + const_reverse_iterator rend() const noexcept { return _data.rend(); } + const_reverse_iterator crend() const noexcept { return _data.crend(); } + + //! Get the string equivalent from the bytes buffer + std::string string() const { return std::string(_data.begin(), _data.end()); } + + //! Encode the Base64 string from the bytes buffer + std::string base64encode() const; + //! Decode the bytes buffer from the Base64 string + static buffer_t base64decode(const std::string& str); + + //! Swap two instances + void swap(buffer_t& value) noexcept + { using std::swap; swap(_data, value._data); } + friend void swap(buffer_t& value1, buffer_t& value2) noexcept + { value1.swap(value2); } + +private: + std::vector _data; +}; + +//! Decimal type +/*! + Represents decimal type using double and provides basic arithmetic operations. +*/ +class decimal_t +{ +public: + decimal_t() noexcept { _value = 0.0; } + decimal_t(int8_t value) noexcept { _value = (double)value; } + decimal_t(uint8_t value) noexcept { _value = (double)value; } + decimal_t(int16_t value) noexcept { _value = (double)value; } + decimal_t(uint16_t value) noexcept { _value = (double)value; } + decimal_t(int32_t value) noexcept { _value = (double)value; } + decimal_t(uint32_t value) noexcept { _value = (double)value; } + decimal_t(int64_t value) noexcept { _value = (double)value; } + decimal_t(uint64_t value) noexcept { _value = (double)value; } + decimal_t(float value) noexcept { _value = (double)value; } + decimal_t(double value) noexcept { _value = value; } + template + explicit decimal_t(const T& value) noexcept { _value = (double)value; } + decimal_t(const decimal_t& value) noexcept = default; + decimal_t(decimal_t&& value) noexcept = default; + ~decimal_t() noexcept = default; + + template + decimal_t& operator=(const T& value) noexcept { _value = (double)value; return *this; } + decimal_t& operator=(const decimal_t& value) noexcept = default; + decimal_t& operator=(decimal_t&& value) noexcept = default; + + // Arithmetic operators + decimal_t operator+() const noexcept { return decimal_t(_value); } + decimal_t operator-() const noexcept { return decimal_t(-_value); } + + decimal_t& operator++() noexcept { return *this += 1; } + decimal_t operator++(int) noexcept { decimal_t temp(*this); ++*this; return temp; } + decimal_t& operator--() noexcept { return *this -= 1; } + decimal_t operator--(int) noexcept { decimal_t temp(*this); --*this; return temp; } + + decimal_t& operator+=(const decimal_t& value) noexcept { return *this = *this + value; } + decimal_t& operator-=(const decimal_t& value) noexcept { return *this = *this - value; } + decimal_t& operator*=(const decimal_t& value) noexcept { return *this = *this * value; } + decimal_t& operator/=(const decimal_t& value) { return *this = *this / value; } + + template + decimal_t& operator+=(const T& value) noexcept { return *this = *this + decimal_t(value); } + template + decimal_t& operator-=(const T& value) noexcept { return *this = *this - decimal_t(value); } + template + decimal_t& operator*=(const T& value) noexcept { return *this = *this * decimal_t(value); } + template + decimal_t& operator/=(const T& value) { return *this = *this / decimal_t(value); } + + template + friend T& operator+=(T& value1, const decimal_t& value2) noexcept { return value1 = (T)(decimal_t(value1) + value2); } + template + friend T& operator-=(T& value1, const decimal_t& value2) noexcept { return value1 = (T)(decimal_t(value1) - value2); } + template + friend T& operator*=(T& value1, const decimal_t& value2) noexcept { return value1 = (T)(decimal_t(value1) * value2); } + template + friend T& operator/=(T& value1, const decimal_t& value2) { return value1 = (T)(decimal_t(value1) / value2); } + + template + friend decimal_t operator+(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) + value2; } + template + friend decimal_t operator+(const decimal_t& value1, const T& value2) noexcept { return value1 + decimal_t(value2); } + friend decimal_t operator+(const decimal_t& value1, const decimal_t& value2) noexcept { return decimal_t(value1._value + value2._value); } + + template + friend decimal_t operator-(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) - value2; } + template + friend decimal_t operator-(const decimal_t& value1, const T& value2) noexcept { return value1 - decimal_t(value2); } + friend decimal_t operator-(const decimal_t& value1, const decimal_t& value2) noexcept { return decimal_t(value1._value - value2._value); } + + template + friend decimal_t operator*(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) * value2; } + template + friend decimal_t operator*(const decimal_t& value1, const T& value2) noexcept { return value1 * decimal_t(value2); } + friend decimal_t operator*(const decimal_t& value1, const decimal_t& value2) noexcept { return decimal_t(value1._value * value2._value); } + + template + friend decimal_t operator/(const T& value1, const decimal_t& value2) { return decimal_t(value1) / value2; } + template + friend decimal_t operator/(const decimal_t& value1, const T& value2) { return value1 / decimal_t(value2); } + friend decimal_t operator/(const decimal_t& value1, const decimal_t& value2) { return decimal_t(value1._value / value2._value); } + + // Comparison operators + template + friend bool operator==(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) == value2; } + template + friend bool operator==(const decimal_t& value1, const T& value2) noexcept { return value1 == decimal_t(value2); } + friend bool operator==(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value == value2._value; } + + template + friend bool operator!=(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) != value2; } + template + friend bool operator!=(const decimal_t& value1, const T& value2) noexcept { return value1 != decimal_t(value2); } + friend bool operator!=(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value != value2._value; } + + template + friend bool operator<(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) < value2; } + template + friend bool operator<(const decimal_t& value1, const T& value2) noexcept { return value1 < decimal_t(value2); } + friend bool operator<(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value < value2._value; } + + template + friend bool operator>(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) > value2; } + template + friend bool operator>(const decimal_t& value1, const T& value2) noexcept { return value1 > decimal_t(value2); } + friend bool operator>(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value > value2._value; } + + template + friend bool operator<=(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) <= value2; } + template + friend bool operator<=(const decimal_t& value1, const T& value2) noexcept { return value1 <= decimal_t(value2); } + friend bool operator<=(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value <= value2._value; } + + template + friend bool operator>=(const T& value1, const decimal_t& value2) noexcept { return decimal_t(value1) >= value2; } + template + friend bool operator>=(const decimal_t& value1, const T& value2) noexcept { return value1 >= decimal_t(value2); } + friend bool operator>=(const decimal_t& value1, const decimal_t& value2) noexcept { return value1._value >= value2._value; } + + // Type cast + operator bool() const noexcept { return (_value != 0.0); } + operator uint8_t() const noexcept { return (uint8_t)_value; } + operator uint16_t() const noexcept { return (uint16_t)_value; } + operator uint32_t() const noexcept { return (uint32_t)_value; } + operator uint64_t() const noexcept { return (uint64_t)_value; } + operator float() const noexcept { return (float)_value; } + operator double() const noexcept { return (double)_value; } + + //! Get string from the current decimal value + std::string string() const { return std::to_string(_value); } + + //! Input instance from the given input stream + friend std::istream& operator>>(std::istream& is, decimal_t& value) + { is >> value._value; return is; } + //! Output instance into the given output stream + friend std::ostream& operator<<(std::ostream& os, const decimal_t& value) + { os << value.string(); return os; } + +#if defined(LOGGING_PROTOCOL) + //! Store logging format + friend CppLogging::Record& operator<<(CppLogging::Record& record, const decimal_t& value) + { return record.StoreCustom(value._value); } +#endif + + //! Swap two instances + void swap(decimal_t& value) noexcept + { using std::swap; swap(_value, value._value); } + friend void swap(decimal_t& value1, decimal_t& value2) noexcept + { value1.swap(value2); } + +private: + double _value; +}; + +} // namespace FBE + +namespace std { + +template <> +struct hash +{ + typedef FBE::decimal_t argument_type; + typedef size_t result_type; + + result_type operator() (const argument_type& value) const + { + result_type result = 17; + result = result * 31 + std::hash()((double)value); + return result; + } +}; + +} // namespace std + +namespace FBE { + +// Register a new enum-based flags macro +#define FBE_ENUM_FLAGS(type)\ +inline FBE::Flags operator|(type f1, type f2) noexcept { return FBE::Flags(f1) | FBE::Flags(f2); }\ +inline FBE::Flags operator&(type f1, type f2) noexcept { return FBE::Flags(f1) & FBE::Flags(f2); }\ +inline FBE::Flags operator^(type f1, type f2) noexcept { return FBE::Flags(f1) ^ FBE::Flags(f2); } + +// Enum-based flags +template +class Flags +{ + // Enum underlying type + typedef typename std::make_unsigned::type>::type type; + +public: + Flags() noexcept : _value(0) {} + explicit Flags(type value) noexcept : _value(value) {} + explicit Flags(TEnum value) noexcept : _value((type)value) {} + Flags(const Flags&) noexcept = default; + Flags(Flags&&) noexcept = default; + ~Flags() noexcept = default; + + Flags& operator=(type value) noexcept + { _value = value; return *this; } + Flags& operator=(TEnum value) noexcept + { _value = (type)value; return *this; } + Flags& operator=(const Flags&) noexcept = default; + Flags& operator=(Flags&&) noexcept = default; + + // Is any flag set? + explicit operator bool() const noexcept { return isset(); } + + // Is no flag set? + bool operator!() const noexcept { return !isset(); } + + // Reverse all flags + Flags operator~() const noexcept { return Flags(~_value); } + + // Flags logical assign operators + Flags& operator&=(const Flags& flags) noexcept + { _value &= flags._value; return *this; } + Flags& operator|=(const Flags& flags) noexcept + { _value |= flags._value; return *this; } + Flags& operator^=(const Flags& flags) noexcept + { _value ^= flags._value; return *this; } + + // Flags logical friend operators + friend Flags operator&(const Flags& flags1, const Flags& flags2) noexcept + { return Flags(flags1._value & flags2._value); } + friend Flags operator|(const Flags& flags1, const Flags& flags2) noexcept + { return Flags(flags1._value | flags2._value); } + friend Flags operator^(const Flags& flags1, const Flags& flags2) noexcept + { return Flags(flags1._value ^ flags2._value); } + + // Flags comparison + friend bool operator==(const Flags& flags1, const Flags& flags2) noexcept + { return flags1._value == flags2._value; } + friend bool operator!=(const Flags& flags1, const Flags& flags2) noexcept + { return flags1._value != flags2._value; } + + // Convert to the enum value + operator TEnum() const noexcept { return (TEnum)_value; } + + //! Is any flag set? + bool isset() const noexcept { return (_value != 0); } + //! Is the given flag set? + bool isset(type value) const noexcept { return (_value & value) != 0; } + //! Is the given flag set? + bool isset(TEnum value) const noexcept { return (_value & (type)value) != 0; } + + // Get the enum value + TEnum value() const noexcept { return (TEnum)_value; } + // Get the underlying enum value + type underlying() const noexcept { return _value; } + // Get the bitset value + std::bitset bitset() const noexcept { return {_value}; } + + // Swap two instances + void swap(Flags& flags) noexcept { using std::swap; swap(_value, flags._value); } + template + friend void swap(Flags& flags1, Flags& flags2) noexcept; + +private: + type _value; +}; + +template +inline void swap(Flags& flags1, Flags& flags2) noexcept +{ + flags1.swap(flags2); +} + +// Get Epoch timestamp +inline uint64_t epoch() { return 0ull; } +// Get UTC timestamp +uint64_t utc(); + +//! Universally unique identifier (UUID) +/*! + A universally unique identifier (UUID) is an identifier standard used + in software construction. This implementation generates the following + UUID types: + - Nil UUID0 (all bits set to zero) + - Sequential UUID1 (time based version) + - Random UUID4 (randomly or pseudo-randomly generated version) + + A UUID is simply a 128-bit value: "123e4567-e89b-12d3-a456-426655440000" + + https://en.wikipedia.org/wiki/Universally_unique_identifier + https://www.ietf.org/rfc/rfc4122.txt +*/ +class uuid_t +{ +public: + //! Default constructor + uuid_t() : _data() { _data.fill(0); } + //! Initialize UUID with a given string + /*! + \param uuid - UUID string + */ + explicit uuid_t(const std::string& uuid); + //! Initialize UUID with a given 16 bytes data buffer + /*! + \param data - UUID 16 bytes data buffer + */ + explicit uuid_t(const std::array& data) : _data(data) {} + uuid_t(const uuid_t&) = default; + uuid_t(uuid_t&&) noexcept = default; + ~uuid_t() = default; + + uuid_t& operator=(const std::string& uuid) + { _data = uuid_t(uuid).data(); return *this; } + uuid_t& operator=(const std::array& data) + { _data = data; return *this; } + uuid_t& operator=(const uuid_t&) = default; + uuid_t& operator=(uuid_t&&) noexcept = default; + + // UUID comparison + friend bool operator==(const uuid_t& uuid1, const uuid_t& uuid2) + { return uuid1._data == uuid2._data; } + friend bool operator!=(const uuid_t& uuid1, const uuid_t& uuid2) + { return uuid1._data != uuid2._data; } + friend bool operator<(const uuid_t& uuid1, const uuid_t& uuid2) + { return uuid1._data < uuid2._data; } + friend bool operator>(const uuid_t& uuid1, const uuid_t& uuid2) + { return uuid1._data > uuid2._data; } + friend bool operator<=(const uuid_t& uuid1, const uuid_t& uuid2) + { return uuid1._data <= uuid2._data; } + friend bool operator>=(const uuid_t& uuid1, const uuid_t& uuid2) + { return uuid1._data >= uuid2._data; } + + //! Check if the UUID is nil UUID0 (all bits set to zero) + explicit operator bool() const noexcept { return *this != nil(); } + + //! Get the UUID data buffer + std::array& data() noexcept { return _data; } + //! Get the UUID data buffer + const std::array& data() const noexcept { return _data; } + + //! Get string from the current UUID in format "00000000-0000-0000-0000-000000000000" + std::string string() const; + + //! Generate nil UUID0 (all bits set to zero) + static uuid_t nil() { return uuid_t(); } + //! Generate sequential UUID1 (time based version) + static uuid_t sequential(); + //! Generate random UUID4 (randomly or pseudo-randomly generated version) + static uuid_t random(); + + //! Output instance into the given output stream + friend std::ostream& operator<<(std::ostream& os, const uuid_t& uuid) + { os << uuid.string(); return os; } + +#if defined(LOGGING_PROTOCOL) + //! Store logging format + friend CppLogging::Record& operator<<(CppLogging::Record& record, const uuid_t& uuid); +#endif + + //! Swap two instances + void swap(uuid_t& uuid) noexcept + { using std::swap; swap(_data, uuid._data); } + friend void swap(uuid_t& uuid1, uuid_t& uuid2) noexcept + { uuid1.swap(uuid2); } + +private: + std::array _data; +}; + +} // namespace FBE + +namespace std { + +template <> +struct hash +{ + typedef FBE::uuid_t argument_type; + typedef size_t result_type; + + result_type operator() (const argument_type& value) const + { + result_type result = 17; + std::hash hasher; + for (size_t i = 0; i < value.data().size(); ++i) + result = result * 31 + hasher(value.data()[i]); + return result; + } +}; + +} // namespace std + +namespace FBE { + +// Fast Binary Encoding buffer based on the dynamic byte buffer +class FBEBuffer +{ +public: + FBEBuffer() : _data(nullptr), _capacity(0), _size(0), _offset(0) {} + // Initialize the read buffer with the given byte buffer and offset + explicit FBEBuffer(const void* data, size_t size, size_t offset = 0) { attach(data, size, offset); } + // Initialize the read buffer with the given byte vector and offset + explicit FBEBuffer(const std::vector& buffer, size_t offset = 0) { attach(buffer, offset); } + // Initialize the read buffer with another buffer and offset + explicit FBEBuffer(const FBEBuffer& buffer, size_t offset = 0) { attach(buffer.data(), buffer.size(), offset); } + // Initialize the write buffer with the given capacity + explicit FBEBuffer(size_t capacity) : FBEBuffer() { reserve(capacity); } + FBEBuffer(const FBEBuffer&) = delete; + FBEBuffer(FBEBuffer&&) noexcept = delete; + ~FBEBuffer() { if (_capacity > 0) std::free(_data); } + + FBEBuffer& operator=(const FBEBuffer&) = delete; + FBEBuffer& operator=(FBEBuffer&&) noexcept = delete; + + bool empty() const noexcept { return (_data == nullptr) || (_size == 0); } + const uint8_t* data() const noexcept { return _data; } + uint8_t* data() noexcept { return _data; } + size_t capacity() const noexcept { return _capacity; } + size_t size() const noexcept { return _size; } + size_t offset() const noexcept { return _offset; } + + // Attach the given buffer with a given offset to the current read buffer + void attach(const void* data, size_t size, size_t offset = 0); + // Attach the given byte vector with a given offset to the current read buffer + void attach(const std::vector& buffer, size_t offset = 0); + + // Clone the given buffer with a given offset to the current buffer + void clone(const void* data, size_t size, size_t offset = 0); + // Clone the given vector with a given offset to the current buffer + void clone(const std::vector& buffer, size_t offset = 0); + + // Allocate memory in the current write buffer and return offset to the allocated memory block + size_t allocate(size_t size); + // Remove some memory of the given size from the current write buffer + void remove(size_t offset, size_t size); + // Reserve memory of the given capacity in the current write buffer + void reserve(size_t capacity); + // Resize the current write buffer + void resize(size_t size); + // Reset the current write buffer and its offset + void reset(); + + // Shift the current write buffer offset + void shift(size_t offset) { _offset += offset; } + // Unshift the current write buffer offset + void unshift(size_t offset) { _offset -= offset; } + +private: + uint8_t* _data; + size_t _capacity; + size_t _size; + size_t _offset; +}; + +// Fast Binary Encoding base model +class Model +{ +public: + Model() : Model(nullptr) {} + Model(const std::shared_ptr& buffer) { _buffer = buffer ? buffer : std::make_shared(); } + Model(const Model&) = default; + Model(Model&&) noexcept = default; + ~Model() = default; + + Model& operator=(const Model&) = default; + Model& operator=(Model&&) noexcept = default; + + // Get the model buffer + FBEBuffer& buffer() noexcept { return *_buffer; } + const FBEBuffer& buffer() const noexcept { return *_buffer; } + + // Attach the model buffer + void attach(const void* data, size_t size, size_t offset = 0) { _buffer->attach(data, size, offset); } + void attach(const std::vector& buffer, size_t offset = 0) { _buffer->attach(buffer, offset); } + void attach(const FBEBuffer& buffer, size_t offset = 0) { _buffer->attach(buffer.data(), buffer.size(), offset); } + + // Model buffer operations + size_t allocate(size_t size) { return _buffer->allocate(size); } + void remove(size_t offset, size_t size) { _buffer->remove(offset, size); } + void reserve(size_t capacity) { _buffer->reserve(capacity); } + void resize(size_t size) { _buffer->resize(size); } + void reset() { _buffer->reset(); } + void shift(size_t offset) { _buffer->shift(offset); } + void unshift(size_t offset) { _buffer->unshift(offset); } + +private: + std::shared_ptr _buffer; +}; + +} // namespace FBE diff --git a/fbe/user_model/fbe_final_models.cpp b/fbe/user_model/fbe_final_models.cpp new file mode 100644 index 0000000..27902f8 --- /dev/null +++ b/fbe/user_model/fbe_final_models.cpp @@ -0,0 +1,436 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: FBE +// Version: 1.7.0.0 + +#include "fbe_final_models.h" + +namespace FBE { + +uint64_t FinalModel::extract(double a) noexcept +{ + uint64_t result; + std::memcpy(&result, &a, sizeof(double)); + return result; +} + +uint64_t FinalModel::uint32x32(uint32_t a, uint32_t b) noexcept +{ + return (uint64_t)a * (uint64_t)b; +} + +void FinalModel::uint64x64(uint64_t a, uint64_t b, uint64_t& low64, uint32_t& high32) noexcept +{ + uint64_t low = uint32x32((uint32_t)a, (uint32_t)b); + uint64_t mid = uint32x32((uint32_t)a, (uint32_t)(b >> 32)); + uint64_t high = uint32x32((uint32_t)(a >> 32), (uint32_t)(b >> 32)); + high += (mid >> 32); + low += (mid <<= 32); + // Test for carry + if (low < mid) + high++; + + mid = uint32x32((uint32_t)(a >> 32), (uint32_t)b); + high += (mid >> 32); + low += (mid <<= 32); + // Test for carry + if (low < mid) + high++; + + if (high > 0xFFFFFFFFu) + { + low64 = 0; + high32 = 0; + } + low64 = low; + high32 = (uint32_t)high; +} + +size_t FinalModel::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return std::numeric_limits::max(); + + return fbe_size(); +} + +size_t FinalModel::get(decimal_t& value) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + // Value taken via reverse engineering the double that corresponds to 2^64 + const double ds2to64 = 1.8446744073709552e+019; + + // Read decimal parts + uint64_t low = *((const uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + uint32_t high = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)); + uint32_t flags = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 12)); + + // Calculate decimal value + double dValue = ((double)low + (double)high * ds2to64) / pow(10.0, (uint8_t)(flags >> 16)); + if (flags & 0x80000000) + dValue = -dValue; + + value = dValue; + return fbe_size(); +} + +size_t FinalModel::set(decimal_t value) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + // The most we can scale by is 10^28, which is just slightly more + // than 2^93. So a float with an exponent of -94 could just + // barely reach 0.5, but smaller exponents will always round to zero. + const uint32_t DBLBIAS = 1022; + + // Get exponent value + double dValue = (double)value; + int32_t iExp = (int32_t)(((uint32_t)(extract(dValue) >> 52) & 0x7FFu) - DBLBIAS); + if ((iExp < -94) || (iExp > 96)) + { + // Value too big for .NET Decimal (exponent is limited to [-94, 96]) + memset((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), 0, 16); + return fbe_size(); + } + + uint32_t flags = 0; + if (dValue < 0) + { + dValue = -dValue; + flags = 0x80000000; + } + + // Round the input to a 15-digit integer. The R8 format has + // only 15 digits of precision, and we want to keep garbage digits + // out of the Decimal were making. + + // Calculate max power of 10 input value could have by multiplying + // the exponent by log10(2). Using scaled integer multiplcation, + // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3. + int32_t iPower = 14 - ((iExp * 19728) >> 16); + + // iPower is between -14 and 43 + if (iPower >= 0) + { + // We have less than 15 digits, scale input up. + if (iPower > 28) + iPower = 28; + + dValue *= pow(10.0, iPower); + } + else + { + if ((iPower != -1) || (dValue >= 1E15)) + dValue /= pow(10.0, -iPower); + else + iPower = 0; // didn't scale it + } + + assert(dValue < 1E15); + if ((dValue < 1E14) && (iPower < 28)) + { + dValue *= 10; + iPower++; + assert(dValue >= 1E14); + } + + // Round to int64 + uint64_t ulMant; + ulMant = (uint64_t)(int64_t)dValue; + dValue -= (int64_t)ulMant; // difference between input & integer + if ((dValue > 0.5) || ((dValue == 0.5) && ((ulMant & 1) != 0))) + ulMant++; + + if (ulMant == 0) + { + // Mantissa is 0 + memset((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), 0, 16); + return fbe_size(); + } + + if (iPower < 0) + { + // Add -iPower factors of 10, -iPower <= (29 - 15) = 14 + iPower = -iPower; + if (iPower < 10) + { + double pow10 = (double)powl(10.0, iPower); + uint64_t low64 = uint32x32((uint32_t)ulMant, (uint32_t)pow10); + uint64_t high64 = uint32x32((uint32_t)(ulMant >> 32), (uint32_t)pow10); + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)low64; + high64 += low64 >> 32; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4)) = (uint32_t)high64; + high64 >>= 32; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = (uint32_t)high64; + } + else + { + // Have a big power of 10. + assert(iPower <= 14); + uint64_t low64; + uint32_t high32; + uint64x64(ulMant, (uint64_t)pow(10.0, iPower), low64, high32); + *((uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = low64; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = high32; + } + } + else + { + // Factor out powers of 10 to reduce the scale, if possible. + // The maximum number we could factor out would be 14. This + // comes from the fact we have a 15-digit number, and the + // MSD must be non-zero -- but the lower 14 digits could be + // zero. Note also the scale factor is never negative, so + // we can't scale by any more than the power we used to + // get the integer. + int lmax = iPower; + if (lmax > 14) + lmax = 14; + + if ((((uint8_t)ulMant) == 0) && (lmax >= 8)) + { + const uint32_t den = 100000000; + uint64_t div = ulMant / den; + if ((uint32_t)ulMant == (uint32_t)(div * den)) + { + ulMant = div; + iPower -= 8; + lmax -= 8; + } + } + + if ((((uint32_t)ulMant & 0xF) == 0) && (lmax >= 4)) + { + const uint32_t den = 10000; + uint64_t div = ulMant / den; + if ((uint32_t)ulMant == (uint32_t)(div * den)) + { + ulMant = div; + iPower -= 4; + lmax -= 4; + } + } + + if ((((uint32_t)ulMant & 3) == 0) && (lmax >= 2)) + { + const uint32_t den = 100; + uint64_t div = ulMant / den; + if ((uint32_t)ulMant == (uint32_t)(div * den)) + { + ulMant = div; + iPower -= 2; + lmax -= 2; + } + } + + if ((((uint32_t)ulMant & 1) == 0) && (lmax >= 1)) + { + const uint32_t den = 10; + uint64_t div = ulMant / den; + if ((uint32_t)ulMant == (uint32_t)(div * den)) + { + ulMant = div; + iPower--; + } + } + + flags |= (uint32_t)iPower << 16; + + *((uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = ulMant; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = 0; + } + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 12)) = flags; + return fbe_size(); +} + +size_t FinalModel::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return std::numeric_limits::max(); + + return fbe_size(); +} + +size_t FinalModel::get(uuid_t& value) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + std::memcpy(value.data().data(), (const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), fbe_size()); + return fbe_size(); +} + +size_t FinalModel::set(uuid_t value) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + std::memcpy((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), value.data().data(), fbe_size()); + return fbe_size(); +} + +size_t FinalModel::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return std::numeric_limits::max(); + + uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) > _buffer.size()) + return std::numeric_limits::max(); + + return 4 + fbe_bytes_size; +} + +size_t FinalModel::get(void* data, size_t size) const noexcept +{ + assert(((size == 0) || (data != nullptr)) && "Invalid buffer!"); + if ((size > 0) && (data == nullptr)) + return 0; + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) > _buffer.size()) + return 4; + + size_t result = std::min(size, (size_t)fbe_bytes_size); + memcpy(data, (const char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), result); + return 4 + fbe_bytes_size; +} + +size_t FinalModel::get(std::vector& value) const noexcept +{ + value.clear(); + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) > _buffer.size()) + return 4; + + const char* fbe_bytes = (const char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4); + value.assign(fbe_bytes, fbe_bytes + fbe_bytes_size); + return 4 + fbe_bytes_size; +} + +size_t FinalModel::set(const void* data, size_t size) +{ + assert(((size == 0) || (data != nullptr)) && "Invalid buffer!"); + if ((size > 0) && (data == nullptr)) + return 0; + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + uint32_t fbe_bytes_size = (uint32_t)size; + assert(((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4 + fbe_bytes_size) > _buffer.size()) + return 4; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_bytes_size; + + memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), data, fbe_bytes_size); + return 4 + fbe_bytes_size; +} + +size_t FinalModel::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return std::numeric_limits::max(); + + uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size()) + return std::numeric_limits::max(); + + return 4 + fbe_string_size; +} + +size_t FinalModel::get(char* data, size_t size) const noexcept +{ + assert(((size == 0) || (data != nullptr)) && "Invalid buffer!"); + if ((size > 0) && (data == nullptr)) + return 0; + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size()) + return 4; + + size_t result = std::min(size, (size_t)fbe_string_size); + memcpy(data, (const char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), result); + return 4 + fbe_string_size; +} + +size_t FinalModel::get(std::string& value) const noexcept +{ + value.clear(); + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size()) + return 4; + + value.assign((const char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), fbe_string_size); + return 4 + fbe_string_size; +} + +size_t FinalModel::set(const char* data, size_t size) +{ + assert(((size == 0) || (data != nullptr)) && "Invalid buffer!"); + if ((size > 0) && (data == nullptr)) + return 0; + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + uint32_t fbe_string_size = (uint32_t)size; + assert(((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size()) + return 4; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_string_size; + + memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), data, fbe_string_size); + return 4 + fbe_string_size; +} + +size_t FinalModel::set(const std::string& value) +{ + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + uint32_t fbe_string_size = (uint32_t)value.size(); + assert(((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4 + fbe_string_size) > _buffer.size()) + return 4; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_string_size; + + memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4), value.data(), fbe_string_size); + return 4 + fbe_string_size; +} + +} // namespace FBE diff --git a/fbe/user_model/fbe_final_models.h b/fbe/user_model/fbe_final_models.h new file mode 100644 index 0000000..f032be0 --- /dev/null +++ b/fbe/user_model/fbe_final_models.h @@ -0,0 +1,457 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: FBE +// Version: 1.7.0.0 + +#pragma once + +#if defined(__clang__) +#pragma clang system_header +#elif defined(__GNUC__) +#pragma GCC system_header +#elif defined(_MSC_VER) +#pragma system_header +#endif + +#include "fbe.h" + +namespace FBE { + +// Fast Binary Encoding base final model +template +class FinalModelBase +{ +public: + FinalModelBase(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the allocation size + size_t fbe_allocation_size(T value) const noexcept { return fbe_size(); } + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the field offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + + // Get the final size + size_t fbe_size() const noexcept { return sizeof(TBase); } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the value is valid + size_t verify() const noexcept; + + // Get the field value + size_t get(T& value) const noexcept; + // Set the field value + size_t set(T value) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; +}; + +// Fast Binary Encoding final model +template +class FinalModel : public FinalModelBase +{ +public: + using FinalModelBase::FinalModelBase; +}; + +// Fast Binary Encoding final model bool specialization +template <> +class FinalModel : public FinalModelBase +{ +public: + using FinalModelBase::FinalModelBase; +}; + +// Fast Binary Encoding final model char specialization +template <> +class FinalModel : public FinalModelBase +{ +public: + using FinalModelBase::FinalModelBase; +}; + +// Fast Binary Encoding final model wchar specialization +template <> +class FinalModel : public FinalModelBase +{ +public: + using FinalModelBase::FinalModelBase; +}; + +// Fast Binary Encoding final model decimal specialization +template <> +class FinalModel +{ +public: + FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the allocation size + size_t fbe_allocation_size(decimal_t value) const noexcept { return fbe_size(); } + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the field offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + + // Get the final size + size_t fbe_size() const noexcept { return 16; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the decimal value is valid + size_t verify() const noexcept; + + // Get the decimal value + size_t get(decimal_t& value) const noexcept; + // Set the decimal value + size_t set(decimal_t value) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; + + static uint64_t extract(double a) noexcept; + static uint64_t uint32x32(uint32_t a, uint32_t b) noexcept; + static void uint64x64(uint64_t a, uint64_t b, uint64_t& low64, uint32_t& high32) noexcept; +}; + +// Fast Binary Encoding final model UUID specialization +template <> +class FinalModel +{ +public: + FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the allocation size + size_t fbe_allocation_size(uuid_t value) const noexcept { return fbe_size(); } + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the field offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + + // Get the final size + size_t fbe_size() const noexcept { return 16; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the UUID value is valid + size_t verify() const noexcept; + + // Get the UUID value + size_t get(uuid_t& value) const noexcept; + // Set the UUID value + size_t set(uuid_t value) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; +}; + +// Fast Binary Encoding final model bytes specialization +template <> +class FinalModel +{ +public: + FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the allocation size + size_t fbe_allocation_size(const void* data, size_t size) const noexcept { return 4 + size; } + template + size_t fbe_allocation_size(const uint8_t (&data)[N]) const noexcept { return 4 + N; } + template + size_t fbe_allocation_size(const std::array& data) const noexcept { return 4 + N; } + size_t fbe_allocation_size(const std::vector& value) const noexcept { return 4 + value.size(); } + size_t fbe_allocation_size(const buffer_t& value) const noexcept { return 4 + value.size(); } + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the field offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the bytes value is valid + size_t verify() const noexcept; + + // Get the bytes value + size_t get(void* data, size_t size) const noexcept; + // Get the bytes value + template + size_t get(uint8_t (&data)[N]) const noexcept { return get(data, N); } + // Get the bytes value + template + size_t get(std::array& data) const noexcept { return get(data.data(), data.size()); } + // Get the bytes value + size_t get(std::vector& value) const noexcept; + // Get the bytes value + size_t get(buffer_t& value) const noexcept { return get(value.buffer()); } + + // Set the bytes value + size_t set(const void* data, size_t size); + // Set the bytes value + template + size_t set(const uint8_t (&data)[N]) { return set(data, N); } + // Set the bytes value + template + size_t set(const std::array& data) { return set(data.data(), data.size()); } + // Set the bytes value + size_t set(const std::vector& value) { return set(value.data(), value.size()); } + // Set the bytes value + size_t set(const buffer_t& value) { return set(value.buffer()); } + +private: + FBEBuffer& _buffer; + mutable size_t _offset; +}; + +// Fast Binary Encoding final model string specialization +template <> +class FinalModel +{ +public: + FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the allocation size + size_t fbe_allocation_size(const char* data, size_t size) const noexcept { return 4 + size; } + template + size_t fbe_allocation_size(const char (&data)[N]) const noexcept { return 4 + N; } + template + size_t fbe_allocation_size(const std::array& data) const noexcept { return 4 + N; } + size_t fbe_allocation_size(const std::string& value) const noexcept { return 4 + value.size(); } + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the field offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the string value is valid + size_t verify() const noexcept; + + // Get the string value + size_t get(char* data, size_t size) const noexcept; + // Get the string value + template + size_t get(char (&data)[N]) const noexcept { return get(data, N); } + // Get the string value + template + size_t get(std::array& data) const noexcept { return get(data.data(), data.size()); } + // Get the string value + size_t get(std::string& value) const noexcept; + + // Set the string value + size_t set(const char* data, size_t size); + // Set the string value + template + size_t set(const char (&data)[N]) { return set(data, N); } + // Set the string value + template + size_t set(const std::array& data) { return set(data.data(), data.size()); } + // Set the string value + size_t set(const std::string& value); + +private: + FBEBuffer& _buffer; + mutable size_t _offset; +}; + +// Fast Binary Encoding final model optional specialization +template +class FinalModel> +{ +public: + FinalModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset), value(buffer, 0) {} + + // Get the allocation size + size_t fbe_allocation_size(const std::optional& opt) const noexcept { return 1 + (opt ? value.fbe_allocation_size(opt.value()) : 0); } + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the field offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + //! Is the value present? + explicit operator bool() const noexcept { return has_value(); } + + // Checks if the object contains a value + bool has_value() const noexcept; + + // Check if the optional value is valid + size_t verify() const noexcept; + + // Get the optional value + size_t get(std::optional& opt) const noexcept; + // Set the optional value + size_t set(const std::optional& opt); + +private: + FBEBuffer& _buffer; + mutable size_t _offset; + +public: + // Base final model value + FinalModel value; +}; + +// Fast Binary Encoding final model array +template +class FinalModelArray +{ +public: + FinalModelArray(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the allocation size + template + size_t fbe_allocation_size(const T (&values)[S]) const noexcept; + template + size_t fbe_allocation_size(const std::array& values) const noexcept; + size_t fbe_allocation_size(const std::vector& values) const noexcept; + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the field offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the array is valid + size_t verify() const noexcept; + + // Get the array as C-array + template + size_t get(T (&values)[S]) const noexcept; + // Get the array as std::array + template + size_t get(std::array& values) const noexcept; + // Get the array as std::vector + size_t get(std::vector& values) const noexcept; + + // Set the array as C-array + template + size_t set(const T (&values)[S]) noexcept; + // Set the array as std::array + template + size_t set(const std::array& values) noexcept; + // Set the array as std::vector + size_t set(const std::vector& values) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; +}; + +// Fast Binary Encoding final model vector +template +class FinalModelVector +{ +public: + FinalModelVector(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the allocation size + size_t fbe_allocation_size(const std::vector& values) const noexcept; + size_t fbe_allocation_size(const std::list& values) const noexcept; + size_t fbe_allocation_size(const std::set& values) const noexcept; + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the field offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the vector is valid + size_t verify() const noexcept; + + // Get the vector as std::vector + size_t get(std::vector& values) const noexcept; + // Get the vector as std::list + size_t get(std::list& values) const noexcept; + // Get the vector as std::set + size_t get(std::set& values) const noexcept; + + // Set the vector as std::vector + size_t set(const std::vector& values) noexcept; + // Set the vector as std::list + size_t set(const std::list& values) noexcept; + // Set the vector as std::set + size_t set(const std::set& values) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; +}; + +// Fast Binary Encoding final model map +template +class FinalModelMap +{ +public: + FinalModelMap(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the allocation size + size_t fbe_allocation_size(const std::map& values) const noexcept; + size_t fbe_allocation_size(const std::unordered_map& values) const noexcept; + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Set the field offset + size_t fbe_offset(size_t offset) const noexcept { return _offset = offset; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the map is valid + size_t verify() const noexcept; + + // Get the map as std::map + size_t get(std::map& values) const noexcept; + // Get the map as std::unordered_map + size_t get(std::unordered_map& values) const noexcept; + + // Set the map as std::map + size_t set(const std::map& values) noexcept; + // Set the map as std::unordered_map + size_t set(const std::unordered_map& values) noexcept; + +private: + FBEBuffer& _buffer; + mutable size_t _offset; +}; + +} // namespace FBE + +#include "fbe_final_models.inl" diff --git a/fbe/user_model/fbe_final_models.inl b/fbe/user_model/fbe_final_models.inl new file mode 100644 index 0000000..d3035a8 --- /dev/null +++ b/fbe/user_model/fbe_final_models.inl @@ -0,0 +1,635 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: FBE +// Version: 1.7.0.0 + +namespace FBE { + +template +inline size_t FinalModelBase::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return std::numeric_limits::max(); + + return fbe_size(); +} + +template +inline size_t FinalModelBase::get(T& value) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + value = (T)(*((const TBase*)(_buffer.data() + _buffer.offset() + fbe_offset()))); + return fbe_size(); +} + +template +inline size_t FinalModelBase::set(T value) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + *((TBase*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (TBase)value; + return fbe_size(); +} + +template +inline bool FinalModel>::has_value() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + 1) > _buffer.size()) + return false; + + uint8_t fbe_has_value = *((const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + return (fbe_has_value != 0); +} + +template +inline size_t FinalModel>::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + 1) > _buffer.size()) + return std::numeric_limits::max(); + + uint8_t fbe_has_value = *((const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_has_value == 0) + return 1; + + _buffer.shift(fbe_offset() + 1); + size_t fbe_result = value.verify(); + _buffer.unshift(fbe_offset() + 1); + return 1 + fbe_result; +} + +template +inline size_t FinalModel>::get(std::optional& opt) const noexcept +{ + opt = std::nullopt; + + assert(((_buffer.offset() + fbe_offset() + 1) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 1) > _buffer.size()) + return 0; + + if (!has_value()) + return 1; + + _buffer.shift(fbe_offset() + 1); + T temp = T(); + size_t size = value.get(temp); + opt.emplace(temp); + _buffer.unshift(fbe_offset() + 1); + return 1 + size; +} + +template +inline size_t FinalModel>::set(const std::optional& opt) +{ + assert(((_buffer.offset() + fbe_offset() + 1) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 1) > _buffer.size()) + return 0; + + uint8_t fbe_has_value = opt ? 1 : 0; + *((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_has_value; + if (fbe_has_value == 0) + return 1; + + _buffer.shift(fbe_offset() + 1); + size_t size = 0; + if (opt) + size = value.set(opt.value()); + _buffer.unshift(fbe_offset() + 1); + return 1 + size; +} + +template +template +inline size_t FinalModelArray::fbe_allocation_size(const T (&values)[S]) const noexcept +{ + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = 0; (i < S) && (i < N); ++i) + size += fbe_model.fbe_allocation_size(values[i]); + return size; +} + +template +template +inline size_t FinalModelArray::fbe_allocation_size(const std::array& values) const noexcept +{ + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = 0; (i < S) && (i < N); ++i) + size += fbe_model.fbe_allocation_size(values[i]); + return size; +} + +template +inline size_t FinalModelArray::fbe_allocation_size(const std::vector& values) const noexcept +{ + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = 0; (i < values.size()) && (i < N); ++i) + size += fbe_model.fbe_allocation_size(values[i]); + return size; +} + +template +inline size_t FinalModelArray::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset()) > _buffer.size()) + return std::numeric_limits::max(); + + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = N; i-- > 0;) + { + size_t offset = fbe_model.verify(); + if (offset == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +template +inline size_t FinalModelArray::get(T (&values)[S]) const noexcept +{ + assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset()) > _buffer.size()) + return 0; + + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = 0; (i < S) && (i < N); ++i) + { + size_t offset = fbe_model.get(values[i]); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +template +inline size_t FinalModelArray::get(std::array& values) const noexcept +{ + assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset()) > _buffer.size()) + return 0; + + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = 0; (i < S) && (i < N); ++i) + { + size_t offset = fbe_model.get(values[i]); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelArray::get(std::vector& values) const noexcept +{ + values.clear(); + + assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset()) > _buffer.size()) + return 0; + + values.reserve(N); + + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = N; i-- > 0;) + { + T value = T(); + size_t offset = fbe_model.get(value); + values.emplace_back(value); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +template +inline size_t FinalModelArray::set(const T (&values)[S]) noexcept +{ + assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset()) > _buffer.size()) + return 0; + + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = 0; (i < S) && (i < N); ++i) + { + size_t offset = fbe_model.set(values[i]); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +template +inline size_t FinalModelArray::set(const std::array& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset()) > _buffer.size()) + return 0; + + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = 0; (i < S) && (i < N); ++i) + { + size_t offset = fbe_model.set(values[i]); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelArray::set(const std::vector& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset()) > _buffer.size()) + return 0; + + size_t size = 0; + FinalModel fbe_model(_buffer, fbe_offset()); + for (size_t i = 0; (i < values.size()) && (i < N); ++i) + { + size_t offset = fbe_model.set(values[i]); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelVector::fbe_allocation_size(const std::vector& values) const noexcept +{ + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (const auto& value : values) + size += fbe_model.fbe_allocation_size(value); + return size; +} + +template +inline size_t FinalModelVector::fbe_allocation_size(const std::list& values) const noexcept +{ + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (const auto& value : values) + size += fbe_model.fbe_allocation_size(value); + return size; +} + +template +inline size_t FinalModelVector::fbe_allocation_size(const std::set& values) const noexcept +{ + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (const auto& value : values) + size += fbe_model.fbe_allocation_size(value); + return size; +} + +template +inline size_t FinalModelVector::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return std::numeric_limits::max(); + + uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (size_t i = fbe_vector_size; i-- > 0;) + { + size_t offset = fbe_model.verify(); + if (offset == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelVector::get(std::vector& values) const noexcept +{ + values.clear(); + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + size_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_vector_size == 0) + return 4; + + values.reserve(fbe_vector_size); + + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (size_t i = fbe_vector_size; i-- > 0;) + { + T value = T(); + size_t offset = fbe_model.get(value); + values.emplace_back(value); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelVector::get(std::list& values) const noexcept +{ + values.clear(); + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + size_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_vector_size == 0) + return 4; + + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (size_t i = fbe_vector_size; i-- > 0;) + { + T value = T(); + size_t offset = fbe_model.get(value); + values.emplace_back(value); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelVector::get(std::set& values) const noexcept +{ + values.clear(); + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + size_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_vector_size == 0) + return 4; + + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (size_t i = fbe_vector_size; i-- > 0;) + { + T value = T(); + size_t offset = fbe_model.get(value); + values.emplace(value); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelVector::set(const std::vector& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size(); + + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (const auto& value : values) + { + size_t offset = fbe_model.set(value); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelVector::set(const std::list& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size(); + + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (const auto& value : values) + { + size_t offset = fbe_model.set(value); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelVector::set(const std::set& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size(); + + size_t size = 4; + FinalModel fbe_model(_buffer, fbe_offset() + 4); + for (const auto& value : values) + { + size_t offset = fbe_model.set(value); + fbe_model.fbe_shift(offset); + size += offset; + } + return size; +} + +template +inline size_t FinalModelMap::fbe_allocation_size(const std::map& values) const noexcept +{ + size_t size = 4; + FinalModel fbe_model_key(_buffer, fbe_offset() + 4); + FinalModel fbe_model_value(_buffer, fbe_offset() + 4); + for (const auto& value : values) + { + size += fbe_model_key.fbe_allocation_size(value.first); + size += fbe_model_value.fbe_allocation_size(value.second); + } + return size; +} + +template +inline size_t FinalModelMap::fbe_allocation_size(const std::unordered_map& values) const noexcept +{ + size_t size = 4; + FinalModel fbe_model_key(_buffer, fbe_offset() + 4); + FinalModel fbe_model_value(_buffer, fbe_offset() + 4); + for (const auto& value : values) + { + size += fbe_model_key.fbe_allocation_size(value.first); + size += fbe_model_value.fbe_allocation_size(value.second); + } + return size; +} + +template +inline size_t FinalModelMap::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return std::numeric_limits::max(); + + uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + + size_t size = 4; + FinalModel fbe_model_key(_buffer, fbe_offset() + 4); + FinalModel fbe_model_value(_buffer, fbe_offset() + 4); + for (size_t i = fbe_map_size; i-- > 0;) + { + size_t offset_key = fbe_model_key.verify(); + if (offset_key == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_model_key.fbe_shift(offset_key); + fbe_model_value.fbe_shift(offset_key); + size += offset_key; + size_t offset_value = fbe_model_value.verify(); + if (offset_value == std::numeric_limits::max()) + return std::numeric_limits::max(); + fbe_model_key.fbe_shift(offset_value); + fbe_model_value.fbe_shift(offset_value); + size += offset_value; + } + return size; +} + +template +inline size_t FinalModelMap::get(std::map& values) const noexcept +{ + values.clear(); + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + size_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_map_size == 0) + return 4; + + size_t size = 4; + FinalModel fbe_model_key(_buffer, fbe_offset() + 4); + FinalModel fbe_model_value(_buffer, fbe_offset() + 4); + for (size_t i = fbe_map_size; i-- > 0;) + { + TKey key; + TValue value; + size_t offset_key = fbe_model_key.get(key); + fbe_model_key.fbe_shift(offset_key); + fbe_model_value.fbe_shift(offset_key); + size_t offset_value = fbe_model_value.get(value); + fbe_model_key.fbe_shift(offset_value); + fbe_model_value.fbe_shift(offset_value); + values.emplace(key, value); + size += offset_key + offset_value; + } + return size; +} + +template +inline size_t FinalModelMap::get(std::unordered_map& values) const noexcept +{ + values.clear(); + + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + size_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_map_size == 0) + return 4; + + size_t size = 4; + FinalModel fbe_model_key(_buffer, fbe_offset() + 4); + FinalModel fbe_model_value(_buffer, fbe_offset() + 4); + for (size_t i = fbe_map_size; i-- > 0;) + { + TKey key; + TValue value; + size_t offset_key = fbe_model_key.get(key); + fbe_model_key.fbe_shift(offset_key); + fbe_model_value.fbe_shift(offset_key); + size_t offset_value = fbe_model_value.get(value); + fbe_model_key.fbe_shift(offset_value); + fbe_model_value.fbe_shift(offset_value); + values.emplace(key, value); + size += offset_key + offset_value; + } + return size; +} + +template +inline size_t FinalModelMap::set(const std::map& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size(); + + size_t size = 4; + FinalModel fbe_model_key(_buffer, fbe_offset() + 4); + FinalModel fbe_model_value(_buffer, fbe_offset() + 4); + for (const auto& value : values) + { + size_t offset_key = fbe_model_key.set(value.first); + fbe_model_key.fbe_shift(offset_key); + fbe_model_value.fbe_shift(offset_key); + size_t offset_value = fbe_model_value.set(value.second); + fbe_model_key.fbe_shift(offset_value); + fbe_model_value.fbe_shift(offset_value); + size += offset_key + offset_value; + } + return size; +} + +template +inline size_t FinalModelMap::set(const std::unordered_map& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + 4) > _buffer.size()) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)values.size(); + + size_t size = 4; + FinalModel fbe_model_key(_buffer, fbe_offset() + 4); + FinalModel fbe_model_value(_buffer, fbe_offset() + 4); + for (const auto& value : values) + { + size_t offset_key = fbe_model_key.set(value.first); + fbe_model_key.fbe_shift(offset_key); + fbe_model_value.fbe_shift(offset_key); + size_t offset_value = fbe_model_value.set(value.second); + fbe_model_key.fbe_shift(offset_value); + fbe_model_value.fbe_shift(offset_value); + size += offset_key + offset_value; + } + return size; +} + +} // namespace FBE diff --git a/fbe/user_model/fbe_models.cpp b/fbe/user_model/fbe_models.cpp new file mode 100644 index 0000000..dd4ecb9 --- /dev/null +++ b/fbe/user_model/fbe_models.cpp @@ -0,0 +1,514 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: FBE +// Version: 1.7.0.0 + +#include "fbe_models.h" + +namespace FBE { + +uint64_t FieldModel::extract(double a) noexcept +{ + uint64_t result; + std::memcpy(&result, &a, sizeof(double)); + return result; +} + +uint64_t FieldModel::uint32x32(uint32_t a, uint32_t b) noexcept +{ + return (uint64_t)a * (uint64_t)b; +} + +void FieldModel::uint64x64(uint64_t a, uint64_t b, uint64_t& low64, uint32_t& high32) noexcept +{ + uint64_t low = uint32x32((uint32_t)a, (uint32_t)b); + uint64_t mid = uint32x32((uint32_t)a, (uint32_t)(b >> 32)); + uint64_t high = uint32x32((uint32_t)(a >> 32), (uint32_t)(b >> 32)); + high += (mid >> 32); + low += (mid <<= 32); + // Test for carry + if (low < mid) + high++; + + mid = uint32x32((uint32_t)(a >> 32), (uint32_t)b); + high += (mid >> 32); + low += (mid <<= 32); + // Test for carry + if (low < mid) + high++; + + if (high > 0xFFFFFFFFu) + { + low64 = 0; + high32 = 0; + } + low64 = low; + high32 = (uint32_t)high; +} + +void FieldModel::get(decimal_t& value, decimal_t defaults) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + { + value = defaults; + return; + } + + // Value taken via reverse engineering the double that corresponds to 2^64 + const double ds2to64 = 1.8446744073709552e+019; + + // Read decimal parts + uint64_t low = *((const uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + uint32_t high = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)); + uint32_t flags = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 12)); + + // Calculate decimal value + double dValue = ((double)low + (double)high * ds2to64) / pow(10.0, (uint8_t)(flags >> 16)); + if (flags & 0x80000000) + dValue = -dValue; + + value = dValue; +} + +void FieldModel::set(decimal_t value) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + // The most we can scale by is 10^28, which is just slightly more + // than 2^93. So a float with an exponent of -94 could just + // barely reach 0.5, but smaller exponents will always round to zero. + const uint32_t DBLBIAS = 1022; + + // Get exponent value + double dValue = (double)value; + int32_t iExp = (int32_t)(((uint32_t)(extract(dValue) >> 52) & 0x7FFu) - DBLBIAS); + if ((iExp < -94) || (iExp > 96)) + { + // Value too big for .NET Decimal (exponent is limited to [-94, 96]) + memset((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), 0, 16); + return; + } + + uint32_t flags = 0; + if (dValue < 0) + { + dValue = -dValue; + flags = 0x80000000; + } + + // Round the input to a 15-digit integer. The R8 format has + // only 15 digits of precision, and we want to keep garbage digits + // out of the Decimal were making. + + // Calculate max power of 10 input value could have by multiplying + // the exponent by log10(2). Using scaled integer multiplcation, + // log10(2) * 2 ^ 16 = .30103 * 65536 = 19728.3. + int32_t iPower = 14 - ((iExp * 19728) >> 16); + + // iPower is between -14 and 43 + if (iPower >= 0) + { + // We have less than 15 digits, scale input up. + if (iPower > 28) + iPower = 28; + + dValue *= pow(10.0, iPower); + } + else + { + if ((iPower != -1) || (dValue >= 1E15)) + dValue /= pow(10.0, -iPower); + else + iPower = 0; // didn't scale it + } + + assert(dValue < 1E15); + if ((dValue < 1E14) && (iPower < 28)) + { + dValue *= 10; + iPower++; + assert(dValue >= 1E14); + } + + // Round to int64 + uint64_t ulMant; + ulMant = (uint64_t)(int64_t)dValue; + dValue -= (int64_t)ulMant; // difference between input & integer + if ((dValue > 0.5) || ((dValue == 0.5) && ((ulMant & 1) != 0))) + ulMant++; + + if (ulMant == 0) + { + // Mantissa is 0 + memset((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), 0, 16); + return; + } + + if (iPower < 0) + { + // Add -iPower factors of 10, -iPower <= (29 - 15) = 14 + iPower = -iPower; + if (iPower < 10) + { + double pow10 = (double)powl(10.0, iPower); + uint64_t low64 = uint32x32((uint32_t)ulMant, (uint32_t)pow10); + uint64_t high64 = uint32x32((uint32_t)(ulMant >> 32), (uint32_t)pow10); + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (uint32_t)low64; + high64 += low64 >> 32; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 4)) = (uint32_t)high64; + high64 >>= 32; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = (uint32_t)high64; + } + else + { + // Have a big power of 10. + assert(iPower <= 14); + uint64_t low64; + uint32_t high32; + uint64x64(ulMant, (uint64_t)pow(10.0, iPower), low64, high32); + *((uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = low64; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = high32; + } + } + else + { + // Factor out powers of 10 to reduce the scale, if possible. + // The maximum number we could factor out would be 14. This + // comes from the fact we have a 15-digit number, and the + // MSD must be non-zero -- but the lower 14 digits could be + // zero. Note also the scale factor is never negative, so + // we can't scale by any more than the power we used to + // get the integer. + int lmax = iPower; + if (lmax > 14) + lmax = 14; + + if ((((uint8_t)ulMant) == 0) && (lmax >= 8)) + { + const uint32_t den = 100000000; + uint64_t div = ulMant / den; + if ((uint32_t)ulMant == (uint32_t)(div * den)) + { + ulMant = div; + iPower -= 8; + lmax -= 8; + } + } + + if ((((uint32_t)ulMant & 0xF) == 0) && (lmax >= 4)) + { + const uint32_t den = 10000; + uint64_t div = ulMant / den; + if ((uint32_t)ulMant == (uint32_t)(div * den)) + { + ulMant = div; + iPower -= 4; + lmax -= 4; + } + } + + if ((((uint32_t)ulMant & 3) == 0) && (lmax >= 2)) + { + const uint32_t den = 100; + uint64_t div = ulMant / den; + if ((uint32_t)ulMant == (uint32_t)(div * den)) + { + ulMant = div; + iPower -= 2; + lmax -= 2; + } + } + + if ((((uint32_t)ulMant & 1) == 0) && (lmax >= 1)) + { + const uint32_t den = 10; + uint64_t div = ulMant / den; + if ((uint32_t)ulMant == (uint32_t)(div * den)) + { + ulMant = div; + iPower--; + } + } + + flags |= (uint32_t)iPower << 16; + + *((uint64_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = ulMant; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 8)) = 0; + } + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 12)) = flags; +} + +void FieldModel::get(uuid_t& value, uuid_t defaults) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + { + value = defaults; + return; + } + + std::memcpy(value.data().data(), (const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), fbe_size()); +} + +void FieldModel::set(uuid_t value) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + std::memcpy((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset()), value.data().data(), fbe_size()); +} + +size_t FieldModel::fbe_extra() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_bytes_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_bytes_offset == 0) || ((_buffer.offset() + fbe_bytes_offset + 4) > _buffer.size())) + return 0; + + uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset)); + return (size_t)(4 + fbe_bytes_size); +} + +bool FieldModel::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return true; + + uint32_t fbe_bytes_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_bytes_offset == 0) + return true; + + if ((_buffer.offset() + fbe_bytes_offset + 4) > _buffer.size()) + return false; + + uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset)); + if ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) > _buffer.size()) + return false; + + return true; +} + +size_t FieldModel::get(void* data, size_t size) const noexcept +{ + assert(((size == 0) || (data != nullptr)) && "Invalid buffer!"); + if ((size > 0) && (data == nullptr)) + return 0; + + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_bytes_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_bytes_offset == 0) + return 0; + + assert(((_buffer.offset() + fbe_bytes_offset + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_bytes_offset + 4) > _buffer.size()) + return 0; + + uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset)); + assert(((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) > _buffer.size()) + return 0; + + size_t result = std::min(size, (size_t)fbe_bytes_size); + memcpy(data, (const char*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset + 4), result); + return result; +} + +void FieldModel::get(std::vector& value) const noexcept +{ + value.clear(); + + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + uint32_t fbe_bytes_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_bytes_offset == 0) + return; + + assert(((_buffer.offset() + fbe_bytes_offset + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_bytes_offset + 4) > _buffer.size()) + return; + + uint32_t fbe_bytes_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset)); + assert(((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) > _buffer.size()) + return; + + const char* fbe_bytes = (const char*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset + 4); + value.assign(fbe_bytes, fbe_bytes + fbe_bytes_size); +} + +void FieldModel::set(const void* data, size_t size) +{ + assert(((size == 0) || (data != nullptr)) && "Invalid buffer!"); + if ((size > 0) && (data == nullptr)) + return; + + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + uint32_t fbe_bytes_size = (uint32_t)size; + uint32_t fbe_bytes_offset = (uint32_t)(_buffer.allocate(4 + fbe_bytes_size) - _buffer.offset()); + assert(((fbe_bytes_offset > 0) && ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) <= _buffer.size())) && "Model is broken!"); + if ((fbe_bytes_offset == 0) || ((_buffer.offset() + fbe_bytes_offset + 4 + fbe_bytes_size) > _buffer.size())) + return; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_bytes_offset; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset)) = fbe_bytes_size; + + memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_bytes_offset + 4), data, fbe_bytes_size); +} + +size_t FieldModel::fbe_extra() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_string_offset == 0) || ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size())) + return 0; + + uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset)); + return (size_t)(4 + fbe_string_size); +} + +bool FieldModel::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return true; + + uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_string_offset == 0) + return true; + + if ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size()) + return false; + + uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset)); + if ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size()) + return false; + + return true; +} + +size_t FieldModel::get(char* data, size_t size) const noexcept +{ + assert(((size == 0) || (data != nullptr)) && "Invalid buffer!"); + if ((size > 0) && (data == nullptr)) + return 0; + + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_string_offset == 0) + return 0; + + assert(((_buffer.offset() + fbe_string_offset + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size()) + return 0; + + uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset)); + assert(((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size()) + return 0; + + size_t result = std::min(size, (size_t)fbe_string_size); + memcpy(data, (const char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), result); + return result; +} + +void FieldModel::get(std::string& value) const noexcept +{ + value.clear(); + + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + _offset)); + if (fbe_string_offset == 0) + return; + + assert(((_buffer.offset() + fbe_string_offset + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size()) + return; + + uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset)); + assert(((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size()) + return; + + value.assign((const char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), fbe_string_size); +} + +void FieldModel::get(std::string& value, const std::string& defaults) const noexcept +{ + value = defaults; + + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + uint32_t fbe_string_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + _offset)); + if (fbe_string_offset == 0) + return; + + assert(((_buffer.offset() + fbe_string_offset + 4) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_string_offset + 4) > _buffer.size()) + return; + + uint32_t fbe_string_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset)); + assert(((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size()) + return; + + value.assign((const char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), fbe_string_size); +} + +void FieldModel::set(const char* data, size_t size) +{ + assert(((size == 0) || (data != nullptr)) && "Invalid buffer!"); + if ((size > 0) && (data == nullptr)) + return; + + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + uint32_t fbe_string_size = (uint32_t)size; + uint32_t fbe_string_offset = (uint32_t)(_buffer.allocate(4 + fbe_string_size) - _buffer.offset()); + assert(((fbe_string_offset > 0) && ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size())) && "Model is broken!"); + if ((fbe_string_offset == 0) || ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size())) + return; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_string_offset; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset)) = fbe_string_size; + + memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), data, fbe_string_size); +} + +void FieldModel::set(const std::string& value) +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + uint32_t fbe_string_size = (uint32_t)value.size(); + uint32_t fbe_string_offset = (uint32_t)(_buffer.allocate(4 + fbe_string_size) - _buffer.offset()); + assert(((fbe_string_offset > 0) && ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) <= _buffer.size())) && "Model is broken!"); + if ((fbe_string_offset == 0) || ((_buffer.offset() + fbe_string_offset + 4 + fbe_string_size) > _buffer.size())) + return; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_string_offset; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_string_offset)) = fbe_string_size; + + memcpy((char*)(_buffer.data() + _buffer.offset() + fbe_string_offset + 4), value.data(), fbe_string_size); +} + +} // namespace FBE diff --git a/fbe/user_model/fbe_models.h b/fbe/user_model/fbe_models.h new file mode 100644 index 0000000..9326a5d --- /dev/null +++ b/fbe/user_model/fbe_models.h @@ -0,0 +1,469 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: FBE +// Version: 1.7.0.0 + +#pragma once + +#if defined(__clang__) +#pragma clang system_header +#elif defined(__GNUC__) +#pragma GCC system_header +#elif defined(_MSC_VER) +#pragma system_header +#endif + +#include "fbe.h" + +namespace FBE { + +// Fast Binary Encoding base field model +template +class FieldModelBase +{ +public: + FieldModelBase(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return sizeof(TBase); } + // Get the field extra size + size_t fbe_extra() const noexcept { return 0; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the value is valid + bool verify() const noexcept { return true; } + + // Get the field value + void get(T& value, T defaults = (T)0) const noexcept; + // Set the field value + void set(T value) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; +}; + +// Fast Binary Encoding field model +template +class FieldModel : public FieldModelBase +{ +public: + using FieldModelBase::FieldModelBase; +}; + +// Fast Binary Encoding field model bool specialization +template <> +class FieldModel : public FieldModelBase +{ +public: + using FieldModelBase::FieldModelBase; +}; + +// Fast Binary Encoding field model char specialization +template <> +class FieldModel : public FieldModelBase +{ +public: + using FieldModelBase::FieldModelBase; +}; + +// Fast Binary Encoding field model wchar specialization +template <> +class FieldModel : public FieldModelBase +{ +public: + using FieldModelBase::FieldModelBase; +}; + +// Fast Binary Encoding field model decimal specialization +template <> +class FieldModel +{ +public: + FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 16; } + // Get the field extra size + size_t fbe_extra() const noexcept { return 0; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the decimal value is valid + bool verify() const noexcept { return true; } + + // Get the decimal value + void get(decimal_t& value, decimal_t defaults = decimal_t()) const noexcept; + // Set the decimal value + void set(decimal_t value) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; + + static uint64_t extract(double a) noexcept; + static uint64_t uint32x32(uint32_t a, uint32_t b) noexcept; + static void uint64x64(uint64_t a, uint64_t b, uint64_t& low64, uint32_t& high32) noexcept; +}; + +// Fast Binary Encoding field model UUID specialization +template <> +class FieldModel +{ +public: + FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 16; } + // Get the field extra size + size_t fbe_extra() const noexcept { return 0; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the UUID value is valid + bool verify() const noexcept { return true; } + + // Get the UUID value + void get(uuid_t& value, uuid_t defaults = uuid_t::nil()) const noexcept; + // Set the UUID value + void set(uuid_t value) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; +}; + +// Fast Binary Encoding field model bytes specialization +template <> +class FieldModel +{ +public: + FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 4; } + // Get the field extra size + size_t fbe_extra() const noexcept; + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the bytes value is valid + bool verify() const noexcept; + + // Get the bytes value + size_t get(void* data, size_t size) const noexcept; + // Get the bytes value + template + size_t get(uint8_t (&data)[N]) const noexcept { return get(data, N); } + // Get the bytes value + template + size_t get(std::array& data) const noexcept { return get(data.data(), data.size()); } + // Get the bytes value + void get(std::vector& value) const noexcept; + // Get the bytes value + void get(buffer_t& value) const noexcept { get(value.buffer()); } + + // Set the bytes value + void set(const void* data, size_t size); + // Set the bytes value + template + void set(const uint8_t (&data)[N]) { set(data, N); } + // Set the bytes value + template + void set(const std::array& data) { set(data.data(), data.size()); } + // Set the bytes value + void set(const std::vector& value) { set(value.data(), value.size()); } + // Set the bytes value + void set(const buffer_t& value) { set(value.buffer()); } + +private: + FBEBuffer& _buffer; + size_t _offset; +}; + +// Fast Binary Encoding field model string specialization +template <> +class FieldModel +{ +public: + FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 4; } + // Get the field extra size + size_t fbe_extra() const noexcept; + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Check if the string value is valid + bool verify() const noexcept; + + // Get the string value + size_t get(char* data, size_t size) const noexcept; + // Get the string value + template + size_t get(char (&data)[N]) const noexcept { return get(data, N); } + // Get the string value + template + size_t get(std::array& data) const noexcept { return get(data.data(), data.size()); } + // Get the string value + void get(std::string& value) const noexcept; + // Get the string value + void get(std::string& value, const std::string& defaults) const noexcept; + + // Set the string value + void set(const char* data, size_t size); + // Set the string value + template + void set(const char (&data)[N]) { set(data, N); } + // Set the string value + template + void set(const std::array& data) { set(data.data(), data.size()); } + // Set the string value + void set(const std::string& value); + +private: + FBEBuffer& _buffer; + size_t _offset; +}; + +// Fast Binary Encoding field model optional specialization +template +class FieldModel> +{ +public: + FieldModel(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset), value(buffer, 0) {} + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 1 + 4; } + // Get the field extra size + size_t fbe_extra() const noexcept; + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + //! Is the value present? + explicit operator bool() const noexcept { return has_value(); } + + // Checks if the object contains a value + bool has_value() const noexcept; + + // Check if the optional value is valid + bool verify() const noexcept; + + // Get the optional value (being phase) + size_t get_begin() const noexcept; + // Get the optional value (end phase) + void get_end(size_t fbe_begin) const noexcept; + + // Get the optional value + void get(std::optional& opt, const std::optional& defaults = std::nullopt) const noexcept; + + // Set the optional value (begin phase) + size_t set_begin(bool has_value); + // Set the optional value (end phase) + void set_end(size_t fbe_begin); + + // Set the optional value + void set(const std::optional& opt); + +private: + FBEBuffer& _buffer; + size_t _offset; + +public: + // Base field model value + FieldModel value; +}; + +// Fast Binary Encoding field model array +template +class FieldModelArray +{ +public: + FieldModelArray(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset), _model(buffer, offset) {} + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return N * _model.fbe_size(); } + // Get the field extra size + size_t fbe_extra() const noexcept { return 0; } + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Get the array + const uint8_t* data() const noexcept; + // Get the array + uint8_t* data() noexcept; + // Get the array offset + size_t offset() const noexcept { return 0; } + // Get the array size + size_t size() const noexcept { return N; } + + // Array index operator + FieldModel operator[](size_t index) const noexcept; + + // Check if the array is valid + bool verify() const noexcept; + + // Get the array as C-array + template + void get(T (&values)[S]) const noexcept; + // Get the array as std::array + template + void get(std::array& values) const noexcept; + // Get the array as std::vector + void get(std::vector& values) const noexcept; + + // Set the array as C-array + template + void set(const T (&values)[S]) noexcept; + // Set the array as std::array + template + void set(const std::array& values) noexcept; + // Set the array as std::vector + void set(const std::vector& values) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; + FieldModel _model; +}; + +// Fast Binary Encoding field model vector +template +class FieldModelVector +{ +public: + FieldModelVector(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 4; } + // Get the field extra size + size_t fbe_extra() const noexcept; + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Get the vector offset + size_t offset() const noexcept; + // Get the vector size + size_t size() const noexcept; + + // Vector index operator + FieldModel operator[](size_t index) const noexcept; + + // Resize the vector and get its first model + FieldModel resize(size_t size); + + // Check if the vector is valid + bool verify() const noexcept; + + // Get the vector as std::vector + void get(std::vector& values) const noexcept; + // Get the vector as std::list + void get(std::list& values) const noexcept; + // Get the vector as std::set + void get(std::set& values) const noexcept; + + // Set the vector as std::vector + void set(const std::vector& values) noexcept; + // Set the vector as std::list + void set(const std::list& values) noexcept; + // Set the vector as std::set + void set(const std::set& values) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; +}; + +// Fast Binary Encoding field model map +template +class FieldModelMap +{ +public: + FieldModelMap(FBEBuffer& buffer, size_t offset) noexcept : _buffer(buffer), _offset(offset) {} + + // Get the field offset + size_t fbe_offset() const noexcept { return _offset; } + // Get the field size + size_t fbe_size() const noexcept { return 4; } + // Get the field extra size + size_t fbe_extra() const noexcept; + + // Shift the current field offset + void fbe_shift(size_t size) noexcept { _offset += size; } + // Unshift the current field offset + void fbe_unshift(size_t size) noexcept { _offset -= size; } + + // Get the map offset + size_t offset() const noexcept; + // Get the map size + size_t size() const noexcept; + + // Map index operator + std::pair, FieldModel> operator[](size_t index) const noexcept; + + // Resize the map and get its first model + std::pair, FieldModel> resize(size_t size); + + // Check if the map is valid + bool verify() const noexcept; + + // Get the map as std::map + void get(std::map& values) const noexcept; + // Get the map as std::unordered_map + void get(std::unordered_map& values) const noexcept; + + // Set the map as std::map + void set(const std::map& values) noexcept; + // Set the map as std::unordered_map + void set(const std::unordered_map& values) noexcept; + +private: + FBEBuffer& _buffer; + size_t _offset; +}; + +} // namespace FBE + +#include "fbe_models.inl" diff --git a/fbe/user_model/fbe_models.inl b/fbe/user_model/fbe_models.inl new file mode 100644 index 0000000..1ddba97 --- /dev/null +++ b/fbe/user_model/fbe_models.inl @@ -0,0 +1,687 @@ +// Automatically generated by the Fast Binary Encoding compiler, do not modify! +// https://github.com/chronoxor/FastBinaryEncoding +// Source: FBE +// Version: 1.7.0.0 + +namespace FBE { + +template +inline void FieldModelBase::get(T& value, T defaults) const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + { + value = defaults; + return; + } + + value = (T)(*((const TBase*)(_buffer.data() + _buffer.offset() + fbe_offset()))); +} + +template +inline void FieldModelBase::set(T value) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + *((TBase*)(_buffer.data() + _buffer.offset() + fbe_offset())) = (TBase)value; +} + +template +inline size_t FieldModel>::fbe_extra() const noexcept +{ + if (!has_value()) + return 0; + + uint32_t fbe_optional_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 1)); + if ((fbe_optional_offset == 0) || ((_buffer.offset() + fbe_optional_offset + 4) > _buffer.size())) + return 0; + + _buffer.shift(fbe_optional_offset); + size_t fbe_result = value.fbe_size() + value.fbe_extra(); + _buffer.unshift(fbe_optional_offset); + return fbe_result; +} + +template +inline bool FieldModel>::has_value() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return false; + + uint8_t fbe_has_value = *((const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + return (fbe_has_value != 0); +} + +template +inline bool FieldModel>::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return true; + + uint8_t fbe_has_value = *((const uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_has_value == 0) + return true; + + uint32_t fbe_optional_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 1)); + if (fbe_optional_offset == 0) + return false; + + _buffer.shift(fbe_optional_offset); + bool fbe_result = value.verify(); + _buffer.unshift(fbe_optional_offset); + return fbe_result; +} + +template +inline size_t FieldModel>::get_begin() const noexcept +{ + if (!has_value()) + return 0; + + uint32_t fbe_optional_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 1)); + assert((fbe_optional_offset > 0) && "Model is broken!"); + if (fbe_optional_offset == 0) + return 0; + + _buffer.shift(fbe_optional_offset); + return fbe_optional_offset; +} + +template +inline void FieldModel>::get_end(size_t fbe_begin) const noexcept +{ + _buffer.unshift(fbe_begin); +} + +template +inline void FieldModel>::get(std::optional& opt, const std::optional& defaults) const noexcept +{ + opt = defaults; + + size_t fbe_begin = get_begin(); + if (fbe_begin == 0) + return; + + T temp = T(); + value.get(temp); + opt.emplace(temp); + + get_end(fbe_begin); +} + +template +inline size_t FieldModel>::set_begin(bool has_value) +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint8_t fbe_has_value = has_value ? 1 : 0; + *((uint8_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_has_value; + if (fbe_has_value == 0) + return 0; + + uint32_t fbe_optional_size = (uint32_t)value.fbe_size(); + uint32_t fbe_optional_offset = (uint32_t)(_buffer.allocate(fbe_optional_size) - _buffer.offset()); + assert(((fbe_optional_offset > 0) && ((_buffer.offset() + fbe_optional_offset + fbe_optional_size) <= _buffer.size())) && "Model is broken!"); + if ((fbe_optional_offset == 0) || ((_buffer.offset() + fbe_optional_offset + fbe_optional_size) > _buffer.size())) + return 0; + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset() + 1)) = fbe_optional_offset; + + _buffer.shift(fbe_optional_offset); + return fbe_optional_offset; +} + +template +inline void FieldModel>::set_end(size_t fbe_begin) +{ + _buffer.unshift(fbe_begin); +} + +template +inline void FieldModel>::set(const std::optional& opt) +{ + size_t fbe_begin = set_begin(opt.has_value()); + if (fbe_begin == 0) + return; + + if (opt) + value.set(opt.value()); + + set_end(fbe_begin); +} + +template +inline const uint8_t* FieldModelArray::data() const noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + return _buffer.data() + _buffer.offset() + fbe_offset(); +} + +template +inline uint8_t* FieldModelArray::data() noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + return _buffer.data() + _buffer.offset() + fbe_offset(); +} + +template +inline FieldModel FieldModelArray::operator[](size_t index) const noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + assert((index < N) && "Index is out of bounds!"); + + FieldModel fbe_model(_buffer, fbe_offset()); + fbe_model.fbe_shift(index * fbe_model.fbe_size()); + return fbe_model; +} + +template +inline bool FieldModelArray::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return false; + + FieldModel fbe_model(_buffer, fbe_offset()); + for (size_t i = N; i-- > 0;) + { + if (!fbe_model.verify()) + return false; + fbe_model.fbe_shift(fbe_model.fbe_size()); + } + + return true; +} + +template +template +inline void FieldModelArray::get(T (&values)[S]) const noexcept +{ + auto fbe_model = (*this)[0]; + for (size_t i = 0; (i < S) && (i < N); ++i) + { + fbe_model.get(values[i]); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +template +inline void FieldModelArray::get(std::array& values) const noexcept +{ + auto fbe_model = (*this)[0]; + for (size_t i = 0; (i < S) && (i < N); ++i) + { + fbe_model.get(values[i]); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +inline void FieldModelArray::get(std::vector& values) const noexcept +{ + values.clear(); + values.reserve(N); + + auto fbe_model = (*this)[0]; + for (size_t i = N; i-- > 0;) + { + T value = T(); + fbe_model.get(value); + values.emplace_back(value); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +template +inline void FieldModelArray::set(const T (&values)[S]) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + auto fbe_model = (*this)[0]; + for (size_t i = 0; (i < S) && (i < N); ++i) + { + fbe_model.set(values[i]); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +template +inline void FieldModelArray::set(const std::array& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + auto fbe_model = (*this)[0]; + for (size_t i = 0; (i < S) && (i < N); ++i) + { + fbe_model.set(values[i]); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +inline void FieldModelArray::set(const std::vector& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + auto fbe_model = (*this)[0]; + for (size_t i = 0; (i < values.size()) && (i < N); ++i) + { + fbe_model.set(values[i]); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +inline size_t FieldModelVector::fbe_extra() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_vector_offset == 0) || ((_buffer.offset() + fbe_vector_offset + 4) > _buffer.size())) + return 0; + + uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset)); + + size_t fbe_result = 4; + FieldModel fbe_model(_buffer, fbe_vector_offset + 4); + for (size_t i = fbe_vector_size; i-- > 0;) + { + fbe_result += fbe_model.fbe_size() + fbe_model.fbe_extra(); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } + return fbe_result; +} + +template +inline size_t FieldModelVector::offset() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + return fbe_vector_offset; +} + +template +inline size_t FieldModelVector::size() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_vector_offset == 0) || ((_buffer.offset() + fbe_vector_offset + 4) > _buffer.size())) + return 0; + + uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset)); + return fbe_vector_size; +} + +template +inline FieldModel FieldModelVector::operator[](size_t index) const noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + + uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((fbe_vector_offset > 0) && ((_buffer.offset() + fbe_vector_offset + 4) <= _buffer.size())) && "Model is broken!"); + + [[maybe_unused]] uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset)); + assert((index < fbe_vector_size) && "Index is out of bounds!"); + + FieldModel fbe_model(_buffer, fbe_vector_offset + 4); + fbe_model.fbe_shift(index * fbe_model.fbe_size()); + return fbe_model; +} + +template +inline FieldModel FieldModelVector::resize(size_t size) +{ + FieldModel fbe_model(_buffer, fbe_offset()); + + uint32_t fbe_vector_size = (uint32_t)(size * fbe_model.fbe_size()); + uint32_t fbe_vector_offset = (uint32_t)(_buffer.allocate(4 + fbe_vector_size) - _buffer.offset()); + assert(((fbe_vector_offset > 0) && ((_buffer.offset() + fbe_vector_offset + 4) <= _buffer.size())) && "Model is broken!"); + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_vector_offset; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset)) = (uint32_t)size; + + memset((char*)(_buffer.data() + _buffer.offset() + fbe_vector_offset + 4), 0, fbe_vector_size); + + return FieldModel(_buffer, fbe_vector_offset + 4); +} + +template +inline bool FieldModelVector::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return true; + + uint32_t fbe_vector_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_vector_offset == 0) + return true; + + if ((_buffer.offset() + fbe_vector_offset + 4) > _buffer.size()) + return false; + + uint32_t fbe_vector_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_vector_offset)); + + FieldModel fbe_model(_buffer, fbe_vector_offset + 4); + for (size_t i = fbe_vector_size; i-- > 0;) + { + if (!fbe_model.verify()) + return false; + fbe_model.fbe_shift(fbe_model.fbe_size()); + } + + return true; +} + +template +inline void FieldModelVector::get(std::vector& values) const noexcept +{ + values.clear(); + + size_t fbe_vector_size = size(); + if (fbe_vector_size == 0) + return; + + values.reserve(fbe_vector_size); + + auto fbe_model = (*this)[0]; + for (size_t i = fbe_vector_size; i-- > 0;) + { + T value = T(); + fbe_model.get(value); + values.emplace_back(value); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +inline void FieldModelVector::get(std::list& values) const noexcept +{ + values.clear(); + + size_t fbe_vector_size = size(); + if (fbe_vector_size == 0) + return; + + auto fbe_model = (*this)[0]; + for (size_t i = fbe_vector_size; i-- > 0;) + { + T value = T(); + fbe_model.get(value); + values.emplace_back(value); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +inline void FieldModelVector::get(std::set& values) const noexcept +{ + values.clear(); + + size_t fbe_vector_size = size(); + if (fbe_vector_size == 0) + return; + + auto fbe_model = (*this)[0]; + for (size_t i = fbe_vector_size; i-- > 0;) + { + T value = T(); + fbe_model.get(value); + values.emplace(value); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +inline void FieldModelVector::set(const std::vector& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + auto fbe_model = resize(values.size()); + for (const auto& value : values) + { + fbe_model.set(value); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +inline void FieldModelVector::set(const std::list& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + auto fbe_model = resize(values.size()); + for (const auto& value : values) + { + fbe_model.set(value); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +inline void FieldModelVector::set(const std::set& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + auto fbe_model = resize(values.size()); + for (const auto& value : values) + { + fbe_model.set(value); + fbe_model.fbe_shift(fbe_model.fbe_size()); + } +} + +template +inline size_t FieldModelMap::fbe_extra() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_map_offset == 0) || ((_buffer.offset() + fbe_map_offset + 4) > _buffer.size())) + return 0; + + uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset)); + + size_t fbe_result = 4; + FieldModel fbe_model_key(_buffer, fbe_map_offset + 4); + FieldModel fbe_model_value(_buffer, fbe_map_offset + 4 + fbe_model_key.fbe_size()); + for (size_t i = fbe_map_size; i-- > 0;) + { + fbe_result += fbe_model_key.fbe_size() + fbe_model_key.fbe_extra(); + fbe_model_key.fbe_shift(fbe_model_key.fbe_size() + fbe_model_value.fbe_size()); + fbe_result += fbe_model_value.fbe_size() + fbe_model_value.fbe_extra(); + fbe_model_value.fbe_shift(fbe_model_key.fbe_size() + fbe_model_value.fbe_size()); + } + return fbe_result; +} + +template +inline size_t FieldModelMap::offset() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + return fbe_map_offset; +} + +template +inline size_t FieldModelMap::size() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return 0; + + uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if ((fbe_map_offset == 0) || ((_buffer.offset() + fbe_map_offset + 4) > _buffer.size())) + return 0; + + uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset)); + return fbe_map_size; +} + +template +inline std::pair, FieldModel> FieldModelMap::operator[](size_t index) const noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + + uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + assert(((fbe_map_offset > 0) && ((_buffer.offset() + fbe_map_offset + 4) <= _buffer.size())) && "Model is broken!"); + + [[maybe_unused]] uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset)); + assert((index < fbe_map_size) && "Index is out of bounds!"); + + FieldModel fbe_model_key(_buffer, fbe_map_offset + 4); + FieldModel fbe_model_value(_buffer, fbe_map_offset + 4 + fbe_model_key.fbe_size()); + fbe_model_key.fbe_shift(index * (fbe_model_key.fbe_size() + fbe_model_value.fbe_size())); + fbe_model_value.fbe_shift(index * (fbe_model_key.fbe_size() + fbe_model_value.fbe_size())); + return std::make_pair(fbe_model_key, fbe_model_value); +} + +template +inline std::pair, FieldModel> FieldModelMap::resize(size_t size) +{ + FieldModel fbe_model_key(_buffer, fbe_offset()); + FieldModel fbe_model_value(_buffer, fbe_offset() + fbe_model_key.fbe_size()); + + uint32_t fbe_map_size = (uint32_t)(size * (fbe_model_key.fbe_size() + fbe_model_value.fbe_size())); + uint32_t fbe_map_offset = (uint32_t)(_buffer.allocate(4 + fbe_map_size) - _buffer.offset()); + assert(((fbe_map_offset > 0) && ((_buffer.offset() + fbe_map_offset + 4 + fbe_map_size) <= _buffer.size())) && "Model is broken!"); + + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())) = fbe_map_offset; + *((uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset)) = (uint32_t)size; + + memset((char*)(_buffer.data() + _buffer.offset() + fbe_map_offset + 4), 0, fbe_map_size); + + return std::make_pair(FieldModel(_buffer, fbe_map_offset + 4), FieldModel(_buffer, fbe_map_offset + 4 + fbe_model_key.fbe_size())); +} + +template +inline bool FieldModelMap::verify() const noexcept +{ + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return true; + + uint32_t fbe_map_offset = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_offset())); + if (fbe_map_offset == 0) + return true; + + if ((_buffer.offset() + fbe_map_offset + 4) > _buffer.size()) + return false; + + uint32_t fbe_map_size = *((const uint32_t*)(_buffer.data() + _buffer.offset() + fbe_map_offset)); + + FieldModel fbe_model_key(_buffer, fbe_map_offset + 4); + FieldModel fbe_model_value(_buffer, fbe_map_offset + 4 + fbe_model_key.fbe_size()); + for (size_t i = fbe_map_size; i-- > 0;) + { + if (!fbe_model_key.verify()) + return false; + fbe_model_key.fbe_shift(fbe_model_key.fbe_size() + fbe_model_value.fbe_size()); + if (!fbe_model_value.verify()) + return false; + fbe_model_value.fbe_shift(fbe_model_key.fbe_size() + fbe_model_value.fbe_size()); + } + + return true; +} + +template +inline void FieldModelMap::get(std::map& values) const noexcept +{ + values.clear(); + + size_t fbe_map_size = size(); + if (fbe_map_size == 0) + return; + + auto fbe_model = (*this)[0]; + for (size_t i = fbe_map_size; i-- > 0;) + { + TKey key; + TValue value; + fbe_model.first.get(key); + fbe_model.second.get(value); + values.emplace(key, value); + fbe_model.first.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size()); + fbe_model.second.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size()); + } +} + +template +inline void FieldModelMap::get(std::unordered_map& values) const noexcept +{ + values.clear(); + + size_t fbe_map_size = size(); + if (fbe_map_size == 0) + return; + + auto fbe_model = (*this)[0]; + for (size_t i = fbe_map_size; i-- > 0;) + { + TKey key; + TValue value; + fbe_model.first.get(key); + fbe_model.second.get(value); + values.emplace(key, value); + fbe_model.first.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size()); + fbe_model.second.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size()); + } +} + +template +inline void FieldModelMap::set(const std::map& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + auto fbe_model = resize(values.size()); + for (const auto& value : values) + { + fbe_model.first.set(value.first); + fbe_model.first.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size()); + fbe_model.second.set(value.second); + fbe_model.second.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size()); + } +} + +template +inline void FieldModelMap::set(const std::unordered_map& values) noexcept +{ + assert(((_buffer.offset() + fbe_offset() + fbe_size()) <= _buffer.size()) && "Model is broken!"); + if ((_buffer.offset() + fbe_offset() + fbe_size()) > _buffer.size()) + return; + + auto fbe_model = resize(values.size()); + for (const auto& value : values) + { + fbe_model.first.set(value.first); + fbe_model.first.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size()); + fbe_model.second.set(value.second); + fbe_model.second.fbe_shift(fbe_model.first.fbe_size() + fbe_model.second.fbe_size()); + } +} + +} // namespace FBE