]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/ceph_json.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / common / ceph_json.h
CommitLineData
7c673cae
FG
1#ifndef CEPH_JSON_H
2#define CEPH_JSON_H
3
9f95a23c
TL
4#include <stdexcept>
5#include <typeindex>
7c673cae 6#include <include/types.h>
9f95a23c 7#include <boost/container/flat_map.hpp>
f67539c2
TL
8#include <boost/container/flat_set.hpp>
9#include <include/ceph_fs.h>
10#include "common/ceph_time.h"
7c673cae
FG
11
12#include "json_spirit/json_spirit.h"
7c673cae
FG
13
14#include "Formatter.h"
15
7c673cae
FG
16
17
18class JSONObj;
19
20class JSONObjIter {
9f95a23c 21 typedef std::map<std::string, JSONObj *>::iterator map_iter_t;
7c673cae
FG
22 map_iter_t cur;
23 map_iter_t last;
24
25public:
26 JSONObjIter();
27 ~JSONObjIter();
28 void set(const JSONObjIter::map_iter_t &_cur, const JSONObjIter::map_iter_t &_end);
29
30 void operator++();
31 JSONObj *operator*();
32
33 bool end() const {
34 return (cur == last);
35 }
36};
37
38class JSONObj
39{
40 JSONObj *parent;
11fdf7f2
TL
41public:
42 struct data_val {
9f95a23c 43 std::string str;
11fdf7f2
TL
44 bool quoted{false};
45
46 void set(std::string_view s, bool q) {
47 str = s;
48 quoted = q;
49 }
50 };
7c673cae 51protected:
9f95a23c
TL
52 std::string name; // corresponds to obj_type in XMLObj
53 json_spirit::Value data;
11fdf7f2
TL
54 struct data_val val;
55 bool data_quoted{false};
9f95a23c
TL
56 std::multimap<std::string, JSONObj *> children;
57 std::map<std::string, data_val> attr_map;
58 void handle_value(json_spirit::Value v);
7c673cae
FG
59
60public:
61
62 JSONObj() : parent(NULL){}
63
64 virtual ~JSONObj();
65
9f95a23c 66 void init(JSONObj *p, json_spirit::Value v, std::string n);
7c673cae 67
9f95a23c 68 std::string& get_name() { return name; }
11fdf7f2 69 data_val& get_data_val() { return val; }
9f95a23c
TL
70 const std::string& get_data() { return val.str; }
71 bool get_data(const std::string& key, data_val *dest);
7c673cae 72 JSONObj *get_parent();
9f95a23c
TL
73 void add_child(std::string el, JSONObj *child);
74 bool get_attr(std::string name, data_val& attr);
75 JSONObjIter find(const std::string& name);
7c673cae 76 JSONObjIter find_first();
9f95a23c
TL
77 JSONObjIter find_first(const std::string& name);
78 JSONObj *find_obj(const std::string& name);
7c673cae 79
9f95a23c
TL
80 friend std::ostream& operator<<(std::ostream &out,
81 const JSONObj &obj); // does not work, FIXME
7c673cae
FG
82
83 bool is_array();
84 bool is_object();
9f95a23c 85 std::vector<std::string> get_array_elements();
7c673cae
FG
86};
87
9f95a23c 88inline std::ostream& operator<<(std::ostream &out, const JSONObj::data_val& dv) {
11fdf7f2
TL
89 const char *q = (dv.quoted ? "\"" : "");
90 out << q << dv.str << q;
91 return out;
92}
93
7c673cae
FG
94class JSONParser : public JSONObj
95{
96 int buf_len;
9f95a23c 97 std::string json_buffer;
7c673cae
FG
98 bool success;
99public:
100 JSONParser();
101 ~JSONParser() override;
102 void handle_data(const char *s, int len);
103
104 bool parse(const char *buf_, int len);
105 bool parse(int len);
106 bool parse();
107 bool parse(const char *file_name);
108
109 const char *get_json() { return json_buffer.c_str(); }
110 void set_failure() { success = false; }
111};
112
9f95a23c 113void encode_json(const char *name, const JSONObj::data_val& v, ceph::Formatter *f);
7c673cae
FG
114
115class JSONDecoder {
116public:
9f95a23c
TL
117 struct err : std::runtime_error {
118 using runtime_error::runtime_error;
7c673cae
FG
119 };
120
121 JSONParser parser;
122
9f95a23c 123 JSONDecoder(ceph::buffer::list& bl) {
7c673cae 124 if (!parser.parse(bl.c_str(), bl.length())) {
9f95a23c 125 std::cout << "JSONDecoder::err()" << std::endl;
7c673cae
FG
126 throw JSONDecoder::err("failed to parse JSON input");
127 }
128 }
129
130 template<class T>
131 static bool decode_json(const char *name, T& val, JSONObj *obj, bool mandatory = false);
132
133 template<class C>
134 static bool decode_json(const char *name, C& container, void (*cb)(C&, JSONObj *obj), JSONObj *obj, bool mandatory = false);
135
136 template<class T>
b32b8144 137 static void decode_json(const char *name, T& val, const T& default_val, JSONObj *obj);
11fdf7f2
TL
138
139 template<class T>
140 static bool decode_json(const char *name, boost::optional<T>& val, JSONObj *obj, bool mandatory = false);
141
9f95a23c
TL
142 template<class T>
143 static bool decode_json(const char *name, std::optional<T>& val, JSONObj *obj, bool mandatory = false);
144
7c673cae
FG
145};
146
147template<class T>
148void decode_json_obj(T& val, JSONObj *obj)
149{
150 val.decode_json(obj);
151}
152
9f95a23c 153inline void decode_json_obj(std::string& val, JSONObj *obj)
7c673cae
FG
154{
155 val = obj->get_data();
156}
157
11fdf7f2
TL
158static inline void decode_json_obj(JSONObj::data_val& val, JSONObj *obj)
159{
160 val = obj->get_data_val();
161}
162
7c673cae
FG
163void decode_json_obj(unsigned long long& val, JSONObj *obj);
164void decode_json_obj(long long& val, JSONObj *obj);
165void decode_json_obj(unsigned long& val, JSONObj *obj);
166void decode_json_obj(long& val, JSONObj *obj);
167void decode_json_obj(unsigned& val, JSONObj *obj);
168void decode_json_obj(int& val, JSONObj *obj);
169void decode_json_obj(bool& val, JSONObj *obj);
9f95a23c 170void decode_json_obj(ceph::buffer::list& val, JSONObj *obj);
7c673cae
FG
171class utime_t;
172void decode_json_obj(utime_t& val, JSONObj *obj);
f67539c2
TL
173void decode_json_obj(ceph_dir_layout& i, JSONObj *obj);
174
175void decode_json_obj(ceph::real_time& val, JSONObj *obj);
176void decode_json_obj(ceph::coarse_real_time& val, JSONObj *obj);
7c673cae
FG
177
178template<class T>
9f95a23c 179void decode_json_obj(std::list<T>& l, JSONObj *obj)
7c673cae
FG
180{
181 l.clear();
182
183 JSONObjIter iter = obj->find_first();
184
185 for (; !iter.end(); ++iter) {
186 T val;
187 JSONObj *o = *iter;
188 decode_json_obj(val, o);
189 l.push_back(val);
190 }
191}
192
193template<class T>
9f95a23c 194void decode_json_obj(std::deque<T>& l, JSONObj *obj)
7c673cae
FG
195{
196 l.clear();
197
198 JSONObjIter iter = obj->find_first();
199
200 for (; !iter.end(); ++iter) {
201 T val;
202 JSONObj *o = *iter;
203 decode_json_obj(val, o);
204 l.push_back(val);
205 }
206}
207
208template<class T>
9f95a23c 209void decode_json_obj(std::set<T>& l, JSONObj *obj)
7c673cae
FG
210{
211 l.clear();
212
213 JSONObjIter iter = obj->find_first();
214
215 for (; !iter.end(); ++iter) {
216 T val;
217 JSONObj *o = *iter;
218 decode_json_obj(val, o);
219 l.insert(val);
220 }
221}
222
1e59de90
TL
223template<class T, class Compare, class Alloc>
224void decode_json_obj(boost::container::flat_set<T, Compare, Alloc>& l, JSONObj *obj)
f67539c2
TL
225{
226 l.clear();
227
228 JSONObjIter iter = obj->find_first();
229
230 for (; !iter.end(); ++iter) {
231 T val;
232 JSONObj *o = *iter;
233 decode_json_obj(val, o);
234 l.insert(val);
235 }
236}
237
7c673cae 238template<class T>
9f95a23c 239void decode_json_obj(std::vector<T>& l, JSONObj *obj)
7c673cae
FG
240{
241 l.clear();
242
243 JSONObjIter iter = obj->find_first();
244
245 for (; !iter.end(); ++iter) {
246 T val;
247 JSONObj *o = *iter;
248 decode_json_obj(val, o);
249 l.push_back(val);
250 }
251}
252
31f18b77 253template<class K, class V, class C = std::less<K> >
9f95a23c 254void decode_json_obj(std::map<K, V, C>& m, JSONObj *obj)
7c673cae
FG
255{
256 m.clear();
257
258 JSONObjIter iter = obj->find_first();
259
260 for (; !iter.end(); ++iter) {
261 K key;
262 V val;
263 JSONObj *o = *iter;
264 JSONDecoder::decode_json("key", key, o);
265 JSONDecoder::decode_json("val", val, o);
266 m[key] = val;
267 }
268}
269
f67539c2
TL
270template<class K, class V, class C = std::less<K> >
271void decode_json_obj(boost::container::flat_map<K, V, C>& m, JSONObj *obj)
272{
273 m.clear();
274
275 JSONObjIter iter = obj->find_first();
276
277 for (; !iter.end(); ++iter) {
278 K key;
279 V val;
280 JSONObj *o = *iter;
281 JSONDecoder::decode_json("key", key, o);
282 JSONDecoder::decode_json("val", val, o);
283 m[key] = val;
284 }
285}
286
7c673cae 287template<class K, class V>
9f95a23c 288void decode_json_obj(std::multimap<K, V>& m, JSONObj *obj)
7c673cae
FG
289{
290 m.clear();
291
292 JSONObjIter iter = obj->find_first();
293
294 for (; !iter.end(); ++iter) {
295 K key;
296 V val;
297 JSONObj *o = *iter;
298 JSONDecoder::decode_json("key", key, o);
299 JSONDecoder::decode_json("val", val, o);
300 m.insert(make_pair(key, val));
301 }
302}
303
9f95a23c
TL
304template<class K, class V>
305void decode_json_obj(boost::container::flat_map<K, V>& m, JSONObj *obj)
306{
307 m.clear();
308
309 JSONObjIter iter = obj->find_first();
310
311 for (; !iter.end(); ++iter) {
312 K key;
313 V val;
314 JSONObj *o = *iter;
315 JSONDecoder::decode_json("key", key, o);
316 JSONDecoder::decode_json("val", val, o);
317 m[key] = val;
318 }
319}
7c673cae
FG
320template<class C>
321void decode_json_obj(C& container, void (*cb)(C&, JSONObj *obj), JSONObj *obj)
322{
323 container.clear();
324
325 JSONObjIter iter = obj->find_first();
326
327 for (; !iter.end(); ++iter) {
328 JSONObj *o = *iter;
329 cb(container, o);
330 }
331}
332
333template<class T>
334bool JSONDecoder::decode_json(const char *name, T& val, JSONObj *obj, bool mandatory)
335{
336 JSONObjIter iter = obj->find_first(name);
337 if (iter.end()) {
338 if (mandatory) {
9f95a23c 339 std::string s = "missing mandatory field " + std::string(name);
7c673cae
FG
340 throw err(s);
341 }
1e59de90
TL
342 if constexpr (std::is_default_constructible_v<T>) {
343 val = T();
344 }
7c673cae
FG
345 return false;
346 }
347
348 try {
349 decode_json_obj(val, *iter);
9f95a23c
TL
350 } catch (const err& e) {
351 std::string s = std::string(name) + ": ";
352 s.append(e.what());
7c673cae
FG
353 throw err(s);
354 }
355
356 return true;
357}
358
359template<class C>
360bool JSONDecoder::decode_json(const char *name, C& container, void (*cb)(C&, JSONObj *), JSONObj *obj, bool mandatory)
361{
362 container.clear();
363
364 JSONObjIter iter = obj->find_first(name);
365 if (iter.end()) {
366 if (mandatory) {
9f95a23c 367 std::string s = "missing mandatory field " + std::string(name);
7c673cae
FG
368 throw err(s);
369 }
370 return false;
371 }
372
373 try {
374 decode_json_obj(container, cb, *iter);
9f95a23c
TL
375 } catch (const err& e) {
376 std::string s = std::string(name) + ": ";
377 s.append(e.what());
7c673cae
FG
378 throw err(s);
379 }
380
381 return true;
382}
383
384template<class T>
b32b8144 385void JSONDecoder::decode_json(const char *name, T& val, const T& default_val, JSONObj *obj)
7c673cae
FG
386{
387 JSONObjIter iter = obj->find_first(name);
388 if (iter.end()) {
389 val = default_val;
390 return;
391 }
392
393 try {
394 decode_json_obj(val, *iter);
9f95a23c 395 } catch (const err& e) {
7c673cae 396 val = default_val;
9f95a23c
TL
397 std::string s = std::string(name) + ": ";
398 s.append(e.what());
7c673cae
FG
399 throw err(s);
400 }
401}
402
11fdf7f2
TL
403template<class T>
404bool JSONDecoder::decode_json(const char *name, boost::optional<T>& val, JSONObj *obj, bool mandatory)
405{
406 JSONObjIter iter = obj->find_first(name);
407 if (iter.end()) {
408 if (mandatory) {
9f95a23c 409 std::string s = "missing mandatory field " + std::string(name);
11fdf7f2
TL
410 throw err(s);
411 }
412 val = boost::none;
413 return false;
414 }
415
416 try {
417 val.reset(T());
418 decode_json_obj(val.get(), *iter);
9f95a23c 419 } catch (const err& e) {
11fdf7f2 420 val.reset();
9f95a23c
TL
421 std::string s = std::string(name) + ": ";
422 s.append(e.what());
11fdf7f2
TL
423 throw err(s);
424 }
425
426 return true;
427}
428
7c673cae 429template<class T>
9f95a23c
TL
430bool JSONDecoder::decode_json(const char *name, std::optional<T>& val, JSONObj *obj, bool mandatory)
431{
432 JSONObjIter iter = obj->find_first(name);
433 if (iter.end()) {
434 if (mandatory) {
435 std::string s = "missing mandatory field " + std::string(name);
436 throw err(s);
437 }
438 val.reset();
439 return false;
440 }
441
442 try {
443 val.emplace();
444 decode_json_obj(*val, *iter);
445 } catch (const err& e) {
446 val.reset();
447 std::string s = std::string(name) + ": ";
448 s.append(e.what());
449 throw err(s);
450 }
451
452 return true;
453}
454
455class JSONEncodeFilter
456{
457public:
458 class HandlerBase {
459 public:
460 virtual ~HandlerBase() {}
461
462 virtual std::type_index get_type() = 0;
463 virtual void encode_json(const char *name, const void *pval, ceph::Formatter *) const = 0;
464 };
465
466 template <class T>
467 class Handler : public HandlerBase {
468 public:
469 virtual ~Handler() {}
470
471 std::type_index get_type() override {
472 return std::type_index(typeid(const T&));
473 }
474 };
475
476private:
477 std::map<std::type_index, HandlerBase *> handlers;
478
479public:
480 void register_type(HandlerBase *h) {
481 handlers[h->get_type()] = h;
482 }
483
484 template <class T>
485 bool encode_json(const char *name, const T& val, ceph::Formatter *f) {
486 auto iter = handlers.find(std::type_index(typeid(val)));
487 if (iter == handlers.end()) {
488 return false;
489 }
490
491 iter->second->encode_json(name, (const void *)&val, f);
492 return true;
493 }
494};
495
496template<class T>
497static void encode_json_impl(const char *name, const T& val, ceph::Formatter *f)
7c673cae
FG
498{
499 f->open_object_section(name);
500 val.dump(f);
501 f->close_section();
502}
503
9f95a23c
TL
504template<class T>
505static void encode_json(const char *name, const T& val, ceph::Formatter *f)
506{
507 JSONEncodeFilter *filter = static_cast<JSONEncodeFilter *>(f->get_external_feature_handler("JSONEncodeFilter"));
508
509 if (!filter ||
510 !filter->encode_json(name, val, f)) {
511 encode_json_impl(name, val, f);
512 }
513}
514
7c673cae
FG
515class utime_t;
516
1e59de90 517void encode_json(const char *name, std::string_view val, ceph::Formatter *f);
9f95a23c 518void encode_json(const char *name, const std::string& val, ceph::Formatter *f);
7c673cae
FG
519void encode_json(const char *name, const char *val, ceph::Formatter *f);
520void encode_json(const char *name, bool val, ceph::Formatter *f);
521void encode_json(const char *name, int val, ceph::Formatter *f);
522void encode_json(const char *name, unsigned val, ceph::Formatter *f);
523void encode_json(const char *name, long val, ceph::Formatter *f);
524void encode_json(const char *name, unsigned long val, ceph::Formatter *f);
525void encode_json(const char *name, long long val, ceph::Formatter *f);
526void encode_json(const char *name, const utime_t& val, ceph::Formatter *f);
9f95a23c 527void encode_json(const char *name, const ceph::buffer::list& bl, ceph::Formatter *f);
7c673cae
FG
528void encode_json(const char *name, long long unsigned val, ceph::Formatter *f);
529
f67539c2
TL
530void encode_json(const char *name, const ceph::real_time& val, ceph::Formatter *f);
531void encode_json(const char *name, const ceph::coarse_real_time& val, ceph::Formatter *f);
532
7c673cae
FG
533template<class T>
534static void encode_json(const char *name, const std::list<T>& l, ceph::Formatter *f)
535{
536 f->open_array_section(name);
9f95a23c 537 for (auto iter = l.cbegin(); iter != l.cend(); ++iter) {
7c673cae
FG
538 encode_json("obj", *iter, f);
539 }
540 f->close_section();
541}
9f95a23c 542
7c673cae
FG
543template<class T>
544static void encode_json(const char *name, const std::deque<T>& l, ceph::Formatter *f)
545{
546 f->open_array_section(name);
9f95a23c 547 for (auto iter = l.cbegin(); iter != l.cend(); ++iter) {
7c673cae
FG
548 encode_json("obj", *iter, f);
549 }
550 f->close_section();
11fdf7f2 551}
9f95a23c 552
11fdf7f2
TL
553template<class T, class Compare = std::less<T> >
554static void encode_json(const char *name, const std::set<T, Compare>& l, ceph::Formatter *f)
7c673cae
FG
555{
556 f->open_array_section(name);
9f95a23c 557 for (auto iter = l.cbegin(); iter != l.cend(); ++iter) {
7c673cae
FG
558 encode_json("obj", *iter, f);
559 }
560 f->close_section();
561}
562
1e59de90 563template<class T, class Compare, class Alloc>
f67539c2 564static void encode_json(const char *name,
1e59de90 565 const boost::container::flat_set<T, Compare, Alloc>& l,
f67539c2
TL
566 ceph::Formatter *f)
567{
568 f->open_array_section(name);
569 for (auto iter = l.cbegin(); iter != l.cend(); ++iter) {
570 encode_json("obj", *iter, f);
571 }
572 f->close_section();
573}
574
7c673cae
FG
575template<class T>
576static void encode_json(const char *name, const std::vector<T>& l, ceph::Formatter *f)
577{
578 f->open_array_section(name);
9f95a23c 579 for (auto iter = l.cbegin(); iter != l.cend(); ++iter) {
7c673cae
FG
580 encode_json("obj", *iter, f);
581 }
582 f->close_section();
583}
584
9f95a23c 585template<class K, class V, class C = std::less<K>>
31f18b77 586static void encode_json(const char *name, const std::map<K, V, C>& m, ceph::Formatter *f)
7c673cae
FG
587{
588 f->open_array_section(name);
9f95a23c 589 for (auto i = m.cbegin(); i != m.cend(); ++i) {
7c673cae
FG
590 f->open_object_section("entry");
591 encode_json("key", i->first, f);
592 encode_json("val", i->second, f);
593 f->close_section();
594 }
595 f->close_section();
596}
597
f67539c2
TL
598template<class K, class V, class C = std::less<K> >
599static void encode_json(const char *name, const boost::container::flat_map<K, V, C>& m, ceph::Formatter *f)
600{
601 f->open_array_section(name);
602 for (auto i = m.cbegin(); i != m.cend(); ++i) {
603 f->open_object_section("entry");
604 encode_json("key", i->first, f);
605 encode_json("val", i->second, f);
606 f->close_section();
607 }
608 f->close_section();
609}
610
7c673cae
FG
611template<class K, class V>
612static void encode_json(const char *name, const std::multimap<K, V>& m, ceph::Formatter *f)
613{
614 f->open_array_section(name);
9f95a23c
TL
615 for (auto i = m.begin(); i != m.end(); ++i) {
616 f->open_object_section("entry");
617 encode_json("key", i->first, f);
618 encode_json("val", i->second, f);
619 f->close_section();
620 }
621 f->close_section();
622}
623
624template<class K, class V>
625static void encode_json(const char *name, const boost::container::flat_map<K, V>& m, ceph::Formatter *f)
626{
627 f->open_array_section(name);
628 for (auto i = m.begin(); i != m.end(); ++i) {
7c673cae
FG
629 f->open_object_section("entry");
630 encode_json("key", i->first, f);
631 encode_json("val", i->second, f);
632 f->close_section();
633 }
634 f->close_section();
635}
9f95a23c 636
7c673cae 637template<class K, class V>
9f95a23c 638void encode_json_map(const char *name, const std::map<K, V>& m, ceph::Formatter *f)
7c673cae
FG
639{
640 f->open_array_section(name);
9f95a23c 641 for (auto iter = m.cbegin(); iter != m.cend(); ++iter) {
7c673cae
FG
642 encode_json("obj", iter->second, f);
643 }
9f95a23c 644 f->close_section();
7c673cae
FG
645}
646
647
648template<class K, class V>
649void encode_json_map(const char *name, const char *index_name,
650 const char *object_name, const char *value_name,
651 void (*cb)(const char *, const V&, ceph::Formatter *, void *), void *parent,
9f95a23c 652 const std::map<K, V>& m, ceph::Formatter *f)
7c673cae
FG
653{
654 f->open_array_section(name);
9f95a23c 655 for (auto iter = m.cbegin(); iter != m.cend(); ++iter) {
7c673cae
FG
656 if (index_name) {
657 f->open_object_section("key_value");
658 f->dump_string(index_name, iter->first);
659 }
660
661 if (object_name) {
662 f->open_object_section(object_name);
663 }
664
665 if (cb) {
666 cb(value_name, iter->second, f, parent);
667 } else {
668 encode_json(value_name, iter->second, f);
669 }
670
671 if (object_name) {
672 f->close_section();
673 }
674 if (index_name) {
675 f->close_section();
676 }
677 }
678 f->close_section();
679}
680
681template<class K, class V>
682void encode_json_map(const char *name, const char *index_name,
683 const char *object_name, const char *value_name,
9f95a23c 684 const std::map<K, V>& m, ceph::Formatter *f)
7c673cae
FG
685{
686 encode_json_map<K, V>(name, index_name, object_name, value_name, NULL, NULL, m, f);
687}
688
689template<class K, class V>
690void encode_json_map(const char *name, const char *index_name, const char *value_name,
9f95a23c 691 const std::map<K, V>& m, ceph::Formatter *f)
7c673cae
FG
692{
693 encode_json_map<K, V>(name, index_name, NULL, value_name, NULL, NULL, m, f);
694}
695
9f95a23c
TL
696template <class T>
697static void encode_json(const char *name, const std::optional<T>& o, ceph::Formatter *f)
698{
699 if (!o) {
700 return;
701 }
702 encode_json(name, *o, f);
703}
704
705
f67539c2
TL
706template<class K, class V>
707void encode_json_map(const char *name, const boost::container::flat_map<K, V>& m, ceph::Formatter *f)
708{
709 f->open_array_section(name);
710 for (auto iter = m.cbegin(); iter != m.cend(); ++iter) {
711 encode_json("obj", iter->second, f);
712 }
713 f->close_section();
714}
715
716
717template<class K, class V>
718void encode_json_map(const char *name, const char *index_name,
719 const char *object_name, const char *value_name,
720 void (*cb)(const char *, const V&, ceph::Formatter *, void *), void *parent,
721 const boost::container::flat_map<K, V>& m, ceph::Formatter *f)
722{
723 f->open_array_section(name);
724 for (auto iter = m.cbegin(); iter != m.cend(); ++iter) {
725 if (index_name) {
726 f->open_object_section("key_value");
727 f->dump_string(index_name, iter->first);
728 }
729
730 if (object_name) {
731 f->open_object_section(object_name);
732 }
733
734 if (cb) {
735 cb(value_name, iter->second, f, parent);
736 } else {
737 encode_json(value_name, iter->second, f);
738 }
739
740 if (object_name) {
741 f->close_section();
742 }
743 if (index_name) {
744 f->close_section();
745 }
746 }
747 f->close_section();
748}
749
750template<class K, class V>
751void encode_json_map(const char *name, const char *index_name,
752 const char *object_name, const char *value_name,
753 const boost::container::flat_map<K, V>& m, ceph::Formatter *f)
754{
755 encode_json_map<K, V>(name, index_name, object_name, value_name, NULL, NULL, m, f);
756}
757
758template<class K, class V>
759void encode_json_map(const char *name, const char *index_name, const char *value_name,
760 const boost::container::flat_map<K, V>& m, ceph::Formatter *f)
761{
762 encode_json_map<K, V>(name, index_name, NULL, value_name, NULL, NULL, m, f);
763}
764
765
11fdf7f2
TL
766class JSONFormattable : public ceph::JSONFormatter {
767 JSONObj::data_val value;
9f95a23c
TL
768 std::vector<JSONFormattable> arr;
769 std::map<std::string, JSONFormattable> obj;
11fdf7f2 770
9f95a23c 771 std::vector<JSONFormattable *> enc_stack;
11fdf7f2
TL
772 JSONFormattable *cur_enc;
773
774protected:
9f95a23c
TL
775 bool handle_value(std::string_view name, std::string_view s, bool quoted) override;
776 bool handle_open_section(std::string_view name, const char *ns, bool section_is_array) override;
11fdf7f2
TL
777 bool handle_close_section() override;
778
779public:
780 JSONFormattable(bool p = false) : JSONFormatter(p) {
781 cur_enc = this;
782 enc_stack.push_back(cur_enc);
783 }
784
785 enum Type {
786 FMT_NONE,
787 FMT_VALUE,
788 FMT_ARRAY,
789 FMT_OBJ,
790 } type{FMT_NONE};
791
792 void set_type(Type t) {
793 type = t;
794 }
795
796 void decode_json(JSONObj *jo) {
797 if (jo->is_array()) {
798 set_type(JSONFormattable::FMT_ARRAY);
799 decode_json_obj(arr, jo);
800 } else if (jo->is_object()) {
801 set_type(JSONFormattable::FMT_OBJ);
802 auto iter = jo->find_first();
803 for (;!iter.end(); ++iter) {
804 JSONObj *field = *iter;
805 decode_json_obj(obj[field->get_name()], field);
806 }
807 } else {
808 set_type(JSONFormattable::FMT_VALUE);
809 decode_json_obj(value, jo);
810 }
811 }
812
9f95a23c 813 void encode(ceph::buffer::list& bl) const {
11fdf7f2
TL
814 ENCODE_START(2, 1, bl);
815 encode((uint8_t)type, bl);
816 encode(value.str, bl);
817 encode(arr, bl);
818 encode(obj, bl);
819 encode(value.quoted, bl);
820 ENCODE_FINISH(bl);
821 }
822
9f95a23c 823 void decode(ceph::buffer::list::const_iterator& bl) {
11fdf7f2
TL
824 DECODE_START(2, bl);
825 uint8_t t;
826 decode(t, bl);
827 type = (Type)t;
828 decode(value.str, bl);
829 decode(arr, bl);
830 decode(obj, bl);
831 if (struct_v >= 2) {
832 decode(value.quoted, bl);
833 } else {
834 value.quoted = true;
835 }
836 DECODE_FINISH(bl);
837 }
838
839 const std::string& val() const {
840 return value.str;
841 }
842
843 int val_int() const;
844 long val_long() const;
845 long long val_long_long() const;
846 bool val_bool() const;
847
9f95a23c 848 const std::map<std::string, JSONFormattable> object() const {
11fdf7f2
TL
849 return obj;
850 }
851
9f95a23c 852 const std::vector<JSONFormattable>& array() const {
11fdf7f2
TL
853 return arr;
854 }
855
856 const JSONFormattable& operator[](const std::string& name) const;
857 const JSONFormattable& operator[](size_t index) const;
858
859 JSONFormattable& operator[](const std::string& name);
860 JSONFormattable& operator[](size_t index);
861
862 operator std::string() const {
863 return value.str;
864 }
865
866 explicit operator int() const {
867 return val_int();
868 }
869
870 explicit operator long() const {
871 return val_long();
872 }
873
874 explicit operator long long() const {
875 return val_long_long();
876 }
877
878 explicit operator bool() const {
879 return val_bool();
880 }
881
882 template<class T>
883 T operator[](const std::string& name) const {
884 return this->operator[](name)(T());
885 }
886
887 template<class T>
888 T operator[](const std::string& name) {
889 return this->operator[](name)(T());
890 }
891
9f95a23c
TL
892 std::string operator ()(const char *def_val) const {
893 return def(std::string(def_val));
11fdf7f2
TL
894 }
895
896 int operator()(int def_val) const {
897 return def(def_val);
898 }
899
900 bool operator()(bool def_val) const {
901 return def(def_val);
902 }
903
9f95a23c 904 bool exists(const std::string& name) const;
11fdf7f2
TL
905 bool exists(size_t index) const;
906
907 std::string def(const std::string& def_val) const;
908 int def(int def_val) const;
909 bool def(bool def_val) const;
910
911 bool find(const std::string& name, std::string *val) const;
912
913 std::string get(const std::string& name, const std::string& def_val) const;
914
915 int get_int(const std::string& name, int def_val) const;
916 bool get_bool(const std::string& name, bool def_val) const;
917
9f95a23c
TL
918 int set(const std::string& name, const std::string& val);
919 int erase(const std::string& name);
11fdf7f2
TL
920
921 void derive_from(const JSONFormattable& jf);
922
9f95a23c 923 void encode_json(const char *name, ceph::Formatter *f) const;
11fdf7f2
TL
924
925 bool is_array() const {
926 return (type == FMT_ARRAY);
927 }
928};
929WRITE_CLASS_ENCODER(JSONFormattable)
930
9f95a23c 931void encode_json(const char *name, const JSONFormattable& v, ceph::Formatter *f);
11fdf7f2 932
7c673cae 933#endif