summaryrefslogtreecommitdiff
path: root/c++/codec-netcdf
diff options
context:
space:
mode:
Diffstat (limited to 'c++/codec-netcdf')
-rw-r--r--c++/codec-netcdf/netcdf.h62
-rw-r--r--c++/codec-netcdf/netcdf.tmpl.h156
2 files changed, 198 insertions, 20 deletions
diff --git a/c++/codec-netcdf/netcdf.h b/c++/codec-netcdf/netcdf.h
index 72e7614..cc9aedb 100644
--- a/c++/codec-netcdf/netcdf.h
+++ b/c++/codec-netcdf/netcdf.h
@@ -23,6 +23,8 @@ class data<Schema, encode::Netcdf> {
private:
std::vector<uint8_t> buff_;
public:
+ data() = default;
+
data(std::vector<uint8_t> buff):
buff_{std::move(buff)}
{}
@@ -67,8 +69,62 @@ public:
* Encoder function
*/
template<typename FromEncoding>
- error_or<void> encode() {
- return make_error<err::not_implemented>();
+ 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{};
}
/**
@@ -79,7 +135,7 @@ public:
int ncid{};
int rc{};
- rc = nc_open_mem("forstio_internal_memory", NC_NOWRITE, from_decode.get_data().size(), &from_decode.get_data()[0], &ncid);
+ 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>();
diff --git a/c++/codec-netcdf/netcdf.tmpl.h b/c++/codec-netcdf/netcdf.tmpl.h
index f3b36b8..00bfbf4 100644
--- a/c++/codec-netcdf/netcdf.tmpl.h
+++ b/c++/codec-netcdf/netcdf.tmpl.h
@@ -48,6 +48,125 @@ struct netcdf_is_group<schema::Struct<schema::Member<T,Lits>...>> {
};
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, 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>
@@ -160,24 +279,27 @@ struct netcdf_decode<schema::Struct<schema::Member<T,Lits>...>, ToDecode> {
* 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;
- }
+ 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);
+ 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;
+ }
}
}