Loading [MathJax]/extensions/tex2jax.js
Logo ROOT  
Reference Guide
 
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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
19// TJSONTree interface
20
22{
23 return root;
24}
25
26// TJSONTree methods
27
28TJSONTree::TJSONTree() : root(this){};
29
30TJSONTree::TJSONTree(std::istream &is) : root(this, is){};
31
33{
35};
36
38{
39 _nodecache.push_back(n);
40 return _nodecache.back();
41}
42
44{
45 return tree;
46}
47
49{
50 return *node;
51}
52
54{
55 return tree;
56}
57
59{
60 return *node;
61}
62
64{
66}
67
68// TJSONTree::Node implementation
69
71public:
72 std::string _key;
73 std::string const &key() const { return _key; }
74 virtual nlohmann::json &get() = 0;
75 virtual const nlohmann::json &get() const = 0;
76 class BaseNode;
77 class NodeRef;
78 Impl(const std::string &k) : _key(k) {}
79 virtual ~Impl() = default;
80 static TJSONTree::Node &mkNode(TJSONTree *t, const std::string &k, nlohmann::json &n);
81 static const TJSONTree::Node &mkNode(const TJSONTree *t, const std::string &k, const nlohmann::json &n);
82};
83
86
87public:
88 virtual nlohmann::json &get() override { return node; }
89 virtual const nlohmann::json &get() const override { return node; }
90 BaseNode(std::istream &is) : Impl(""), node(nlohmann::json::parse(is)) {}
91 BaseNode() : Impl("") {}
92};
93
96
97public:
98 virtual nlohmann::json &get() override { return node; }
99 virtual const nlohmann::json &get() const override { return node; }
100 NodeRef(const std::string &k, nlohmann::json &n) : Impl(k), node(n) {}
101 NodeRef(const NodeRef &other) : Impl(other.key()), node(other.node) {}
102};
103
105{
106 Node::Impl::NodeRef ref(k, n);
107 return t->incache(Node(t, ref));
108}
109
110const TJSONTree::Node &TJSONTree::Node::Impl::mkNode(const TJSONTree *t, const std::string &k, const nlohmann::json &n)
111{
112 // not so nice to use const_cast here, but the non-const version will only live in the cache
113 Node::Impl::NodeRef ref(k, const_cast<nlohmann::json &>(n));
114 return const_cast<TJSONTree *>(t)->incache(Node(const_cast<TJSONTree *>(t), ref));
115}
116
117TJSONTree::Node::Node(TJSONTree *t, std::istream &is) : tree(t), node(std::make_unique<Impl::BaseNode>(is)) {}
118
119TJSONTree::Node::Node(TJSONTree *t) : tree(t), node(std::make_unique<Impl::BaseNode>()) {}
120
122 : tree(t), node(std::make_unique<Impl::NodeRef>(other.key(), other.get()))
123{
124}
125
126TJSONTree::Node::Node(const Node &other) : Node(other.tree, *other.node) {}
127
129
130// TJSONNode interface
131
132void TJSONTree::Node::writeJSON(std::ostream &os) const
133{
134 os << node->get();
135}
136
138{
139 node->get() = s;
140 return *this;
141}
142
144{
145 node->get() = i;
146 return *this;
147}
148
150{
151 node->get() = d;
152 return *this;
153}
154
156{
157 v = node->get().get<std::string>();
158 return *this;
159}
160
162{
163 return Impl::mkNode(tree, k, node->get()[k]);
164}
165
167{
168 return Impl::mkNode(tree, "", node->get()[pos]);
169}
170
171const TJSONTree::Node &TJSONTree::Node::operator[](std::string const &k) const
172{
173 return Impl::mkNode(tree, k, node->get()[k]);
174}
175
177{
178 return Impl::mkNode(tree, "", node->get()[pos]);
179}
180
182{
183 return node->get().is_array() || node->get().is_object();
184}
185
187{
188 return node->get().is_object();
189}
190
192{
193 return node->get().is_array();
194}
195
196namespace {
197
198// To check whether it's allowed to reset the type of an object. We allow
199// this for nodes that have no type yet, or nodes with an empty string.
200bool isResettingPossible(nlohmann::json const &node)
201{
202
203 if (node.type() == nlohmann::json::value_t::null) {
204 return true;
205 }
206
207 if (node.type() == nlohmann::json::value_t::string) {
208 if (node.get<std::string>() == "") {
209 return true;
210 }
211 }
212 return false;
213}
214} // namespace
215
217{
218 if (node->get().type() == nlohmann::json::value_t::object)
219 return;
220
221 if (isResettingPossible(node->get())) {
222 node->get() = nlohmann::json::object();
223 } else {
224 throw std::runtime_error("cannot declare " + this->key() + " to be of map-type, already of type " +
225 node->get().type_name());
226 }
227}
228
230{
231 if (node->get().type() == nlohmann::json::value_t::array)
232 return;
233
234 if (isResettingPossible(node->get())) {
235 node->get() = nlohmann::json::array();
236 } else {
237 throw std::runtime_error("cannot declare " + this->key() + " to be of seq-type, already of type " +
238 node->get().type_name());
239 }
240}
241
242std::string TJSONTree::Node::key() const
243{
244 return node->key();
245}
246
247namespace {
248std::string itoa(int i)
249{
250 std::stringstream ss;
251 ss << i;
252 return ss.str();
253}
254std::string ftoa(float f)
255{
256 std::stringstream ss;
257 ss << f;
258 return ss.str();
259}
260} // namespace
261
262std::string TJSONTree::Node::val() const
263{
264 switch (node->get().type()) {
265 case nlohmann::json::value_t::string: return node->get().get<std::string>();
266 case nlohmann::json::value_t::boolean: return node->get().get<bool>() ? "true" : "false";
267 case nlohmann::json::value_t::number_integer: return ::itoa(node->get().get<int>());
268 case nlohmann::json::value_t::number_unsigned: return ::itoa(node->get().get<unsigned int>());
269 case nlohmann::json::value_t::number_float: return ::ftoa(node->get().get<float>());
270 default:
271 throw std::runtime_error(std::string("node " + node->key() + ": implicit string conversion for type " +
272 node->get().type_name() + " not supported!"));
273 }
274}
275
277{
278 return node->get().get<int>();
279}
281{
282 return node->get().get<float>();
283}
285{
286 auto const &nd = node->get();
287
288 // Attempting to convert zeroes and ones to bools.
289 if (nd.type() == nlohmann::json::value_t::number_unsigned) {
290 auto val = nd.get<unsigned int>();
291 if (val == 0)
292 return false;
293 if (val == 1)
294 return true;
295 }
296
297 return nd.get<bool>();
298}
299
301{
302 return node->key().size() > 0;
303}
304
306{
307 return node->get().is_primitive();
308}
309
310bool TJSONTree::Node::has_child(std::string const &c) const
311{
312 return node->get().find(c) != node->get().end();
313}
314
316{
317 node->get().push_back("");
318 return Impl::mkNode(tree, "", node->get().back());
319}
320
322{
323 return node->get().size();
324}
325
327{
328 return Impl::mkNode(tree, "", node->get().at(pos));
329}
330
332{
333 return Impl::mkNode(tree, "", node->get().at(pos));
334}
335
338
339template <class Nd, class NdType, class json_it>
341public:
342 enum class POS { BEGIN, END };
343 ChildItImpl(NdType &n, POS p)
344 : node(n), iter(p == POS::BEGIN ? n.get_node().get().begin() : n.get_node().get().end()){};
345 ChildItImpl(NdType &n, json_it it) : node(n), iter(it) {}
346 ChildItImpl(const ChildItImpl &other) : node(other.node), iter(other.iter) {}
348 virtual std::unique_ptr<typename child_iterator::Impl> clone() const override
349 {
350 return std::make_unique<ChildItImpl>(node, iter);
351 }
352 virtual void forward() override { ++iter; }
353 virtual void backward() override { --iter; }
354 virtual Nd &current() override
355 {
356 if (node.is_seq()) {
357 return TJSONTree::Node::Impl::mkNode(node.get_tree(), "", iter.value());
358 } else {
359 return TJSONTree::Node::Impl::mkNode(node.get_tree(), iter.key(), iter.value());
360 }
361 }
362 virtual bool equal(const typename child_iterator::Impl &other) const override
363 {
364 auto it = dynamic_cast<const ChildItImpl<Nd, NdType, json_it> *>(&other);
365 return it && it->iter == this->iter;
366 }
367
368private:
369 NdType &node;
370 json_it iter;
371};
372
374{
376 return {child_iterator(std::make_unique<childIt>(*this, childIt::POS::BEGIN)),
377 child_iterator(std::make_unique<childIt>(*this, childIt::POS::END))};
378}
380{
381 using childConstIt =
383 return {const_child_iterator(std::make_unique<childConstIt>(*this, childConstIt::POS::BEGIN)),
384 const_child_iterator(std::make_unique<childConstIt>(*this, childConstIt::POS::END))};
385}
nlohmann::basic_json<>::const_iterator const_json_iterator
nlohmann::basic_json<>::iterator json_iterator
#define d(i)
Definition RSha256.hxx:102
#define f(i)
Definition RSha256.hxx:104
#define c(i)
Definition RSha256.hxx:101
virtual Nd & current() override
ChildItImpl(NdType &n, POS p)
virtual void backward() override
virtual std::unique_ptr< typename child_iterator::Impl > clone() const override
ChildItImpl(const ChildItImpl &other)
virtual void forward() override
virtual bool equal(const typename child_iterator::Impl &other) const override
ChildItImpl(NdType &n, json_it it)
virtual nlohmann::json & get() override
virtual const nlohmann::json & get() const override
NodeRef(const std::string &k, nlohmann::json &n)
NodeRef(const NodeRef &other)
virtual nlohmann::json & get() override
virtual const nlohmann::json & get() const 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
virtual bool is_container() const override
virtual bool has_child(std::string const &) const override
virtual bool val_bool() const override
virtual Node & child(size_t pos) override
virtual const Node & operator>>(std::string &v) const override
virtual void set_seq() override
children_view children() override
virtual Node & operator[](std::string const &k) override
virtual Node & append_child() override
const TJSONTree * get_tree() const
virtual size_t num_children() const override
virtual std::string val() const override
virtual void writeJSON(std::ostream &os) const override
virtual bool has_key() const override
TJSONTree * tree
Definition JSONParser.h:26
virtual std::string key() const override
virtual void set_map() override
virtual bool is_seq() const override
virtual bool has_val() const override
virtual float val_float() const override
Node(TJSONTree *t, std::istream &is)
const Impl & get_node() const
virtual bool is_map() const override
virtual Node & operator<<(std::string const &s) override
virtual int val_int() const override
TJSONTree::Node & incache(const TJSONTree::Node &n)
Node root
Definition JSONParser.h:77
std::list< Node > _nodecache
Definition JSONParser.h:78
void clearcache()
virtual ~TJSONTree()
virtual Node & rootnode() override
const Int_t n
Definition legend1.C:16
basic_json< std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, std::allocator, adl_serializer, std::vector< std::uint8_t > > json
Definition tree.py:1