diff options
author | Claudius 'keldu' Holeksa <mail@keldu.de> | 2024-07-30 16:56:29 +0200 |
---|---|---|
committer | Claudius 'keldu' Holeksa <mail@keldu.de> | 2024-07-30 16:56:29 +0200 |
commit | d5bf26c38a28bfe114511375ed125505f8325514 (patch) | |
tree | e7c29d2ee6aa58f9a30ff60ffe75aa71a2c93eef /modules/codec/c++/data_raw.hpp | |
parent | 718ed6a0a59c1f0869488ae725edc453e86b355b (diff) |
wip for managing the raw data in a native format
Diffstat (limited to 'modules/codec/c++/data_raw.hpp')
-rw-r--r-- | modules/codec/c++/data_raw.hpp | 478 |
1 files changed, 478 insertions, 0 deletions
diff --git a/modules/codec/c++/data_raw.hpp b/modules/codec/c++/data_raw.hpp new file mode 100644 index 0000000..3081423 --- /dev/null +++ b/modules/codec/c++/data_raw.hpp @@ -0,0 +1,478 @@ +#pragma once + +#include "data.hpp" + +namespace saw { +namespace encode { +struct NativeRaw { + static constexpr string_literal name = "encode::NativeRaw"; +}; +} + +template<> +class data<schema::Void, encode::NativeRaw> { +public: + using Schema = schema::Void; + using MetaSchema = schema::Void; +}; + +template<> +class data<schema::Bool, encode::NativeRaw> { +public: + using Schema = schema::Bool; + using MetaSchema = schema::Void; +private: + bool value_; +public: + data():value_{false}{} + data(data<MetaSchema, encode::NativeRaw>):value_{false}{} + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + void set(bool val){ + value_ = val; + } + + bool get() const { + return value_; + } +}; + +template<typename T, size_t N> +class data<schema::Primitive<T,N>, encode::NativeRaw> { +public: + using Schema = schema::Primitive<T,N>; + using MetaSchema = typename meta_schema<Schema>::MetaSchema; +private: + typename native_data_type<Schema>::type value_; +public: + data():value_{}{} + data(data<MetaSchema, encode::NativeRaw>):value_{}{} + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + data(typename native_data_type<Schema>::type value__): + value_{std::move(value__)}{} + + void set(typename native_data_type<Schema>::type val){ + value_ = val; + } + + typename native_data_type<Schema>::type get() const {return value_;} + + data<Schema, encode::NativeRaw> operator*(const data<Schema, encode::NativeRaw>& rhs)const{ + return {get() * rhs.get()}; + } + + data<Schema, encode::NativeRaw> operator/(const data<Schema, encode::NativeRaw>& rhs)const{ + return {get() / rhs.get()}; + } + + data<Schema, encode::NativeRaw> operator+(const data<Schema, encode::NativeRaw>& rhs)const{ + return {get() + rhs.get()}; + } + + data<Schema, encode::NativeRaw>& operator+=(const data<Schema, encode::NativeRaw>& rhs)const{ + value_ += rhs.get(); + return *this; + } + + data<Schema, encode::NativeRaw>& operator-=(const data<Schema, encode::NativeRaw>& rhs)const{ + value_ -= rhs.get(); + return *this; + } + + data<Schema, encode::NativeRaw> operator-(const data<Schema, encode::NativeRaw>& rhs)const{ + return {get() - rhs.get()}; + } + + template<typename Enc> + bool operator==(const data<Schema, Enc>& rhs)const{ + return get() == rhs.get(); + } + + template<typename Enc> + bool operator<(const data<Schema, Enc>& rhs) const { + return get() < rhs.get(); + } + + /** + * Casts + */ + template<typename Target> + data<Target, encode::NativeRaw> cast_to() const { + auto raw_to = static_cast<typename saw::native_data_type<Target>::type>(value_); + return {raw_to}; + } +}; + +/** + * Mixed precision class for native formats + */ +template<typename TA, uint64_t NA, typename TB, uint64_t NB> +class data<schema::MixedPrecision<schema::Primitive<TA,NA>, schema::Primitive<TB,NB>>, encode::NativeRaw>{ +public: + using Schema = schema::MixedPrecision<schema::Primitive<TA,NA>, schema::Primitive<TB,NB>>; + using MetaSchema = typename meta_schema<Schema>::MetaSchema; +private: + data<typename Schema::StorageSchema, encode::NativeRaw> value_; +public: + data():value_{}{} + data(data<MetaSchema, encode::NativeRaw>):value_{}{} + + data(typename saw::native_data_type<typename Schema::InterfaceSchema>::type val__):value_{static_cast<typename saw::native_data_type<typename Schema::StorageSchema>::type>(val__)}{} + + typename saw::native_data_type<typename Schema::InterfaceSchema>::type get() const { + return value_.template cast_to<typename Schema::InterfaceSchema>().get(); + } + + data(const saw::data<typename Schema::InterfaceSchema, encode::NativeRaw>& val){ + value_ = val.template cast_to<typename Schema::StorageSchema>(); + } + + void set(typename saw::native_data_type<typename Schema::InterfaceSchema>::type val){ + value_.set(static_cast<typename Schema::StorageSchema>(val)); + } + + data<Schema, encode::NativeRaw> operator*(const data<Schema, encode::NativeRaw>& rhs) const { + using CalcType = typename native_data_type<typename Schema::InterfaceSchema>::type; + CalcType left = static_cast<CalcType>(value_.get()); + CalcType right = static_cast<CalcType>(rhs.get()); + return {left * right}; + } + + data<typename Schema::InterfaceSchema, encode::NativeRaw> operator*(const data<typename Schema::InterfaceSchema, encode::NativeRaw>& rhs) const { + using CalcType = typename native_data_type<typename Schema::InterfaceSchema>::type; + CalcType left = static_cast<CalcType>(value_.get()); + CalcType right = rhs.get(); + return {left * right}; + } + + data<typename Schema::InterfaceSchema, encode::NativeRaw> operator/(const data<Schema, encode::NativeRaw>& rhs)const{ + using CalcType = typename native_data_type<typename Schema::InterfaceSchema>::type; + CalcType left = static_cast<CalcType>(value_.get()); + CalcType right = static_cast<CalcType>(rhs.get()); + return {left / right}; + } + + data<typename Schema::InterfaceSchema, encode::NativeRaw> operator+(const data<Schema, encode::NativeRaw>& rhs)const{ + using CalcType = typename native_data_type<typename Schema::InterfaceSchema>::type; + CalcType left = static_cast<CalcType>(value_.get()); + CalcType right = static_cast<CalcType>(rhs.get()); + return {left + right}; + } + + data<Schema, encode::NativeRaw>& operator+=(const data<Schema, encode::NativeRaw>& rhs)const{ + *this = *this + rhs.get(); + return *this; + } + + data<typename Schema::InterfaceSchema, encode::NativeRaw> operator-(const data<Schema, encode::NativeRaw>& rhs)const{ + using CalcType = typename native_data_type<typename Schema::InterfaceSchema>::type; + CalcType left = static_cast<CalcType>(value_.get()); + CalcType right = static_cast<CalcType>(rhs.get()); + return {left - right}; + } + + data<Schema, encode::NativeRaw>& operator-=(const data<Schema, encode::NativeRaw>& rhs) const { + *this = *this - rhs.get(); + return *this; + } + + template<typename Enc> + bool operator==(const data<Schema, Enc>& rhs)const{ + return get() == rhs.get(); + } + + template<typename Enc> + bool operator<(const data<Schema, Enc>& rhs) const { + return get() < rhs.get(); + } +}; + +/** + * Data class which represents a struct in the native format. + */ +template<typename... T, string_literal... literals> +class data<schema::Struct<schema::Member<T, literals>...>, encode::NativeRaw, storage::Default> { +public: + using Schema = schema::Struct<schema::Member<T,literals>...>; + using MetaSchema = typename meta_schema<Schema>::MetaSchema; +private: + /** + * Tuple storing the member values. + */ + std::tuple<data<T,encode::NativeRaw, storage::Default>...> value_; + + template<uint64_t i = 0u> + struct init_helper { + static void apply(std::tuple<data<T,encode::NativeRaw,storage::Default>...>& val, data<Schema, encode::NativeRaw>&& init){ + auto& val_i = val.template get<i>(); + auto& init_i = init.template get<i>(); + + val_i = {std::move(init_i)}; + + if constexpr ( (i+1u) < sizeof...(T) ){ + init_helper<i+1u>::apply(val, init); + } + } + }; +public: + /** + * Default constructor. + */ + data() = default; + data(data<MetaSchema, encode::NativeRaw> init){ + if constexpr ( 0u < sizeof...(T) ){ + init_helper<0u>::apply(value_, std::move(init)); + } + } + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + /** + * Get the member value based on the string_literal. + */ + template<string_literal literal> + data< + typename parameter_pack_type< + parameter_key_pack_index< + literal, literals... + >::value + , T...>::type + , encode::NativeRaw, storage::Default>& get(){ + return std::get<parameter_key_pack_index<literal, literals...>::value>(value_); + } + + /** + * Get the member value based on the string_literal. + */ + template<string_literal literal> + const data< + typename parameter_pack_type< + parameter_key_pack_index< + literal, literals... + >::value + , T...>::type + , encode::NativeRaw, storage::Default>& get() const { + return std::get<parameter_key_pack_index<literal, literals...>::value>(value_); + } + + /** + * Return the amount of members. + */ + constexpr size_t size() const { + return sizeof...(T); + } +}; + +template<typename... T> +class data<schema::Tuple<T...>, encode::NativeRaw, storage::Default> { +public: + using Schema = schema::Tuple<T...>; + using MetaSchema = typename meta_schema<Schema>::MetaSchema; +private: + std::tuple<data<T,encode::NativeRaw, storage::Default>...> value_; + + template<uint64_t i = 0u> + struct init_helper { + static void apply(std::tuple<data<T,encode::NativeRaw,storage::Default>...>& val, data<MetaSchema, encode::NativeRaw>&& init){ + auto& val_i = val.template get<i>(); + auto& init_i = init.template get<i>(); + + val_i = {std::move(init_i)}; + + if constexpr ( (i+1u) < sizeof...(T) ){ + init_helper<i+1u>::apply(val, init); + } + } + }; +public: + data() = default; + data(data<MetaSchema, encode::NativeRaw> init){ + if constexpr ( 0u < sizeof...(T) ){ + init_helper<0u>::apply(value_, std::move(init)); + } + } + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + template<size_t i> + data<typename parameter_pack_type<i,T...>::type, encode::NativeRaw, storage::Default>& get(){ + return std::get<i>(value_); + } + + template<size_t i> + const data<typename parameter_pack_type<i,T...>::type, encode::NativeRaw, storage::Default>& get() const{ + return std::get<i>(value_); + } + + constexpr size_t size() const { + return sizeof...(T); + } +}; + +template<typename T, size_t Dim> +class data<schema::Array<T,Dim>, encode::NativeRaw, storage::Default> { + public: + using Schema = schema::Array<T,Dim>; + using MetaSchema = typename meta_schema<Schema>::MetaSchema; + private: + // data<schema::FixedArray<schema::UInt64, Dim>> dims_; + std::array<uint64_t, Dim> dims_; + std::vector< + std::conditional< + is_primitive<Schema>::value, + typename native_data_type<Schema>::type, + data<T, encode::NativeRaw, storage::Default> + > + > value_; + + uint64_t get_full_size() const { + uint64_t s = 1; + + for(uint64_t iter = 0; iter < Dim; ++iter){ + assert(dims_.at(iter) > 0); + s *= dims_.at(iter); + } + + return s; + } + public: + data(): + value_{} + { + for(auto& iter : dims_){ + iter = 0u; + } + } + + SAW_DEFAULT_COPY(data); + SAW_DEFAULT_MOVE(data); + + data(const std::array<uint64_t, Dim>& i): + dims_{i}, + value_{} + { + value_.resize(get_full_size()); + } + + data(data<MetaSchema, encode::NativeRaw> init) + { + for(uint64_t i = 0; i < Dim; ++i){ + dims_.at(i) = init.at(i).get(); + } + value_.resize(get_full_size()); + } + + template<size_t i = 0> + error_or<void> add(saw::data<T,encode::NativeRaw, storage::Default> data){ + /** @todo + * Generally the last dimension can always accept a element so to say. + * Changing the others would require moving data due to the stride changing. + * Since the last dimension doesn't affect the stride, we don't need reordering there. + * But I want a quick solution for one dimension so here we are. + * + * I can always ignore strides and use a stacked std::vector + * std::vector<std::vector<...>> and so on. + * But for now I'm keeping the strides. Smaller chunks of memory aren't to bad either + * though. + * I'll probably change it to the smaller chunks + */ + static_assert(Dim == 1, "Currently can't deal with higher dims"); + static_assert(i < Dim, "Can't add to dimension. Index i larger than dimension size"); + + try { + value_.emplace_back(std::move(data)); + }catch(const std::exception& e){ + (void) e; + return make_error<err::out_of_memory>(); + } + + ++dims_.at(i); + + return void_t{}; + } + + template<std::integral... Dims> + data(Dims... size_): + data{{static_cast<uint64_t>(size_)...}} + { + static_assert(sizeof...(Dims)==Dim, "Argument size must be equal to the Dimension"); + } + + data<T, encode::NativeRaw, storage::Default>& at(const std::array<uint64_t, Dim>& ind){ + return value_.at(this->get_flat_index(ind)); + } + + const data<T, encode::NativeRaw, storage::Default>& at(const std::array<uint64_t, Dim>& ind) const { + return value_.at(this->get_flat_index(ind)); + } + + template<std::integral... Dims> + data<T, encode::NativeRaw, storage::Default>& at(Dims... i){ + return value_.at(this->get_flat_index(std::array<uint64_t, Dim>{static_cast<uint64_t>(i)...})); + } + + template<std::integral... Dims> + const data<T, encode::NativeRaw, storage::Default>& at(Dims... i) const { + return value_.at(this->get_flat_index(std::array<uint64_t, Dim>{static_cast<uint64_t>(i)...})); + } + + data<T,encode::NativeRaw, storage::Default>& at(const data<schema::FixedArray<schema::UInt64,Dim>>& i){ + return value_.at(this->get_flat_index(i)); + } + + const data<T,encode::NativeRaw, storage::Default>& at(const data<schema::FixedArray<schema::UInt64,Dim>>& i)const{ + return value_.at(this->get_flat_index(i)); + } + + std::size_t get_dim_size(uint64_t i) const { + return dims_.at(i); + } + + size_t size() const { return value_.size();} + + data<schema::FixedArray<schema::UInt64, Dim>> get_dims() const { + return {dims_}; + } + +private: + template<typename U> + uint64_t get_flat_index(const U& i) const { + static_assert( + std::is_same_v<U,data<schema::FixedArray<schema::UInt64,Dim>>> or + std::is_same_v<U,std::array<uint64_t,Dim>>, + "Unsupported type" + ); + assert(value_.size() == get_full_size()); + uint64_t s = 0; + + uint64_t stride = 1; + + for(uint64_t iter = 0; iter < Dim; ++iter){ + uint64_t ind = [](auto val) -> uint64_t { + using V = std::decay_t<decltype(val)>; + if constexpr (std::is_same_v<V,data<schema::UInt64>>){ + return val.get(); + }else if constexpr (std::is_same_v<V, uint64_t>){ + return val; + }else{ + static_assert(always_false<V>, "Cases exhausted"); + } + }(i.at(iter)); + assert(ind < dims_.at(iter)); + s += ind * stride; + stride *= dims_.at(iter); + } + + return s; + } +}; + + +} |