Warning, file /include/root/RooFit/Detail/JSONInterface.h was not indexed
or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef RooFit_Detail_JSONInterface_h
0014 #define RooFit_Detail_JSONInterface_h
0015
0016 #include <ROOT/RSpan.hxx>
0017
0018 #include <iostream>
0019 #include <map>
0020 #include <unordered_map>
0021 #include <memory>
0022 #include <stdexcept>
0023 #include <string>
0024 #include <vector>
0025
0026 namespace RooFit {
0027 namespace Detail {
0028
0029 class JSONNode {
0030 public:
0031 template <class Nd>
0032 class child_iterator_t {
0033 public:
0034 class Impl {
0035 public:
0036 virtual ~Impl() = default;
0037 virtual std::unique_ptr<Impl> clone() const = 0;
0038 virtual void forward() = 0;
0039 virtual void backward() = 0;
0040 virtual Nd ¤t() = 0;
0041 virtual bool equal(const Impl &other) const = 0;
0042 };
0043
0044 child_iterator_t(std::unique_ptr<Impl> impl) : it(std::move(impl)) {}
0045 child_iterator_t(const child_iterator_t &other) : it(std::move(other.it->clone())) {}
0046
0047 child_iterator_t &operator++()
0048 {
0049 it->forward();
0050 return *this;
0051 }
0052 child_iterator_t &operator--()
0053 {
0054 it->backward();
0055 return *this;
0056 }
0057 Nd &operator*() const { return it->current(); }
0058 Nd &operator->() const { return it->current(); }
0059
0060 friend bool operator!=(child_iterator_t const &lhs, child_iterator_t const &rhs)
0061 {
0062 return !lhs.it->equal(*rhs.it);
0063 }
0064 friend bool operator==(child_iterator_t const &lhs, child_iterator_t const &rhs)
0065 {
0066 return lhs.it->equal(*rhs.it);
0067 }
0068
0069 private:
0070 std::unique_ptr<Impl> it;
0071 };
0072
0073 using child_iterator = child_iterator_t<JSONNode>;
0074 using const_child_iterator = child_iterator_t<const JSONNode>;
0075
0076 template <class Nd>
0077 class children_view_t {
0078 child_iterator_t<Nd> b, e;
0079
0080 public:
0081 inline children_view_t(child_iterator_t<Nd> const &b_, child_iterator_t<Nd> const &e_) : b(b_), e(e_) {}
0082
0083 inline child_iterator_t<Nd> begin() const { return b; }
0084 inline child_iterator_t<Nd> end() const { return e; }
0085 };
0086
0087 public:
0088 virtual void writeJSON(std::ostream &os) const = 0;
0089 virtual void writeYML(std::ostream &) const { throw std::runtime_error("YML not supported"); }
0090
0091 public:
0092 virtual JSONNode &operator<<(std::string const &s) = 0;
0093 inline JSONNode &operator<<(const char *s) { return *this << std::string(s); }
0094 virtual JSONNode &operator<<(int i) = 0;
0095 virtual JSONNode &operator<<(double d) = 0;
0096 virtual JSONNode &operator<<(bool b) = 0;
0097 virtual const JSONNode &operator>>(std::string &v) const = 0;
0098 virtual JSONNode &operator[](std::string const &k) = 0;
0099 virtual const JSONNode &operator[](std::string const &k) const = 0;
0100 virtual bool is_container() const = 0;
0101 virtual bool is_map() const = 0;
0102 virtual bool is_seq() const = 0;
0103 virtual JSONNode &set_map() = 0;
0104 virtual JSONNode &set_seq() = 0;
0105 virtual void clear() = 0;
0106
0107 virtual std::string key() const = 0;
0108 virtual std::string val() const = 0;
0109 virtual int val_int() const { return atoi(this->val().c_str()); }
0110 virtual double val_double() const { return std::stod(this->val()); }
0111 virtual bool val_bool() const { return atoi(this->val().c_str()); }
0112 template <class T>
0113 T val_t() const;
0114 virtual bool has_key() const = 0;
0115 virtual bool has_val() const = 0;
0116 virtual bool has_child(std::string const &) const = 0;
0117 virtual JSONNode &append_child() = 0;
0118 virtual size_t num_children() const = 0;
0119
0120 using children_view = children_view_t<JSONNode>;
0121 using const_children_view = children_view_t<const JSONNode>;
0122
0123 virtual children_view children();
0124 virtual const_children_view children() const;
0125 virtual JSONNode &child(size_t pos) = 0;
0126 virtual const JSONNode &child(size_t pos) const = 0;
0127
0128 template <typename Collection>
0129 void fill_seq(Collection const &coll)
0130 {
0131 set_seq();
0132 for (auto const &item : coll) {
0133 append_child() << item;
0134 }
0135 }
0136
0137 template <typename Collection>
0138 void fill_seq(Collection const &coll, size_t nmax)
0139 {
0140 set_seq();
0141 size_t n = 0;
0142 for (auto const &item : coll) {
0143 if (n >= nmax)
0144 break;
0145 append_child() << item;
0146 ++n;
0147 }
0148 }
0149
0150 template <typename Collection, typename TransformationFunc>
0151 void fill_seq(Collection const &coll, TransformationFunc func)
0152 {
0153 set_seq();
0154 for (auto const &item : coll) {
0155 append_child() << func(item);
0156 }
0157 }
0158
0159 template <typename Matrix>
0160 void fill_mat(Matrix const &mat)
0161 {
0162 set_seq();
0163 for (int i = 0; i < mat.GetNrows(); ++i) {
0164 auto &row = append_child();
0165 row.set_seq();
0166 for (int j = 0; j < mat.GetNcols(); ++j) {
0167 row.append_child() << mat(i, j);
0168 }
0169 }
0170 }
0171
0172 JSONNode const *find(std::string const &key) const
0173 {
0174 auto &n = *this;
0175 return n.has_child(key) ? &n[key] : nullptr;
0176 }
0177
0178 template <typename... Keys_t>
0179 JSONNode const *find(std::string const &key, Keys_t const &...keys) const
0180 {
0181 auto &n = *this;
0182 return n.has_child(key) ? n[key].find(keys...) : nullptr;
0183 }
0184
0185 JSONNode &get(std::string const &key)
0186 {
0187 auto &n = *this;
0188 n.set_map();
0189 return n[key];
0190 }
0191
0192 template <typename... Keys_t>
0193 JSONNode &get(std::string const &key, Keys_t const &...keys)
0194 {
0195 auto &next = get(key);
0196 next.set_map();
0197 return next.get(keys...);
0198 }
0199 };
0200
0201 class JSONTree {
0202 public:
0203 virtual ~JSONTree() = default;
0204
0205 virtual JSONNode &rootnode() = 0;
0206
0207 static std::unique_ptr<JSONTree> create();
0208 static std::unique_ptr<JSONTree> create(std::istream &is);
0209 static std::unique_ptr<JSONTree> create(std::string const &str);
0210
0211 static std::string getBackend();
0212 static void setBackend(std::string const &name);
0213
0214 static bool hasBackend(std::string const &name);
0215
0216 private:
0217
0218 enum class Backend { NlohmannJson, Ryml };
0219
0220 static Backend &getBackendEnum();
0221
0222 template <typename... Args>
0223 static std::unique_ptr<JSONTree> createImpl(Args &&...args);
0224 };
0225
0226 std::ostream &operator<<(std::ostream &os, RooFit::Detail::JSONNode const &s);
0227
0228 template <class T>
0229 std::vector<T> &operator<<(std::vector<T> &v, RooFit::Detail::JSONNode::children_view const &cv)
0230 {
0231 for (const auto &e : cv) {
0232 v.push_back(e.val_t<T>());
0233 }
0234 return v;
0235 }
0236
0237 template <class T>
0238 std::vector<T> &operator<<(std::vector<T> &v, RooFit::Detail::JSONNode::const_children_view const &cv)
0239 {
0240 for (const auto &e : cv) {
0241 v.push_back(e.val_t<T>());
0242 }
0243 return v;
0244 }
0245
0246 template <class T>
0247 std::vector<T> &operator<<(std::vector<T> &v, RooFit::Detail::JSONNode const &n)
0248 {
0249 if (!n.is_seq()) {
0250 throw std::runtime_error("node " + n.key() + " is not of sequence type!");
0251 }
0252 v << n.children();
0253 return v;
0254 }
0255
0256 inline RooFit::Detail::JSONNode &operator<<(RooFit::Detail::JSONNode &n, std::span<const double> v)
0257 {
0258 n.fill_seq(v);
0259 return n;
0260 }
0261
0262 inline RooFit::Detail::JSONNode &operator<<(RooFit::Detail::JSONNode &n, std::span<const float> v)
0263 {
0264 n.fill_seq(v);
0265 return n;
0266 }
0267
0268 template <class Key, class T, class Hash, class KeyEqual, class Allocator>
0269 RooFit::Detail::JSONNode &
0270 operator<<(RooFit::Detail::JSONNode &n, const std::unordered_map<Key, T, Hash, KeyEqual, Allocator> &m)
0271 {
0272 n.set_map();
0273 for (const auto &it : m) {
0274 n[it.first] << it.second;
0275 }
0276 return n;
0277 }
0278
0279 template <class Key, class T, class Compare, class Allocator>
0280 RooFit::Detail::JSONNode &operator<<(RooFit::Detail::JSONNode &n, const std::map<Key, T, Compare, Allocator> &m)
0281 {
0282 n.set_map();
0283 for (const auto &it : m) {
0284 n[it.first] << it.second;
0285 }
0286 return n;
0287 }
0288
0289 template <>
0290 inline int JSONNode::val_t<int>() const
0291 {
0292 return val_int();
0293 }
0294 template <>
0295 inline double JSONNode::val_t<double>() const
0296 {
0297 return val_double();
0298 }
0299 template <>
0300 inline bool JSONNode::val_t<bool>() const
0301 {
0302 return val_bool();
0303 }
0304 template <>
0305 inline std::string JSONNode::val_t<std::string>() const
0306 {
0307 return val();
0308 }
0309
0310 }
0311 }
0312
0313 #endif