summaryrefslogtreecommitdiff
path: root/modules/codec/c++/data.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/codec/c++/data.hpp')
-rw-r--r--modules/codec/c++/data.hpp451
1 files changed, 451 insertions, 0 deletions
diff --git a/modules/codec/c++/data.hpp b/modules/codec/c++/data.hpp
new file mode 100644
index 0000000..3aebc89
--- /dev/null
+++ b/modules/codec/c++/data.hpp
@@ -0,0 +1,451 @@
+#pragma once
+
+#include <forstio/common.h>
+#include <forstio/error.h>
+#include <forstio/templates.h>
+
+#include <cassert>
+
+#include <array>
+#include <concepts>
+#include <variant>
+#include <vector>
+
+#include "schema.hpp
+
+namespace saw {
+namespace encode {
+struct Native {};
+}
+template<typename Schema, typename Encode>
+class codec;
+/*
+ * Helper for the basic message container, so the class doesn't have to be
+ * specialized 10 times.
+ */
+template <class T> struct native_data_type;
+
+template <>
+struct native_data_type<schema::Primitive<schema::SignedInteger, 1>> {
+ using type = int8_t;
+};
+
+template <>
+struct native_data_type<schema::Primitive<schema::SignedInteger, 2>> {
+ using type = int16_t;
+};
+
+template <>
+struct native_data_type<schema::Primitive<schema::SignedInteger, 4>> {
+ using type = int32_t;
+};
+
+template <>
+struct native_data_type<schema::Primitive<schema::SignedInteger, 8>> {
+ using type = int64_t;
+};
+
+template <>
+struct native_data_type<schema::Primitive<schema::UnsignedInteger, 1>> {
+ using type = uint8_t;
+};
+
+template <>
+struct native_data_type<schema::Primitive<schema::UnsignedInteger, 2>> {
+ using type = uint16_t;
+};
+
+template <>
+struct native_data_type<schema::Primitive<schema::UnsignedInteger, 4>> {
+ using type = uint32_t;
+};
+
+template <>
+struct native_data_type<schema::Primitive<schema::UnsignedInteger, 8>> {
+ using type = uint64_t;
+};
+
+template <>
+struct native_data_type<schema::Primitive<schema::FloatingPoint, 4>> {
+ using type = float;
+};
+
+template <>
+struct native_data_type<schema::Primitive<schema::FloatingPoint, 8>> {
+ using type = double;
+};
+
+template<typename T, typename Encoding = encode::Native>
+class data {
+private:
+ static_assert(always_false<T>, "Type not supported");
+};
+
+template<typename... T, string_literal... literals>
+class data<schema::Union<schema::Member<T, literals>...>, encode::Native> {
+private:
+ std::variant<data<T,encode::Native>...> value_;
+public:
+ data() = default;
+
+ SAW_DEFAULT_COPY(data);
+ SAW_DEFAULT_MOVE(data);
+
+ template<string_literal lit>
+ void set(data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native> val){
+ value_ = std::move(val);
+ }
+
+ template<string_literal lit>
+ data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>& init(){
+ value_ = data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>{};
+ return get<lit>();
+ }
+
+ template<string_literal lit>
+ bool holds_alternative() const {
+ return (parameter_key_pack_index<lit, literals...>::value == value_.index());
+ }
+
+ template<string_literal lit>
+ data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>& get(){
+ return std::get<parameter_key_pack_index<lit, literals...>::value>(value_);
+ }
+
+ template<string_literal lit>
+ const data<typename parameter_pack_type<parameter_key_pack_index<lit, literals...>::value, T...>::type, encode::Native>& get() const{
+ return std::get<parameter_key_pack_index<lit, literals...>::value>(value_);
+ }
+};
+
+template<typename... T, string_literal... literals>
+class data<schema::Struct<schema::Member<T, literals>...>, encode::Native> {
+private:
+ std::tuple<data<T,encode::Native>...> value_;
+public:
+ data() = default;
+ SAW_DEFAULT_COPY(data);
+ SAW_DEFAULT_MOVE(data);
+
+ template<string_literal literal>
+ data<
+ typename parameter_pack_type<
+ parameter_key_pack_index<
+ literal, literals...
+ >::value
+ , T...>::type
+ , encode::Native>& get(){
+ return std::get<parameter_key_pack_index<literal, literals...>::value>(value_);
+ }
+
+ template<string_literal literal>
+ const data<
+ typename parameter_pack_type<
+ parameter_key_pack_index<
+ literal, literals...
+ >::value
+ , T...>::type
+ , encode::Native>& get() const {
+ return std::get<parameter_key_pack_index<literal, literals...>::value>(value_);
+ }
+
+ constexpr size_t size() const {
+ return sizeof...(T);
+ }
+};
+
+template<typename... T>
+class data<schema::Tuple<T...>, encode::Native> {
+private:
+ std::tuple<data<T,encode::Native>...> value_;
+public:
+ data() = default;
+ SAW_DEFAULT_COPY(data);
+ SAW_DEFAULT_MOVE(data);
+
+ template<size_t i>
+ data<typename parameter_pack_type<i,T...>::type, encode::Native>& get(){
+ return std::get<i>(value_);
+ }
+
+ template<size_t i>
+ const data<typename parameter_pack_type<i,T...>::type, encode::Native>& 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::Native> {
+ private:
+ std::array<uint64_t, Dim> dims_;
+ std::vector<data<T, encode::Native>> 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() = default;
+ SAW_DEFAULT_COPY(data);
+ SAW_DEFAULT_MOVE(data);
+
+ data(const std::array<uint64_t, Dim>& i):
+ dims_{i},
+ value_{}
+ {
+ value_.resize(get_full_size());
+ }
+
+ template<size_t i = 0>
+ error_or<void> add(saw::data<T,encode::Native> 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<std::size_t>(size_)...}}
+ {
+ static_assert(sizeof...(Dims)==Dim, "Argument size must be equal to the Dimension");
+ }
+
+ data<T, encode::Native>& at(const std::array<std::size_t, Dim>& ind){
+ return value_.at(this->get_flat_index(ind));
+ }
+
+ const data<T, encode::Native>& at(const std::array<std::size_t, Dim>& ind) const {
+ return value_.at(this->get_flat_index(ind));
+ }
+
+ template<std::integral... Dims>
+ data<T, encode::Native>& at(Dims... i){
+ return value_.at(this->get_flat_index({static_cast<uint64_t>(i)...}));
+ }
+
+ template<std::integral... Dims>
+ const data<T, encode::Native>& at(Dims... i) const {
+ return value_.at(this->get_flat_index({static_cast<uint64_t>(i)...}));
+ }
+
+ data<T,encode::Native>& at(const data<schema::FixedArray<schema::UInt64,Dim>>& i){
+ return value_.at(this->get_flat_index(i));
+ }
+
+ const data<T,encode::Native>& at(const data<schema::FixedArray<schema::UInt64,Dim>>& i)const{
+ return value_.at(this->get_flat_index(i));
+ }
+
+ std::size_t get_dim_size(std::size_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:
+ uint64_t get_flat_index(const std::array<uint64_t, Dim>& i) const {
+ return get_flat_index(data<schema::FixedArray<schema::UInt64,Dim>>{i});
+ }
+
+ uint64_t get_flat_index(const data<schema::FixedArray<schema::UInt64,Dim>>& i) const {
+ uint64_t s = 0;
+
+ uint64_t stride = 1;
+
+ for(uint64_t iter = 0; iter < Dim; ++iter){
+ assert(i.at(iter).get() < dims_.at(iter));
+ s += i.at(iter).get() * stride;
+ stride *= dims_.at(iter);
+ }
+
+ return s;
+ }
+};
+
+template<typename T, uint64_t... D>
+class data<schema::FixedArray<T,D...>, encode::Native> {
+private:
+ //using inner_type = std::array<data<T, encode::Native>, multiply_helper<Dims...>::value>;
+ //std::unique_ptr<inner_type> value_;
+ using ArrayT = std::array<data<T, encode::Native>, ct_multiply<uint64_t, D...>::value>;
+ ArrayT value_;
+
+public:
+ data() = default;
+
+ data(const std::array<typename native_data_type<T>::type, ct_multiply<uint64_t, D...>::value>& data) requires (is_primitive<T>::value)
+ {
+ for(uint64_t i = 0; i < ct_multiply<uint64_t, D...>::value; ++i){
+ value_.at(i).set(data.at(i));
+ }
+ }
+
+ data<T, encode::Native>& at(const std::array<uint64_t, sizeof...(D)>& ind){
+ return value_.at(this->get_flat_index(ind));
+ }
+
+ const data<T, encode::Native>& at(const std::array<uint64_t, sizeof...(D)>& ind) const {
+ return value_.at(this->get_flat_index(ind));
+ }
+
+ template<std::integral... Dims>
+ data<T, encode::Native>& at(Dims... i) {
+ return value_.at(this->get_flat_index({i...}));
+ }
+
+ template<std::integral... Dims>
+ const data<T, encode::Native>& at(Dims... i) const {
+ return value_.at(this->get_flat_index({i...}));
+ }
+
+ data<T, encode::Native>& at(const data<schema::FixedArray<schema::UInt64, sizeof...(D)>>& i){
+ return value_.at(this->get_flat_index(i));
+ }
+
+ const data<T, encode::Native>& at(const data<schema::FixedArray<schema::UInt64, sizeof...(D)>>& i)const{
+ return value_.at(this->get_flat_index(i));
+ }
+
+ template<uint64_t i>
+ uint64_t get_dim_size() const {
+ return parameter_pack_value<i, uint64_t, D...>::value;
+ }
+
+ data<schema::FixedArray<schema::UInt64, sizeof...(D)>> get_dims() const {
+ return {std::array<uint64_t, sizeof...(D)>{D...}};
+ }
+private:
+ uint64_t get_flat_index(const std::array<uint64_t, sizeof...(D)>& i) const {
+ uint64_t s = 0;
+
+ uint64_t stride = 1;
+
+ constexpr static std::array<uint64_t, sizeof...(D)> dims_{D...};
+
+ for(uint64_t iter = 0; iter < sizeof...(D); ++iter){
+ assert(i.at(iter) < dims_.at(iter));
+ s += i.at(iter) * stride;
+ stride *= dims_.at(iter);
+ }
+
+ return s;
+ }
+};
+
+template<>
+class data<schema::String, encode::Native> {
+private:
+ std::string value_;
+public:
+ data() = default;
+ SAW_DEFAULT_COPY(data);
+ SAW_DEFAULT_MOVE(data);
+
+ data(std::string value__):value_{std::move(value__)}{}
+ data(std::size_t size_){
+ value_.resize(size_);
+ }
+
+ std::size_t size() const {
+ return value_.size();
+ }
+
+ void set(std::string str){
+ value_ = std::move(str);
+ }
+
+ char& at(size_t i) {
+ return value_.at(i);
+ }
+
+ const char& at(size_t i) const {
+ return value_.at(i);
+ }
+
+ char get_at(size_t i) const{
+ return value_.at(i);
+ }
+
+ void set_at(size_t i, char val){
+ value_.at(i) = val;
+ }
+
+ bool operator==(const std::string_view& val)const{
+ return value_ == val;
+ }
+};
+
+template<typename T, size_t N>
+class data<schema::Primitive<T,N>, encode::Native> {
+private:
+ typename native_data_type<schema::Primitive<T,N>>::type value_;
+public:
+ data():value_{}{}
+
+ SAW_DEFAULT_COPY(data);
+ SAW_DEFAULT_MOVE(data);
+
+ data(typename native_data_type<schema::Primitive<T,N>>::type value__):
+ value_{std::move(value__)}{}
+
+ void set(typename native_data_type<schema::Primitive<T,N>>::type val){
+ value_ = val;
+ }
+
+ typename native_data_type<schema::Primitive<T,N>>::type get() const {return value_;}
+
+ data<schema::Primitive<T,N>, encode::Native> operator*(const saw::data<schema::Primitive<T,N>, encode::Native>& rhs)const{
+ return {get() * rhs.get()};
+ }
+
+ data<schema::Primitive<T,N>, encode::Native> operator/(const saw::data<schema::Primitive<T,N>, encode::Native>& rhs)const{
+ return {get() / rhs.get()};
+ }
+
+ data<schema::Primitive<T,N>, encode::Native> operator+(const saw::data<schema::Primitive<T,N>, encode::Native>& rhs)const{
+ return {get() + rhs.get()};
+ }
+
+ data<schema::Primitive<T,N>, encode::Native> operator-(const saw::data<schema::Primitive<T,N>, encode::Native>& rhs)const{
+ return {get() - rhs.get()};
+ }
+};
+
+
+}