summaryrefslogtreecommitdiff
path: root/modules/codec-vtk/c++
diff options
context:
space:
mode:
Diffstat (limited to 'modules/codec-vtk/c++')
-rw-r--r--modules/codec-vtk/c++/SConscript38
-rw-r--r--modules/codec-vtk/c++/netcdf.hpp148
-rw-r--r--modules/codec-vtk/c++/netcdf.tmpl.hpp348
3 files changed, 534 insertions, 0 deletions
diff --git a/modules/codec-vtk/c++/SConscript b/modules/codec-vtk/c++/SConscript
new file mode 100644
index 0000000..6d8866b
--- /dev/null
+++ b/modules/codec-vtk/c++/SConscript
@@ -0,0 +1,38 @@
+#!/bin/false
+
+import os
+import os.path
+import glob
+
+
+Import('env')
+
+dir_path = Dir('.').abspath
+
+# Environment for base library
+codec_netcdf_env = env.Clone();
+
+codec_netcdf_env.sources = sorted(glob.glob(dir_path + "/*.cpp"))
+codec_netcdf_env.headers = sorted(glob.glob(dir_path + "/*.hpp"))
+
+env.sources += codec_netcdf_env.sources;
+env.headers += codec_netcdf_env.headers;
+
+## Shared lib
+objects_shared = []
+codec_netcdf_env.add_source_files(objects_shared, codec_netcdf_env.sources, shared=True);
+env.library_shared = codec_netcdf_env.SharedLibrary('#build/forstio-codec-netcdf', [objects_shared]);
+
+## Static lib
+objects_static = []
+codec_netcdf_env.add_source_files(objects_static, codec_netcdf_env.sources, shared=False);
+env.library_static = codec_netcdf_env.StaticLibrary('#build/forstio-codec-netcdf', [objects_static]);
+
+# Set Alias
+env.Alias('library_codec_netcdf', [env.library_shared, env.library_static]);
+
+env.targets += ['library_codec_netcdf'];
+
+# Install
+env.Install('$prefix/lib/', [env.library_shared, env.library_static]);
+env.Install('$prefix/include/forstio/codec/netcdf/', [codec_netcdf_env.headers]);
diff --git a/modules/codec-vtk/c++/netcdf.hpp b/modules/codec-vtk/c++/netcdf.hpp
new file mode 100644
index 0000000..2c0a786
--- /dev/null
+++ b/modules/codec-vtk/c++/netcdf.hpp
@@ -0,0 +1,148 @@
+#pragma once
+
+#include <forstio/string_literal.hpp>
+#include <forstio/error.hpp>
+#include <forstio/codec/data.hpp>
+
+namespace saw {
+namespace encode {
+/**
+ * Template type hint
+ */
+struct VtkLegacy {};
+}
+
+/**
+ * Class representing the files system netcdf file
+ */
+template<typename Schema>
+class data<Schema, encode::VtkLegacy> {
+private:
+ std::vector<uint8_t> buff_;
+public:
+ data() = default;
+
+ data(std::vector<uint8_t> buff):
+ buff_{std::move(buff)}
+ {}
+
+ template<size_t N>
+ data(const std::array<uint8_t, N>& arr):
+ buff_{arr.begin(), arr.end()}
+ {}
+
+ std::vector<uint8_t>& get_data() {
+ return buff_;
+ }
+
+ const std::vector<uint8_t>& get_data() const {
+ return buff_;
+ }
+};
+
+template<typename Schema>
+class codec<Schema, encode::VtkLegacy>{
+ static_assert(always_false<Schema,encode::VtkLegacy>, "NetCDF only supports Structs as a root object");
+};
+
+}
+#include "vtk.tmpl.hpp"
+namespace saw {
+
+template<typename... Vals, string_literal... Keys>
+class codec<schema::Struct<schema::Member<Vals,Keys>...>, encode::VtkLegacy> {
+private:
+ using Schema = schema::Struct<schema::Member<Vals,Keys>...>;
+public:
+ SAW_FORBID_COPY(codec);
+ SAW_DEFAULT_MOVE(codec);
+
+ /**
+ * Default constructor
+ */
+ codec() = default;
+
+ /**
+ * Encoder function
+ */
+ template<typename FromEncoding>
+ error_or<void> encode(const data<Schema, FromEncoding>& from, data<Schema,encode::VtkLegacy>& to) {
+ int rc{};
+ int ncid{};
+
+ rc = nc_create_mem("forstio_internal_write_memory", 0,/*NC_NETCDF4, */0, &ncid);
+ if(rc != NC_NOERR){
+ return make_error<err::critical>();
+ }
+
+ {
+ auto eov = impl::netcdf_encode<Schema,FromEncoding>::encode_meta(from, ncid);
+ if(eov.is_error()){
+ nc_close(ncid);
+ return eov;
+ }
+ }
+
+ rc = nc_enddef(ncid);
+ if(rc != NC_NOERR){
+ nc_close(ncid);
+ return make_error<err::critical>();
+ }
+
+ {
+ auto eov = impl::netcdf_encode<Schema,FromEncoding>::encode(from, ncid);
+ if(eov.is_error()){
+ nc_close(ncid);
+ return eov;
+ }
+ }
+
+ NC_memio nc_memio;
+ rc = nc_close_memio(ncid, &nc_memio);
+ if(rc != NC_NOERR){
+ return make_error<err::critical>();
+ }
+
+ if(!nc_memio.memory || nc_memio.size == 0){
+ return make_error<err::critical>();
+ }
+
+ try {
+ to.get_data().resize(nc_memio.size);
+ }catch(const std::exception& e){
+ (void) e;
+ return make_error<err::out_of_memory>();
+ }
+
+ for(std::size_t i = 0; i < nc_memio.size; ++i){
+ to.get_data().at(i) = static_cast<uint8_t*>(nc_memio.memory)[i];
+ }
+
+ free(nc_memio.memory);
+ nc_memio.memory = nullptr;
+
+ return void_t{};
+ }
+
+ /**
+ * Decoder function
+ */
+ template<typename ToEncoding>
+ error_or<void> decode(data<Schema, encode::VtkLegacy>& from_decode, data<Schema,ToEncoding>& to_decode) {
+ int ncid{};
+ int rc{};
+
+ rc = nc_open_mem("forstio_internal_read_memory", NC_NOWRITE, from_decode.get_data().size(), &from_decode.get_data()[0], &ncid);
+ if(rc != NC_NOERR){
+ // Don't know how to get the error, so fail critically.
+ return make_error<err::critical>();
+ }
+
+ auto eov = impl::netcdf_decode<Schema, ToEncoding>::decode(to_decode, ncid);
+
+ nc_close(ncid);
+
+ return eov;
+ }
+};
+}
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{};
+ }
+};
+}
+}