#pragma once #include #include #include #include #include namespace saw { namespace encode { /** * Template type hint */ struct Netcdf {}; } /** * Class representing the files system netcdf file */ template class data { private: std::vector buff_; public: data() = default; data(std::vector buff): buff_{std::move(buff)} {} template data(const std::array& arr): buff_{arr.begin(), arr.end()} {} std::vector& get_data() { return buff_; } const std::vector& get_data() const { return buff_; } }; template class codec{ static_assert(always_false, "NetCDF only supports Structs as a root object"); }; } #include "netcdf.tmpl.hpp" namespace saw { template class codec...>, encode::Netcdf> { private: using Schema = schema::Struct...>; public: SAW_FORBID_COPY(codec); SAW_DEFAULT_MOVE(codec); /** * Default constructor */ codec() = default; /** * Encoder function */ template error_or encode(const data& from, data& 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(); } { auto eov = impl::netcdf_encode::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(); } { auto eov = impl::netcdf_encode::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(); } if(!nc_memio.memory || nc_memio.size == 0){ return make_error(); } try { to.get_data().resize(nc_memio.size); }catch(const std::exception& e){ (void) e; return make_error(); } for(std::size_t i = 0; i < nc_memio.size; ++i){ to.get_data().at(i) = static_cast(nc_memio.memory)[i]; } free(nc_memio.memory); nc_memio.memory = nullptr; return void_t{}; } /** * Decoder function */ template error_or decode(data& from_decode, data& 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(); } auto eov = impl::netcdf_decode::decode(to_decode, ncid); nc_close(ncid); return eov; } }; }