#pragma once #include "AVISO.h" #include "AVISOLOCAL.h" #include "BFileW.h" #include "HYCOM.h" #include "NEMO.h" #include #include using michlib::BFileW; using michlib::errmessage; using michlib::GPL; using michlib::message; using DataVariants = std::variant; template concept InfoSupported = requires(T t) { { t.template Info() } -> std::convertible_to; }; template concept ParametersSupported = requires(T t, michlib_internal::ParameterListEx& pars, const CLArgs& args) { { t.template Parameters(pars, args).first } -> std::convertible_to; }; template concept ReadPSupported = requires(T t, const MString& vname, const BaseParameters* ip, size_t i) { { t.template Read(vname, ip, i)(0) } -> std::convertible_to; }; template concept ReadSupported = requires(T t, const MString& vname, size_t i) { { t.template Read(vname, i)(0) } -> std::convertible_to; }; template concept ReadUVPSupported = requires(T t, const BaseParameters* ip, size_t i) { { t.template ReadUV(ip, i).U(0, 0) + t.template ReadUV(ip, i).V(0, 0) } -> std::convertible_to; }; class Data: public DataVariants { public: using TIndex = std::vector; private: TIndex GetTIndexes(const MDateTime& b, const MDateTime& e) const { TIndex out; auto nt = NTimes(); const MDateTime& beg = (b < e) ? b : e; const MDateTime& end = (b > e) ? b : e; if(beg > Time(nt - 1) || end < Time(0)) return out; size_t ib = 0, ie = nt - 1; for(size_t i = 0; i < nt; i++) if(Time(i) >= beg) { ib = i; break; } for(size_t i = nt; i != 0; i--) if(Time(i - 1) <= end) { ie = i - 1; break; } out.resize(ie - ib + 1); for(size_t i = 0; i < ie - ib + 1; i++) out[i] = i + ib; return out; } TIndex GetTIndexes(const MString& regex) { { MDateTime time; if(time.FromString(regex)) return TIndex(1, GetTIndex(time)); // Time, not regex if(regex == "BEGIN" || regex == "BEG" || regex == "FIRST") return TIndex(1, 0); // First time if(regex == "END" || regex == "LAST") return TIndex(1, NTimes() - 1); // Last time } TIndex out; std::unique_ptr regbuf(new regex_t); if(0 != regcomp(regbuf.get(), regex.Buf(), REG_EXTENDED | REG_NOSUB)) return out; for(size_t i = 0; i < NTimes(); i++) { MString date = Time(i).ToString(); if(0 != regexec(regbuf.get(), date.Buf(), 0, 0, 0)) continue; out.push_back(i); } return out; } size_t GetTIndex(const MDateTime& t) { size_t nt = NTimes(); if(t <= Time(0)) return 0; if(t >= Time(nt - 1)) return nt - 1; for(size_t i = 0; i < nt - 1; i++) if(t >= Time(i) && t <= Time(i + 1)) return (t - Time(i) <= Time(i + 1) - t) ? i : (i + 1); return 0; } public: Data() = default; Data(DataVariants&& d): DataVariants(std::move(d)) {} MDateTime Time(size_t it) const { return std::visit([it = it](const auto& arg) -> auto { return arg.Time(it); }, *this); } size_t NTimes() const { return std::visit([](const auto& arg) -> auto { return arg.NTimes(); }, *this); } auto CheckVar(const MString& vname) const { return std::visit([&vname = std::as_const(vname)](const auto& arg) -> auto { return arg.CheckVar(vname); }, *this); } MString Init(const CLArgs& args) { MString src = args.contains("source") ? args.at("source") : ""; if(!src.Exist()) return "No source specified"; if(src == "NEMO") { NEMOData data; auto res = data.Open(args); if(res.Exist()) return "Can't open source " + src + ":\n" + res; *this = Data(std::move(data)); } else if(src == "AVISO") { AVISOData data; auto res = data.Open(args); if(res.Exist()) return "Can't open source " + src + ":\n" + res; *this = Data(std::move(data)); } else if(src == "AVISOLOCAL") { AVISOLOCALData data; auto res = data.Open(args); if(res.Exist()) return "Can't open source " + src + ":\n" + res; *this = Data(std::move(data)); } else if(src == "HYCOM") { HYCOMData data; auto res = data.Open(args); if(res.Exist()) return "Can't open source " + src + ":\n" + res; *this = Data(std::move(data)); } else return "Unknown source: " + src; return ""; } MString ActionInfo(const CLArgs& args); MString ActionTsc(const CLArgs& args); MString ActionUV(const CLArgs& args); };