diff options
Diffstat (limited to 'modules/codec-netcdf/c++/netcdf.h')
-rw-r--r-- | modules/codec-netcdf/c++/netcdf.h | 151 |
1 files changed, 151 insertions, 0 deletions
diff --git a/modules/codec-netcdf/c++/netcdf.h b/modules/codec-netcdf/c++/netcdf.h new file mode 100644 index 0000000..52ad494 --- /dev/null +++ b/modules/codec-netcdf/c++/netcdf.h @@ -0,0 +1,151 @@ +#pragma once + +#include <forstio/string_literal.h> +#include <forstio/error.h> +#include <forstio/codec/data.h> + +#include <netcdf.h> +#include <netcdf_mem.h> + +namespace saw { +namespace encode { +/** + * Template type hint + */ +struct Netcdf {}; +} + +/** + * Class representing the files system netcdf file + */ +template<typename Schema> +class data<Schema, encode::Netcdf> { +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::Netcdf>{ + static_assert(always_false<Schema,encode::Netcdf>, "NetCDF only supports Structs as a root object"); +}; + +} +#include "netcdf.tmpl.h" +namespace saw { + +template<typename... Vals, string_literal... Keys> +class codec<schema::Struct<schema::Member<Vals,Keys>...>, encode::Netcdf> { +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::Netcdf>& 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::Netcdf>& 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; + } +}; +} |