summaryrefslogtreecommitdiff
path: root/c++/codec-netcdf/netcdf.tmpl.h
blob: 921c84eb630aef3a55b6c37207d2c1b9194f7b8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#pragma once

namespace saw {
namespace impl {
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 RootSchema, typename ToEncode>
struct netcdf_decode;

template<typename RootSchema, typename ToDecode>
struct netcdf_decode<schema::Int32, RootSchema, ToDecode> {
		using Schema = schema::Int32;
		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 != NC_INT){
						return make_error<err::critical>();
				}
				if(nc_dimnum != 0){
						return make_error<err::critical>();
				}
				
				int32_t val{};
				rc = nc_get_var_int(from, nc_varid, &val);
				if(rc != NC_NOERR){
						return make_error<err::critical>();
				}

				to.set(val);

				return void_t {};
		}
};

template<typename... T, string_literal... Lits, typename RootSchema, typename ToDecode>
struct netcdf_decode<schema::Struct<schema::Member<T,Lits>...>, RootSchema, 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, RootSchema, 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, RootSchema, ToDecode>::decode(to.template get<Literal>(), from, nc_varid); 
				}

			}
			if constexpr ((i+1) < sizeof...(T)){
				auto eov = decode_member<i+1>(from, to, ncid);
				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{};
	}
};
}
}