File indexing completed on 2026-09-04 09:26:48
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
0090 public:
0091 virtual JSONNode &operator<<(std::string const &s) = 0;
0092 inline JSONNode &operator<<(const char *s) { return *this << std::string(s); }
0093 virtual JSONNode &operator<<(int i) = 0;
0094 virtual JSONNode &operator<<(double d) = 0;
0095 virtual JSONNode &operator<<(bool b) = 0;
0096 virtual const JSONNode &operator>>(std::string &v) const = 0;
0097 virtual JSONNode &operator[](std::string const &k) = 0;
0098 virtual const JSONNode &operator[](std::string const &k) const = 0;
0099 virtual bool is_container() const = 0;
0100 virtual bool is_map() const = 0;
0101 virtual bool is_seq() const = 0;
0102 virtual bool is_null() const = 0;
0103 virtual bool is_number() const;
0104 virtual JSONNode &set_map() = 0;
0105 virtual JSONNode &set_seq() = 0;
0106 virtual JSONNode &set_null() = 0;
0107 virtual void clear() = 0;
0108
0109 virtual std::string key() const = 0;
0110 virtual std::string val() const = 0;
0111 virtual int val_int() const { return atoi(this->val().c_str()); }
0112 virtual double val_double() const;
0113 virtual bool val_bool() const { return atoi(this->val().c_str()); }
0114 template <class T>
0115 T val_t() const;
0116 virtual bool has_key() const = 0;
0117 virtual bool has_val() const = 0;
0118 virtual bool has_child(std::string const &) const = 0;
0119 virtual JSONNode &append_child() = 0;
0120 virtual size_t num_children() const = 0;
0121
0122 using children_view = children_view_t<JSONNode>;
0123 using const_children_view = children_view_t<const JSONNode>;
0124
0125 virtual children_view children();
0126 virtual const_children_view children() const;
0127 virtual JSONNode &child(size_t pos) = 0;
0128 virtual const JSONNode &child(size_t pos) const = 0;
0129
0130 template <typename Collection>
0131 void fill_seq(Collection const &coll)
0132 {
0133 set_seq();
0134 for (auto const &item : coll) {
0135 append_child() << item;
0136 }
0137 }
0138
0139 template <typename Collection>
0140 void fill_seq(Collection const &coll, size_t nmax)
0141 {
0142 set_seq();
0143 size_t n = 0;
0144 for (auto const &item : coll) {
0145 if (n >= nmax)
0146 break;
0147 append_child() << item;
0148 ++n;
0149 }
0150 }
0151
0152 template <typename Collection, typename TransformationFunc>
0153 void fill_seq(Collection const &coll, TransformationFunc func)
0154 {
0155 set_seq();
0156 for (auto const &item : coll) {
0157 append_child() << func(item);
0158 }
0159 }
0160
0161 template <typename Matrix>
0162 void fill_mat(Matrix const &mat)
0163 {
0164 set_seq();
0165 for (int i = 0; i < mat.GetNrows(); ++i) {
0166 auto &row = append_child();
0167 row.set_seq();
0168 for (int j = 0; j < mat.GetNcols(); ++j) {
0169 row.append_child() << mat(i, j);
0170 }
0171 }
0172 }
0173
0174 JSONNode const *find(std::string const &key) const
0175 {
0176 auto &n = *this;
0177 return n.has_child(key) ? &n[key] : nullptr;
0178 }
0179
0180 template <typename... Keys_t>
0181 JSONNode const *find(std::string const &key, Keys_t const &...keys) const
0182 {
0183 auto &n = *this;
0184 return n.has_child(key) ? n[key].find(keys...) : nullptr;
0185 }
0186
0187 JSONNode &get(std::string const &key)
0188 {
0189 auto &n = *this;
0190 n.set_map();
0191 return n[key];
0192 }
0193
0194 template <typename... Keys_t>
0195 JSONNode &get(std::string const &key, Keys_t const &...keys)
0196 {
0197 auto &next = get(key);
0198 next.set_map();
0199 return next.get(keys...);
0200 }
0201 };
0202
0203 class JSONTree {
0204 public:
0205 virtual ~JSONTree() = default;
0206
0207 virtual JSONNode &rootnode() = 0;
0208
0209 static std::unique_ptr<JSONTree> create();
0210 static std::unique_ptr<JSONTree> create(std::istream &is);
0211 static std::unique_ptr<JSONTree> create(std::string const &str);
0212
0213 private:
0214 template <typename... Args>
0215 static std::unique_ptr<JSONTree> createImpl(Args &&...args);
0216 };
0217
0218 std::ostream &operator<<(std::ostream &os, RooFit::Detail::JSONNode const &s);
0219
0220 template <class T>
0221 std::vector<T> &operator<<(std::vector<T> &v, RooFit::Detail::JSONNode::children_view const &cv)
0222 {
0223 for (const auto &e : cv) {
0224 v.push_back(e.val_t<T>());
0225 }
0226 return v;
0227 }
0228
0229 template <class T>
0230 std::vector<T> &operator<<(std::vector<T> &v, RooFit::Detail::JSONNode::const_children_view const &cv)
0231 {
0232 for (const auto &e : cv) {
0233 v.push_back(e.val_t<T>());
0234 }
0235 return v;
0236 }
0237
0238 template <class T>
0239 std::vector<T> &operator<<(std::vector<T> &v, RooFit::Detail::JSONNode const &n)
0240 {
0241 if (!n.is_seq()) {
0242 throw std::runtime_error("node " + n.key() + " is not of sequence type!");
0243 }
0244 v << n.children();
0245 return v;
0246 }
0247
0248 inline RooFit::Detail::JSONNode &operator<<(RooFit::Detail::JSONNode &n, std::span<const double> v)
0249 {
0250 n.fill_seq(v);
0251 return n;
0252 }
0253
0254 inline RooFit::Detail::JSONNode &operator<<(RooFit::Detail::JSONNode &n, std::span<const float> v)
0255 {
0256 n.fill_seq(v);
0257 return n;
0258 }
0259
0260 inline RooFit::Detail::JSONNode &operator<<(RooFit::Detail::JSONNode &n, std::span<const int> v)
0261 {
0262 n.fill_seq(v);
0263 return n;
0264 }
0265
0266 template <class Key, class T, class Hash, class KeyEqual, class Allocator>
0267 RooFit::Detail::JSONNode &
0268 operator<<(RooFit::Detail::JSONNode &n, const std::unordered_map<Key, T, Hash, KeyEqual, Allocator> &m)
0269 {
0270 n.set_map();
0271 for (const auto &it : m) {
0272 n[it.first] << it.second;
0273 }
0274 return n;
0275 }
0276
0277 template <class Key, class T, class Compare, class Allocator>
0278 RooFit::Detail::JSONNode &operator<<(RooFit::Detail::JSONNode &n, const std::map<Key, T, Compare, Allocator> &m)
0279 {
0280 n.set_map();
0281 for (const auto &it : m) {
0282 n[it.first] << it.second;
0283 }
0284 return n;
0285 }
0286
0287 template <>
0288 inline int JSONNode::val_t<int>() const
0289 {
0290 return val_int();
0291 }
0292 template <>
0293 inline double JSONNode::val_t<double>() const
0294 {
0295 return val_double();
0296 }
0297 template <>
0298 inline bool JSONNode::val_t<bool>() const
0299 {
0300 return val_bool();
0301 }
0302 template <>
0303 inline std::string JSONNode::val_t<std::string>() const
0304 {
0305 return val();
0306 }
0307
0308 }
0309 }
0310
0311 #endif