diff options
Diffstat (limited to 'modules/codec-vtk/c++/netcdf.tmpl.hpp')
-rw-r--r-- | modules/codec-vtk/c++/netcdf.tmpl.hpp | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/modules/codec-vtk/c++/netcdf.tmpl.hpp b/modules/codec-vtk/c++/netcdf.tmpl.hpp new file mode 100644 index 0000000..bf257e4 --- /dev/null +++ b/modules/codec-vtk/c++/netcdf.tmpl.hpp @@ -0,0 +1,348 @@ +#pragma once + +namespace saw { +namespace impl { +template<typename Schema> +struct netcdf_primitive_id { + static_assert(always_false<Schema>, "Not a primitive id"); +}; + +template<> +struct netcdf_primitive_id<schema::Int32> { + static constexpr nc_type value = NC_INT; +}; + +template<> +struct netcdf_primitive_id<schema::UInt32> { + static constexpr nc_type value = NC_UINT; +}; + +template<> +struct netcdf_primitive_id<schema::Int64> { + static constexpr nc_type value = NC_INT64; +}; + +template<> +struct netcdf_primitive_id<schema::UInt64> { + static constexpr nc_type value = NC_UINT64; +}; + +template<> +struct netcdf_primitive_id<schema::Float32> { + static constexpr nc_type value = NC_FLOAT; +}; + +template<> +struct netcdf_primitive_id<schema::Float64> { + static constexpr nc_type value = NC_DOUBLE; +}; + +template<typename Schema> +struct netcdf_is_group { + static constexpr bool value = false; +}; + +template<typename... T, string_literal... Lits> +struct netcdf_is_group<schema::Struct<schema::Member<T,Lits>...>> { + static constexpr bool value = true; +}; + +template<typename Schema, typename ToEncode> +struct netcdf_encode; + +template<typename T, size_t N, typename ToEncode> +struct netcdf_encode<schema::Primitive<T,N>, ToEncode> { + using Schema = schema::Primitive<T,N>; + + static error_or<void> encode(const data<Schema, ToEncode>& from, int ncid, int ncvarid){ + int rc{}; + + typename native_data_type<Schema>::type val = from.get(); + + rc = nc_put_var(ncid, ncvarid, &val); + if(rc != NC_NOERR) { + return make_error<err::critical>(); + } + + return void_t{}; + } + + static error_or<void> encode_meta(const data<Schema, ToEncode>& from, int ncid, int ncvarid){ + (void) from; + (void) ncid; + (void) ncvarid; + return void_t{}; + } +}; + +template<typename T, size_t Dim, typename ToEncode> +struct netcdf_encode<schema::Array<T,Dim>, ToEncode> { + using Schema = schema::Array<T,Dim>; + + template<size_t Level> + static error_or<void> encode_level(data<Schema,ToEncode>& from, int ncid, int ncvarid){ + + return make_error<err::not_implemented>(); + } + + static error_or<void> encode(data<Schema, ToEncode>& from, int ncid, int ncvarid){ + + return make_error<err::not_implemented>(); + } + + static error_or<void> encode_meta(const data<Schema, ToEncode>& from, int ncid, int ncvarid){ + + return make_error<err::not_implemented>(); + } +}; + +template<typename... T, string_literal... Lits, typename ToEncode> +struct netcdf_encode<schema::Struct<schema::Member<T,Lits>...>, ToEncode> { + using Schema = schema::Struct<schema::Member<T,Lits>...>; + + template<std::size_t i> + static error_or<void> encode_member(const data<Schema, ToEncode>& from, int ncid){ + using Type = typename parameter_pack_type<i,T...>::type; + constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; + { + /** + * We have to ask for the internal id of the netcdf structure + */ + if constexpr (netcdf_is_group<Type>::value){ + return make_error<err::not_implemented>(); + }else{ + int nc_varid{}; + int rc {}; + rc = nc_inq_varid(ncid, Literal.data.data(), &nc_varid); + if(rc != NC_NOERR) { + return make_error<err::critical>(); + } + auto eov = netcdf_encode<Type, ToEncode>::encode(from.template get<Literal>(), ncid, nc_varid); + if(eov.is_error()){ + return eov; + } + } + + } + if constexpr ((i+1) < sizeof...(T)){ + auto eov = encode_member<i+1>(from, ncid); + if(eov.is_error()){ + return eov; + } + } + + return void_t{}; + } + + static error_or<void> encode(const data<Schema, ToEncode>& from, int ncid){ + if constexpr (sizeof...(T) > 0){ + auto eov = encode_member<0>(from, ncid); + return eov; + } + + return void_t{}; + } + + template<std::size_t i> + static error_or<void> encode_meta_member(const data<Schema, ToEncode>& from, int ncid){ + using Type = typename parameter_pack_type<i,T...>::type; + constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; + { + /** + * We have to ask for the internal id of the netcdf structure + */ + if constexpr (netcdf_is_group<Type>::value){ + return make_error<err::not_implemented>(); + }else{ + int nc_varid{}; + int rc {}; + rc = nc_def_var(ncid, Literal.data.data(), netcdf_primitive_id<Type>::value, 0, nullptr, &nc_varid); + if(rc != NC_NOERR) { + return make_error<err::critical>(); + } + auto eov = netcdf_encode<Type, ToEncode>::encode_meta(from.template get<Literal>(), ncid, nc_varid); + if(eov.is_error()){ + return eov; + } + } + + } + if constexpr ((i+1) < sizeof...(T)){ + auto eov = encode_meta_member<i+1>(from, ncid); + if(eov.is_error()){ + return eov; + } + } + + return void_t{}; + } + + static error_or<void> encode_meta(const data<Schema, ToEncode>& from, int ncid){ + if constexpr (sizeof...(T) > 0){ + auto eov = encode_meta_member<0>(from, ncid); + return eov; + } + + return void_t{}; + } +}; + +template<typename Schema, typename ToDecode> +struct netcdf_decode; + +template<typename T, size_t N, typename ToDecode> +struct netcdf_decode<schema::Primitive<T,N>, ToDecode> { + using Schema = schema::Primitive<T,N>; + + static error_or<void> decode(data<Schema, ToDecode>& to, int from, int nc_varid){ + int rc{}; + + nc_type nc_vartype{}; + int nc_dimnum{}; + std::array<int,NC_MAX_VAR_DIMS> nc_dimids; + + rc = nc_inq_var(from, nc_varid, nullptr, &nc_vartype, &nc_dimnum, &nc_dimids[0], nullptr); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + if(nc_vartype != netcdf_primitive_id<schema::Primitive<T,N>>::value){ + return make_error<err::critical>(); + } + if(nc_dimnum != 0){ + return make_error<err::critical>(); + } + + typename native_data_type<schema::Primitive<T,N>>::type val{}; + rc = nc_get_var(from, nc_varid, &val); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + + to.set(val); + + return void_t {}; + } +}; + +template<typename T, size_t Dim, typename ToDecode> +struct netcdf_decode<schema::Array<T,Dim>, ToDecode> { + using Schema = schema::Array<T,Dim>; + + template<std::size_t Level> + static error_or<void> decode_level(data<Schema, ToDecode>& to, int from, int nc_varid, std::array<std::size_t, Dim>& index, const std::array<size_t,Dim>& count){ + if constexpr ( Level == Dim ){ + int rc{}; + typename native_data_type<T>::type val; + rc = nc_get_vara(from, nc_varid, index.data(), count.data(), &val); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + to.at(index).set(val); + }else{ + const std::size_t dim_size = to.get_dim_size(Level); + for(index[Level] = 0; index[Level] < dim_size; ++index[Level]){ + auto eov = decode_level<Level+1>(to, from, nc_varid, index, count); + if(eov.is_error()){ + return eov; + } + } + } + + return void_t{}; + } + + static error_or<void> decode(data<Schema, ToDecode>& to, int from, int nc_varid){ + int rc{}; + + nc_type nc_vartype{}; + + int nc_dimnum{}; + std::array<int, NC_MAX_VAR_DIMS> nc_dimids; + + rc = nc_inq_var(from, nc_varid, nullptr, &nc_vartype, &nc_dimnum, &nc_dimids[0], nullptr); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + if(nc_vartype != netcdf_primitive_id<T>::value){ + return make_error<err::critical>(); + } + if(nc_dimnum != Dim){ + return make_error<err::critical>(); + } + + std::array<std::size_t, Dim> dims; + std::array<size_t, Dim> count; + for(std::size_t i = 0; i < Dim; ++i){ + rc = nc_inq_dim(from, nc_dimids[i], nullptr, &dims[i]); + if(rc != NC_NOERR){ + return make_error<err::critical>(); + } + count[i] = 1; + } + + to = {dims}; + std::array<std::size_t, Dim> index; + + return decode_level<0>(to, from, nc_varid, index, count); + } +}; + +template<typename... T, string_literal... Lits, typename ToDecode> +struct netcdf_decode<schema::Struct<schema::Member<T,Lits>...>, ToDecode> { + using Schema = schema::Struct<schema::Member<T,Lits>...>; + + template<std::size_t i> + static error_or<void> decode_member(data<Schema,ToDecode>& to, int from){ + using Type = typename parameter_pack_type<i,T...>::type; + constexpr string_literal Literal = parameter_key_pack_type<i, Lits...>::literal; + { + /** + * We have to ask for the internal id of the netcdf structure + */ + if constexpr (netcdf_is_group<Type>::value){ + int nc_group_id{}; + int rc {}; + rc = nc_inq_ncid(from, Literal.data.data(), &nc_group_id); + if(rc != NC_NOERR) { + return make_error<err::critical>(); + } + auto eov = netcdf_decode<Type, ToDecode>::decode(to.template get<Literal>(), nc_group_id); + if(eov.is_error()){ + return eov; + } + }else{ + int nc_varid{}; + int rc {}; + rc = nc_inq_varid(from, Literal.data.data(), &nc_varid); + if(rc != NC_NOERR) { + return make_error<err::critical>(); + } + auto eov = netcdf_decode<Type, ToDecode>::decode(to.template get<Literal>(), from, nc_varid); + if(eov.is_error()){ + return eov; + } + } + + } + if constexpr ((i+1) < sizeof...(T)){ + auto eov = decode_member<i+1>(to, from); + if(eov.is_error()){ + return eov; + } + } + + return void_t{}; + } + + + static error_or<void> decode(data<Schema, ToDecode>& to, int from){ + if constexpr (sizeof...(T) > 0){ + auto eov = decode_member<0>(to, from); + return eov; + } + + return void_t{}; + } +}; +} +} |