Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
JSONParser.cxx
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#include "JSONParser.h"
14
15#include <sstream>
16
17#include <nlohmann/json.hpp>
18
19namespace {
20inline nlohmann::json parseWrapper(std::istream &is)
21{
22 try {
23 return nlohmann::json::parse(is);
24 } catch (const nlohmann::json::exception &ex) {
25 throw std::runtime_error(ex.what());
26 }
27}
28} // namespace
29
30// TJSONTree methods
31
32TJSONTree::TJSONTree() : root(this){};
33
34TJSONTree::TJSONTree(std::istream &is) : root(this, is){};
35
37{
39};
40
42{
43 _nodecache.push_back(n);
44 return _nodecache.back();
45}
46
48{
49 return *node;
50}
51
53{
54 return *node;
55}
56
58{
60}
61
62// TJSONTree::Node implementation
63
65public:
66 std::string _key;
67 std::string const &key() const { return _key; }
68 virtual nlohmann::json &get() = 0;
69 virtual const nlohmann::json &get() const = 0;
70 class BaseNode;
71 class NodeRef;
72 Impl(const std::string &k) : _key(k) {}
73 virtual ~Impl() = default;
74 static TJSONTree::Node &mkNode(TJSONTree *t, const std::string &k, nlohmann::json &n);
75 static const TJSONTree::Node &mkNode(const TJSONTree *t, const std::string &k, const nlohmann::json &n);
76};
77
79 nlohmann::json node;
80
81public:
82 nlohmann::json &get() override { return node; }
83 const nlohmann::json &get() const override { return node; }
84 BaseNode(std::istream &is) : Impl(""), node(parseWrapper(is)) {}
85 BaseNode() : Impl("") {}
86};
87
89 nlohmann::json &node;
90
91public:
92 nlohmann::json &get() override { return node; }
93 const nlohmann::json &get() const override { return node; }
94 NodeRef(const std::string &k, nlohmann::json &n) : Impl(k), node(n) {}
95 NodeRef(const NodeRef &other) : Impl(other.key()), node(other.node) {}
96};
97
98TJSONTree::Node &TJSONTree::Node::Impl::mkNode(TJSONTree *t, const std::string &k, nlohmann::json &n)
99{
100 Node::Impl::NodeRef ref(k, n);
101 return t->incache(Node(t, ref));
102}
103
104const TJSONTree::Node &TJSONTree::Node::Impl::mkNode(const TJSONTree *t, const std::string &k, const nlohmann::json &n)
105{
106 // not so nice to use const_cast here, but the non-const version will only live in the cache
107 Node::Impl::NodeRef ref(k, const_cast<nlohmann::json &>(n));
108 return const_cast<TJSONTree *>(t)->incache(Node(const_cast<TJSONTree *>(t), ref));
109}
110
111TJSONTree::Node::Node(TJSONTree *t, std::istream &is) : tree(t), node(std::make_unique<Impl::BaseNode>(is)) {}
112
113TJSONTree::Node::Node(TJSONTree *t) : tree(t), node(std::make_unique<Impl::BaseNode>()) {}
114
116 : tree(t), node(std::make_unique<Impl::NodeRef>(other.key(), other.get()))
117{
118}
119
120TJSONTree::Node::Node(const Node &other) : Node(other.tree, *other.node) {}
121
122// TJSONNode interface
123
124void TJSONTree::Node::writeJSON(std::ostream &os) const
125{
126 os << node->get();
127}
128
130{
131 node->get() = s;
132 return *this;
133}
134
136{
137 node->get() = i;
138 return *this;
139}
140
142{
143 node->get() = d;
144 return *this;
145}
146
148{
149 node->get() = b;
150 return *this;
151}
152
154{
155 v = node->get().get<std::string>();
156 return *this;
157}
158
160{
161 return Impl::mkNode(tree, k, node->get()[k]);
162}
163
164const TJSONTree::Node &TJSONTree::Node::operator[](std::string const &k) const
165{
166 return Impl::mkNode(tree, k, node->get()[k]);
167}
168
170{
171 return node->get().is_array() || node->get().is_object();
172}
173
175{
176 return node->get().is_object();
177}
178
180{
181 return node->get().is_array();
182}
183
184namespace {
185
186// To check whether it's allowed to reset the type of an object. We allow
187// this for nodes that have no type yet, or nodes with an empty string.
188bool isResettingPossible(nlohmann::json const &node)
189{
190
191 if (node.type() == nlohmann::json::value_t::null) {
192 return true;
193 }
194
195 if (node.type() == nlohmann::json::value_t::string) {
196 if (node.get<std::string>().empty()) {
197 return true;
198 }
199 }
200 return false;
201}
202} // namespace
203
205{
206 if (node->get().type() == nlohmann::json::value_t::object)
207 return *this;
208
209 if (isResettingPossible(node->get())) {
210 node->get() = nlohmann::json::object();
211 } else {
212 throw std::runtime_error("cannot declare \"" + this->key() + "\" to be of map - type, already of type " +
213 node->get().type_name());
214 }
215 return *this;
216}
217
219{
220 if (node->get().type() == nlohmann::json::value_t::array)
221 return *this;
222
223 if (isResettingPossible(node->get())) {
224 node->get() = nlohmann::json::array();
225 } else {
226 throw std::runtime_error("cannot declare \"" + this->key() + "\" to be of seq - type, already of type " +
227 node->get().type_name());
228 }
229 return *this;
230}
231
233{
234 node->get().clear();
235}
236
237std::string TJSONTree::Node::key() const
238{
239 return node->key();
240}
241
242std::string TJSONTree::Node::val() const
243{
244 switch (node->get().type()) {
245 case nlohmann::json::value_t::string: return node->get().get<std::string>();
246 case nlohmann::json::value_t::boolean: return node->get().get<bool>() ? "true" : "false";
247 case nlohmann::json::value_t::number_integer: return std::to_string(node->get().get<int>());
248 case nlohmann::json::value_t::number_unsigned: return std::to_string(node->get().get<unsigned int>());
249 case nlohmann::json::value_t::number_float: return std::to_string(node->get().get<double>());
250 default:
251 throw std::runtime_error("node \"" + node->key() + "\": implicit string conversion for type " +
252 node->get().type_name() + " not supported!");
253 }
254}
255
257{
258 return node->get().get<int>();
259}
261{
262 return node->get().get<double>();
263}
265{
266 auto const &nd = node->get();
267
268 // Attempting to convert zeroes and ones to bools.
269 if (nd.type() == nlohmann::json::value_t::number_unsigned) {
270 auto val = nd.get<unsigned int>();
271 if (val == 0)
272 return false;
273 if (val == 1)
274 return true;
275 }
276
277 return nd.get<bool>();
278}
279
281{
282 return !node->key().empty();
283}
284
286{
287 return node->get().is_primitive();
288}
289
290bool TJSONTree::Node::has_child(std::string const &c) const
291{
292 return node->get().find(c) != node->get().end();
293}
294
296{
297 node->get().push_back("");
298 return Impl::mkNode(tree, "", node->get().back());
299}
300
302{
303 return node->get().size();
304}
305
307{
308 return Impl::mkNode(tree, "", node->get().at(pos));
309}
310
312{
313 return Impl::mkNode(tree, "", node->get().at(pos));
314}
315
316using json_iterator = nlohmann::basic_json<>::iterator;
317using const_json_iterator = nlohmann::basic_json<>::const_iterator;
318
319template <class Nd, class NdType, class json_it>
321public:
322 enum class POS { BEGIN, END };
323 ChildItImpl(NdType &n, POS p)
324 : node(n), iter(p == POS::BEGIN ? n.get_node().get().begin() : n.get_node().get().end()){};
325 ChildItImpl(NdType &n, json_it it) : node(n), iter(it) {}
326 ChildItImpl(const ChildItImpl &other) : node(other.node), iter(other.iter) {}
328 std::unique_ptr<typename child_iterator::Impl> clone() const override
329 {
330 return std::make_unique<ChildItImpl>(node, iter);
331 }
332 void forward() override { ++iter; }
333 void backward() override { --iter; }
334 Nd &current() override
335 {
336 if (node.is_seq()) {
337 return TJSONTree::Node::Impl::mkNode(node.get_tree(), "", iter.value());
338 } else {
339 return TJSONTree::Node::Impl::mkNode(node.get_tree(), iter.key(), iter.value());
340 }
341 }
342 bool equal(const typename child_iterator::Impl &other) const override
343 {
344 // We can use static_cast here because we never compare Iterators for
345 // different JSON node types.
346 auto it = static_cast<const ChildItImpl<Nd, NdType, json_it> *>(&other);
347 return it && it->iter == this->iter;
348 }
349
350private:
351 NdType &node;
352 json_it iter;
353};
354
356{
358 return {child_iterator(std::make_unique<childIt>(*this, childIt::POS::BEGIN)),
359 child_iterator(std::make_unique<childIt>(*this, childIt::POS::END))};
360}
362{
363 using childConstIt =
365 return {const_child_iterator(std::make_unique<childConstIt>(*this, childConstIt::POS::BEGIN)),
366 const_child_iterator(std::make_unique<childConstIt>(*this, childConstIt::POS::END))};
367}
nlohmann::basic_json<>::const_iterator const_json_iterator
nlohmann::basic_json<>::iterator json_iterator
#define d(i)
Definition RSha256.hxx:102
#define b(i)
Definition RSha256.hxx:100
#define c(i)
Definition RSha256.hxx:101
winID h TVirtualViewer3D TVirtualGLPainter p
JSONNode & get(std::string const &key)
std::unique_ptr< typename child_iterator::Impl > clone() const override
ChildItImpl(NdType &n, POS p)
ChildItImpl(const ChildItImpl &other)
bool equal(const typename child_iterator::Impl &other) const override
ChildItImpl(NdType &n, json_it it)
const nlohmann::json & get() const override
nlohmann::json & get() override
NodeRef(const std::string &k, nlohmann::json &n)
NodeRef(const NodeRef &other)
const nlohmann::json & get() const override
nlohmann::json & get() override
Impl(const std::string &k)
virtual const nlohmann::json & get() const =0
static TJSONTree::Node & mkNode(TJSONTree *t, const std::string &k, nlohmann::json &n)
virtual nlohmann::json & get()=0
std::string const & key() const
virtual ~Impl()=default
bool is_container() const override
bool has_child(std::string const &) const override
bool val_bool() const override
Node & child(size_t pos) override
const Node & operator>>(std::string &v) const override
Node & operator[](std::string const &k) override
Node & append_child() override
void clear() override
size_t num_children() const override
std::string val() const override
void writeJSON(std::ostream &os) const override
bool has_key() const override
std::string key() const override
Node & set_map() override
double val_double() const override
bool is_seq() const override
std::unique_ptr< Impl > node
Definition JSONParser.h:31
Node & set_seq() override
bool has_val() const override
Node(TJSONTree *t, std::istream &is)
const Impl & get_node() const
bool is_map() const override
children_view children() override
Node & operator<<(std::string const &s) override
int val_int() const override
TJSONTree::Node & incache(const TJSONTree::Node &n)
std::list< Node > _nodecache
Definition JSONParser.h:78
void clearcache()
~TJSONTree() override
const Int_t n
Definition legend1.C:16
Double_t ex[n]
Definition legend1.C:17