diff options
Diffstat (limited to 'modules/codec-vtk/c++/netcdf.hpp')
-rw-r--r-- | modules/codec-vtk/c++/netcdf.hpp | 148 |
1 files changed, 148 insertions, 0 deletions
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; + } +}; +} |