Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
JSONInterface.h
Go to the documentation of this file.
1/*
2 * Project: RooFit
3 * Authors:
4 * Carsten D. Burgard, DESY/ATLAS, Dec 2021
5 *
6 * Copyright (c) 2022, CERN
7 *
8 * Redistribution and use in source and binary forms,
9 * with or without modification, are permitted according to the terms
10 * listed in LICENSE (http://roofit.sourceforge.net/license.txt)
11 */
12
13#ifndef RooFit_Detail_JSONInterface_h
14#define RooFit_Detail_JSONInterface_h
15
16#include <ROOT/RSpan.hxx>
17
18#include <iostream>
19#include <map>
20#include <unordered_map>
21#include <memory>
22#include <stdexcept>
23#include <string>
24#include <vector>
25
26namespace RooFit {
27namespace Detail {
28
29class JSONNode {
30public:
31 template <class Nd>
33 public:
34 class Impl {
35 public:
36 virtual ~Impl() = default;
37 virtual std::unique_ptr<Impl> clone() const = 0;
38 virtual void forward() = 0;
39 virtual void backward() = 0;
40 virtual Nd &current() = 0;
41 virtual bool equal(const Impl &other) const = 0;
42 };
43
44 child_iterator_t(std::unique_ptr<Impl> impl) : it(std::move(impl)) {}
45 child_iterator_t(const child_iterator_t &other) : it(std::move(other.it->clone())) {}
46
48 {
49 it->forward();
50 return *this;
51 }
53 {
54 it->backward();
55 return *this;
56 }
57 Nd &operator*() const { return it->current(); }
58 Nd &operator->() const { return it->current(); }
59
60 friend bool operator!=(child_iterator_t const &lhs, child_iterator_t const &rhs)
61 {
62 return !lhs.it->equal(*rhs.it);
63 }
64 friend bool operator==(child_iterator_t const &lhs, child_iterator_t const &rhs)
65 {
66 return lhs.it->equal(*rhs.it);
67 }
68
69 private:
70 std::unique_ptr<Impl> it;
71 };
72
75
76 template <class Nd>
79
80 public:
81 inline children_view_t(child_iterator_t<Nd> const &b_, child_iterator_t<Nd> const &e_) : b(b_), e(e_) {}
82
83 inline child_iterator_t<Nd> begin() const { return b; }
84 inline child_iterator_t<Nd> end() const { return e; }
85 };
86
87public:
88 virtual void writeJSON(std::ostream &os) const = 0;
89 virtual void writeYML(std::ostream &) const { throw std::runtime_error("YML not supported"); }
90
91public:
92 virtual JSONNode &operator<<(std::string const &s) = 0;
93 inline JSONNode &operator<<(const char *s) { return *this << std::string(s); }
94 virtual JSONNode &operator<<(int i) = 0;
95 virtual JSONNode &operator<<(double d) = 0;
96 virtual JSONNode &operator<<(bool b) = 0;
97 virtual const JSONNode &operator>>(std::string &v) const = 0;
98 virtual JSONNode &operator[](std::string const &k) = 0;
99 virtual const JSONNode &operator[](std::string const &k) const = 0;
100 virtual bool is_container() const = 0;
101 virtual bool is_map() const = 0;
102 virtual bool is_seq() const = 0;
103 virtual JSONNode &set_map() = 0;
104 virtual JSONNode &set_seq() = 0;
105 virtual void clear() = 0;
106
107 virtual std::string key() const = 0;
108 virtual std::string val() const = 0;
109 virtual int val_int() const { return atoi(this->val().c_str()); }
110 virtual double val_double() const { return std::stod(this->val()); }
111 virtual bool val_bool() const { return atoi(this->val().c_str()); }
112 template <class T>
113 T val_t() const;
114 virtual bool has_key() const = 0;
115 virtual bool has_val() const = 0;
116 virtual bool has_child(std::string const &) const = 0;
117 virtual JSONNode &append_child() = 0;
118 virtual size_t num_children() const = 0;
119
122
123 virtual children_view children();
124 virtual const_children_view children() const;
125 virtual JSONNode &child(size_t pos) = 0;
126 virtual const JSONNode &child(size_t pos) const = 0;
127
128 template <typename Collection>
129 void fill_seq(Collection const &coll)
130 {
131 set_seq();
132 for (auto const &item : coll) {
133 append_child() << item;
134 }
135 }
136
137 template <typename Collection>
138 void fill_seq(Collection const &coll, size_t nmax)
139 {
140 set_seq();
141 size_t n = 0;
142 for (auto const &item : coll) {
143 if (n >= nmax)
144 break;
145 append_child() << item;
146 ++n;
147 }
148 }
149
150 template <typename Collection, typename TransformationFunc>
151 void fill_seq(Collection const &coll, TransformationFunc func)
152 {
153 set_seq();
154 for (auto const &item : coll) {
155 append_child() << func(item);
156 }
157 }
158
159 template <typename Matrix>
160 void fill_mat(Matrix const &mat)
161 {
162 set_seq();
163 for (int i = 0; i < mat.GetNrows(); ++i) {
164 auto &row = append_child();
165 row.set_seq();
166 for (int j = 0; j < mat.GetNcols(); ++j) {
167 row.append_child() << mat(i, j);
168 }
169 }
170 }
171
172 JSONNode const *find(std::string const &key) const
173 {
174 auto &n = *this;
175 return n.has_child(key) ? &n[key] : nullptr;
176 }
177
178 template <typename... Keys_t>
179 JSONNode const *find(std::string const &key, Keys_t const &...keys) const
180 {
181 auto &n = *this;
182 return n.has_child(key) ? n[key].find(keys...) : nullptr;
183 }
184
185 JSONNode &get(std::string const &key)
186 {
187 auto &n = *this;
188 n.set_map();
189 return n[key];
190 }
191
192 template <typename... Keys_t>
193 JSONNode &get(std::string const &key, Keys_t const &...keys)
194 {
195 auto &next = get(key);
196 next.set_map();
197 return next.get(keys...);
198 }
199};
200
201class JSONTree {
202public:
203 virtual ~JSONTree() = default;
204
205 virtual JSONNode &rootnode() = 0;
206
207 static std::unique_ptr<JSONTree> create();
208 static std::unique_ptr<JSONTree> create(std::istream &is);
209 static std::unique_ptr<JSONTree> create(std::string const &str);
210
211 static std::string getBackend();
212 static void setBackend(std::string const &name);
213
214 static bool hasBackend(std::string const &name);
215
216private:
217 // Internally, we store the backend type with an enum to be more memory efficient.
218 enum class Backend { NlohmannJson, Ryml };
219
220 static Backend &getBackendEnum();
221
222 template <typename... Args>
223 static std::unique_ptr<JSONTree> createImpl(Args &&...args);
224};
225
226std::ostream &operator<<(std::ostream &os, RooFit::Detail::JSONNode const &s);
227
228template <class T>
229std::vector<T> &operator<<(std::vector<T> &v, RooFit::Detail::JSONNode::children_view const &cv)
230{
231 for (const auto &e : cv) {
232 v.push_back(e.val_t<T>());
233 }
234 return v;
235}
236
237template <class T>
238std::vector<T> &operator<<(std::vector<T> &v, RooFit::Detail::JSONNode::const_children_view const &cv)
239{
240 for (const auto &e : cv) {
241 v.push_back(e.val_t<T>());
242 }
243 return v;
244}
245
246template <class T>
247std::vector<T> &operator<<(std::vector<T> &v, RooFit::Detail::JSONNode const &n)
248{
249 if (!n.is_seq()) {
250 throw std::runtime_error("node " + n.key() + " is not of sequence type!");
251 }
252 v << n.children();
253 return v;
254}
255
257{
258 n.fill_seq(v);
259 return n;
260}
261
263{
264 n.fill_seq(v);
265 return n;
266}
267
268template <class Key, class T, class Hash, class KeyEqual, class Allocator>
270operator<<(RooFit::Detail::JSONNode &n, const std::unordered_map<Key, T, Hash, KeyEqual, Allocator> &m)
271{
272 n.set_map();
273 for (const auto &it : m) {
274 n[it.first] << it.second;
275 }
276 return n;
277}
278
279template <class Key, class T, class Compare, class Allocator>
280RooFit::Detail::JSONNode &operator<<(RooFit::Detail::JSONNode &n, const std::map<Key, T, Compare, Allocator> &m)
281{
282 n.set_map();
283 for (const auto &it : m) {
284 n[it.first] << it.second;
285 }
286 return n;
287}
288
289template <>
290inline int JSONNode::val_t<int>() const
291{
292 return val_int();
293}
294template <>
295inline double JSONNode::val_t<double>() const
296{
297 return val_double();
298}
299template <>
300inline bool JSONNode::val_t<bool>() const
301{
302 return val_bool();
303}
304template <>
305inline std::string JSONNode::val_t<std::string>() const
306{
307 return val();
308}
309
310} // namespace Detail
311} // namespace RooFit
312
313#endif
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define e(i)
Definition RSha256.hxx:103
TBuffer & operator<<(TBuffer &buf, const Tmpl *obj)
Definition TBuffer.h:397
char name[80]
Definition TGX11.cxx:110
virtual std::unique_ptr< Impl > clone() const =0
virtual bool equal(const Impl &other) const =0
child_iterator_t(std::unique_ptr< Impl > impl)
child_iterator_t(const child_iterator_t &other)
friend bool operator==(child_iterator_t const &lhs, child_iterator_t const &rhs)
friend bool operator!=(child_iterator_t const &lhs, child_iterator_t const &rhs)
child_iterator_t< Nd > begin() const
children_view_t(child_iterator_t< Nd > const &b_, child_iterator_t< Nd > const &e_)
child_iterator_t< Nd > end() const
virtual JSONNode & operator<<(std::string const &s)=0
virtual bool val_bool() const
JSONNode & get(std::string const &key)
virtual std::string val() const =0
virtual const JSONNode & operator>>(std::string &v) const =0
void fill_seq(Collection const &coll, size_t nmax)
JSONNode & get(std::string const &key, Keys_t const &...keys)
void fill_seq(Collection const &coll)
virtual JSONNode & set_map()=0
virtual JSONNode & append_child()=0
JSONNode const * find(std::string const &key, Keys_t const &...keys) const
virtual JSONNode & operator<<(double d)=0
virtual void clear()=0
virtual children_view children()
virtual size_t num_children() const =0
virtual JSONNode & child(size_t pos)=0
virtual JSONNode & set_seq()=0
virtual bool is_container() const =0
virtual void writeJSON(std::ostream &os) const =0
virtual bool is_seq() const =0
virtual const JSONNode & operator[](std::string const &k) const =0
virtual JSONNode & operator<<(bool b)=0
virtual void writeYML(std::ostream &) const
virtual bool is_map() const =0
virtual bool has_child(std::string const &) const =0
virtual std::string key() const =0
JSONNode & operator<<(const char *s)
void fill_seq(Collection const &coll, TransformationFunc func)
virtual JSONNode & operator[](std::string const &k)=0
void fill_mat(Matrix const &mat)
virtual bool has_key() const =0
virtual const JSONNode & child(size_t pos) const =0
virtual double val_double() const
JSONNode const * find(std::string const &key) const
virtual bool has_val() const =0
virtual int val_int() const
virtual JSONNode & operator<<(int i)=0
static void setBackend(std::string const &name)
Set the library that serves as the backend for the JSON interface.
static Backend & getBackendEnum()
static std::unique_ptr< JSONTree > create()
static bool hasBackend(std::string const &name)
Check if ROOT was compiled with support for a certain JSON backend library.
static std::string getBackend()
Returns the name of the library that serves as the backend for the JSON interface,...
static std::unique_ptr< JSONTree > createImpl(Args &&...args)
virtual ~JSONTree()=default
virtual JSONNode & rootnode()=0
Int_t GetNrows() const
Int_t GetNcols() const
const Int_t n
Definition legend1.C:16
The namespace RooFit contains mostly switches that change the behaviour of functions of PDFs (or othe...
Definition CodegenImpl.h:64
TMarker m
Definition textangle.C:8