Michael Uleysky
6 months ago
2 changed files with 234 additions and 3 deletions
@ -0,0 +1,206 @@
|
||||
#pragma once |
||||
#include "ncsimple.h" |
||||
#include "zarr.h" |
||||
#include <set> |
||||
|
||||
#define DEFFUNC(func, def) \ |
||||
auto func(const MString& var) const \
|
||||
{ \
|
||||
const auto ind = FindVar(var); \
|
||||
return ind < sources.size() ? sources[ind].func(var) : (def); \
|
||||
} |
||||
#define DEFFUNCA(func, def) \ |
||||
auto func(const MString& att) const \
|
||||
{ \
|
||||
const auto ind = FindAtt(att); \
|
||||
return ind < sources.size() ? sources[ind].func(att) : (def); \
|
||||
} |
||||
#define DEFFUNC2(func, def) \ |
||||
auto func(const MString& var, const MString& name) const \
|
||||
{ \
|
||||
const auto ind = FindVar(var); \
|
||||
return ind < sources.size() ? sources[ind].func(var, name) : (def); \
|
||||
} |
||||
#define DEFFUNCNAMES(func) \ |
||||
auto func() const \
|
||||
{ \
|
||||
std::set<MString> names; \
|
||||
for(const auto& s: sources) \
|
||||
{ \
|
||||
auto snames = s.func(); \
|
||||
for(const auto& name: snames) names.insert(name); \
|
||||
} \
|
||||
std::vector<MString> out; \
|
||||
for(const auto& name: names) out.push_back(name); \
|
||||
return out; \
|
||||
} |
||||
|
||||
template<class T> class NCZarrMultiCommon: private DimReqDef |
||||
{ |
||||
protected: |
||||
std::vector<T> sources; |
||||
|
||||
private: |
||||
size_t FindVar(const MString& var) const |
||||
{ |
||||
for(size_t i = 0; i < sources.size(); i++) |
||||
if(sources[i].HasVar(var)) return i; |
||||
return sources.size(); |
||||
} |
||||
|
||||
size_t FindAtt(const MString& att) const |
||||
{ |
||||
for(size_t i = 0; i < sources.size(); i++) |
||||
if(sources[i].HasAtt(att)) return i; |
||||
return sources.size(); |
||||
} |
||||
|
||||
public: |
||||
explicit operator bool() const |
||||
{ |
||||
if(sources.empty()) return false; |
||||
for(const auto& s: sources) |
||||
if(!s) return false; |
||||
return true; |
||||
} |
||||
|
||||
size_t NDim() const { return DimNames().size(); } |
||||
DEFFUNC(NDim, 0) |
||||
|
||||
size_t NAtt() const { return AttNames().size(); } |
||||
DEFFUNC(NAtt, 0) |
||||
|
||||
DEFFUNCNAMES(AttNames) |
||||
DEFFUNC(AttNames, decltype(AttNames())()) |
||||
|
||||
DEFFUNCNAMES(VarNames) |
||||
DEFFUNC(VarT, T::VarType::UNDEF) |
||||
DEFFUNC(VarFill, decltype(T().VarFill(MString()))()) |
||||
|
||||
DEFFUNC(DimNames, decltype(T().DimNames(MString()))()) |
||||
|
||||
DEFFUNC2(DimSize, 0) |
||||
|
||||
DEFFUNC2(AttT, T::AttType::UNDEF) |
||||
DEFFUNC2(AttInt, 0) |
||||
DEFFUNC2(AttUInt, 0) |
||||
DEFFUNC2(AttReal, 0.0) |
||||
DEFFUNC2(AttString, MString()) |
||||
DEFFUNC2(AttBool, false) |
||||
|
||||
DEFFUNCA(AttT, T::AttType::UNDEF) |
||||
DEFFUNCA(AttInt, 0) |
||||
DEFFUNCA(AttUInt, 0) |
||||
DEFFUNCA(AttReal, 0.0) |
||||
DEFFUNCA(AttString, MString()) |
||||
DEFFUNCA(AttBool, false) |
||||
|
||||
DEFFUNC2(HasDim, false) |
||||
DEFFUNC(HasVar, false) |
||||
DEFFUNCA(HasAtt, false) |
||||
DEFFUNC2(HasAtt, false) |
||||
|
||||
// Request is string
|
||||
template<class Data, class Transform> Error Read(const MString& vname, Data& data, Transform transform, const char* request) const |
||||
{ |
||||
return Read(vname, data, transform, MString(request)); |
||||
} |
||||
|
||||
// Request by one dimension
|
||||
template<class Data, class Transform> Error Read(const MString& vname, Data& data, Transform transform, DimReq&& req1) const |
||||
{ |
||||
return Read(vname, data, transform, std::vector<DimReq>{std::move(req1)}); |
||||
} |
||||
// Request by two dimension
|
||||
template<class Data, class Transform> Error Read(const MString& vname, Data& data, Transform transform, DimReq&& req1, DimReq&& req2) const |
||||
{ |
||||
return Read(vname, data, transform, std::vector<DimReq>{std::move(req1), std::move(req2)}); |
||||
} |
||||
// Request by three dimension
|
||||
template<class Data, class Transform> Error Read(const MString& vname, Data& data, Transform transform, DimReq&& req1, DimReq&& req2, DimReq&& req3) const |
||||
{ |
||||
return Read(vname, data, transform, std::vector<DimReq>{std::move(req1), std::move(req2), std::move(req3)}); |
||||
} |
||||
// Request by four dimension
|
||||
template<class Data, class Transform> Error Read(const MString& vname, Data& data, Transform transform, DimReq&& req1, DimReq&& req2, DimReq&& req3, DimReq&& req4) const |
||||
{ |
||||
return Read(vname, data, transform, std::vector<DimReq>{std::move(req1), std::move(req2), std::move(req3), std::move(req4)}); |
||||
} |
||||
|
||||
// Request full variable
|
||||
template<class Data, class Transform> Error Read(const MString& vname, Data& data, Transform transform) const |
||||
{ |
||||
auto ind = FindVar(vname); |
||||
if(ind < sources.size()) return sources[ind].Read(vname, data, transform); |
||||
return Error("NCZarrMultiCommon::Read", "Variable " + vname + " not found"); |
||||
} |
||||
|
||||
// Base function for all Read's
|
||||
template<class Data, class Transform> Error Read(const MString& vname, Data& data, Transform transform, const std::vector<DimReqDef::DimReq>& reqs) const |
||||
{ |
||||
auto ind = FindVar(vname); |
||||
if(ind < sources.size()) return sources[ind].Read(vname, data, transform, reqs); |
||||
return Error("NCZarrMultiCommon::Read", "Variable " + vname + " not found"); |
||||
} |
||||
|
||||
// Request by string argument
|
||||
template<class Data, class Transform> Error Read(const MString& vname, Data& data, Transform transform, const MString& request) const |
||||
{ |
||||
auto ind = FindVar(vname); |
||||
if(ind < sources.size()) return sources[ind].Read(vname, data, transform, request); |
||||
return Error("NCZarrMultiCommon::Read", "Variable " + vname + " not found"); |
||||
} |
||||
|
||||
// Request full one-dimensional variable
|
||||
template<class Type> Error Read(const MString& vname, std::vector<Type>& out) const |
||||
{ |
||||
auto ind = FindVar(vname); |
||||
if(ind < sources.size()) return sources[ind].Read(vname, out); |
||||
return Error("NCZarrMultiCommon::Read", "Variable " + vname + " not found"); |
||||
} |
||||
}; |
||||
|
||||
#undef DEFFUNC |
||||
#undef DEFFUNCA |
||||
#undef DEFFUNC2 |
||||
#undef DEFFUNCNAME |
||||
|
||||
class NCMulti: public NCZarrMultiCommon<NCSimple> |
||||
{ |
||||
public: |
||||
Error Open(const std::vector<MString>& names) |
||||
{ |
||||
sources.clear(); |
||||
decltype(sources) newsources; |
||||
static const MString pref = "NcMulti::Open"; |
||||
if(names.size() == 0) return Error(pref, "empty file list"); |
||||
for(const auto& name: names) |
||||
{ |
||||
newsources.emplace_back(); |
||||
auto ret = newsources.back().Open(name); |
||||
if(!ret) return ret.Add(pref, "Can't open file " + name); |
||||
} |
||||
sources = std::move(newsources); |
||||
return Error(); |
||||
} |
||||
}; |
||||
|
||||
class ZarrMulti: public NCZarrMultiCommon<Zarr> |
||||
{ |
||||
public: |
||||
Error Open(const MString& product, const std::vector<MString>& dsets, bool time = true) |
||||
{ |
||||
sources.clear(); |
||||
decltype(sources) newsources; |
||||
static const MString pref = "ZarrMulti::Open"; |
||||
if(dsets.size() == 0) return Error(pref, "empty datasets list"); |
||||
for(const auto& dset: dsets) |
||||
{ |
||||
newsources.emplace_back(); |
||||
auto ret = newsources.back().Open(product, dset, time); |
||||
if(!ret) return ret.Add(pref, "Can't open dataset " + dset); |
||||
} |
||||
sources = std::move(newsources); |
||||
return Error(); |
||||
} |
||||
}; |
Loading…
Reference in new issue