Back to home page

EIC code displayed by LXR

 
 

    


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  * Project: RooFit
0003  * Authors:
0004  *   Carsten D. Burgard, DESY/ATLAS, Dec 2021
0005  *
0006  * Copyright (c) 2022, CERN
0007  *
0008  * Redistribution and use in source and binary forms,
0009  * with or without modification, are permitted according to the terms
0010  * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
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 &current() = 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    // Internally, we store the backend type with an enum to be more memory efficient.
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 } // namespace Detail
0311 } // namespace RooFit
0312 
0313 #endif