]> git.proxmox.com Git - ceph.git/blob - ceph/src/common/ceph_json.h
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / common / ceph_json.h
1 #ifndef CEPH_JSON_H
2 #define CEPH_JSON_H
3
4 #include <stdexcept>
5 #include <typeindex>
6 #include <include/types.h>
7 #include <boost/container/flat_map.hpp>
8 #include <boost/container/flat_set.hpp>
9 #include <include/ceph_fs.h>
10 #include "common/ceph_time.h"
11
12 #include "json_spirit/json_spirit.h"
13
14 #include "Formatter.h"
15
16
17
18 class JSONObj;
19
20 class JSONObjIter {
21 typedef std::map<std::string, JSONObj *>::iterator map_iter_t;
22 map_iter_t cur;
23 map_iter_t last;
24
25 public:
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
38 class JSONObj
39 {
40 JSONObj *parent;
41 public:
42 struct data_val {
43 std::string str;
44 bool quoted{false};
45
46 void set(std::string_view s, bool q) {
47 str = s;
48 quoted = q;
49 }
50 };
51 protected:
52 std::string name; // corresponds to obj_type in XMLObj
53 json_spirit::Value data;
54 struct data_val val;
55 bool data_quoted{false};
56 std::multimap<std::string, JSONObj *> children;
57 std::map<std::string, data_val> attr_map;
58 void handle_value(json_spirit::Value v);
59
60 public:
61
62 JSONObj() : parent(NULL){}
63
64 virtual ~JSONObj();
65
66 void init(JSONObj *p, json_spirit::Value v, std::string n);
67
68 std::string& get_name() { return name; }
69 data_val& get_data_val() { return val; }
70 const std::string& get_data() { return val.str; }
71 bool get_data(const std::string& key, data_val *dest);
72 JSONObj *get_parent();
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);
76 JSONObjIter find_first();
77 JSONObjIter find_first(const std::string& name);
78 JSONObj *find_obj(const std::string& name);
79
80 friend std::ostream& operator<<(std::ostream &out,
81 const JSONObj &obj); // does not work, FIXME
82
83 bool is_array();
84 bool is_object();
85 std::vector<std::string> get_array_elements();
86 };
87
88 inline std::ostream& operator<<(std::ostream &out, const JSONObj::data_val& dv) {
89 const char *q = (dv.quoted ? "\"" : "");
90 out << q << dv.str << q;
91 return out;
92 }
93
94 class JSONParser : public JSONObj
95 {
96 int buf_len;
97 std::string json_buffer;
98 bool success;
99 public:
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
113 void encode_json(const char *name, const JSONObj::data_val& v, ceph::Formatter *f);
114
115 class JSONDecoder {
116 public:
117 struct err : std::runtime_error {
118 using runtime_error::runtime_error;
119 };
120
121 JSONParser parser;
122
123 JSONDecoder(ceph::buffer::list& bl) {
124 if (!parser.parse(bl.c_str(), bl.length())) {
125 std::cout << "JSONDecoder::err()" << std::endl;
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>
137 static void decode_json(const char *name, T& val, const T& default_val, JSONObj *obj);
138
139 template<class T>
140 static bool decode_json(const char *name, boost::optional<T>& val, JSONObj *obj, bool mandatory = false);
141
142 template<class T>
143 static bool decode_json(const char *name, std::optional<T>& val, JSONObj *obj, bool mandatory = false);
144
145 };
146
147 template<class T>
148 void decode_json_obj(T& val, JSONObj *obj)
149 {
150 val.decode_json(obj);
151 }
152
153 inline void decode_json_obj(std::string& val, JSONObj *obj)
154 {
155 val = obj->get_data();
156 }
157
158 static inline void decode_json_obj(JSONObj::data_val& val, JSONObj *obj)
159 {
160 val = obj->get_data_val();
161 }
162
163 void decode_json_obj(unsigned long long& val, JSONObj *obj);
164 void decode_json_obj(long long& val, JSONObj *obj);
165 void decode_json_obj(unsigned long& val, JSONObj *obj);
166 void decode_json_obj(long& val, JSONObj *obj);
167 void decode_json_obj(unsigned& val, JSONObj *obj);
168 void decode_json_obj(int& val, JSONObj *obj);
169 void decode_json_obj(bool& val, JSONObj *obj);
170 void decode_json_obj(ceph::buffer::list& val, JSONObj *obj);
171 class utime_t;
172 void decode_json_obj(utime_t& val, JSONObj *obj);
173 void decode_json_obj(ceph_dir_layout& i, JSONObj *obj);
174
175 void decode_json_obj(ceph::real_time& val, JSONObj *obj);
176 void decode_json_obj(ceph::coarse_real_time& val, JSONObj *obj);
177
178 template<class T>
179 void decode_json_obj(std::list<T>& l, JSONObj *obj)
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
193 template<class T>
194 void decode_json_obj(std::deque<T>& l, JSONObj *obj)
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
208 template<class T>
209 void decode_json_obj(std::set<T>& l, JSONObj *obj)
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
223 template<class T, class Compare, class Alloc>
224 void decode_json_obj(boost::container::flat_set<T, Compare, Alloc>& l, JSONObj *obj)
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
238 template<class T>
239 void decode_json_obj(std::vector<T>& l, JSONObj *obj)
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
253 template<class K, class V, class C = std::less<K> >
254 void decode_json_obj(std::map<K, V, C>& m, JSONObj *obj)
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
270 template<class K, class V, class C = std::less<K> >
271 void 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
287 template<class K, class V>
288 void decode_json_obj(std::multimap<K, V>& m, JSONObj *obj)
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
304 template<class K, class V>
305 void 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 }
320 template<class C>
321 void 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
333 template<class T>
334 bool 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) {
339 std::string s = "missing mandatory field " + std::string(name);
340 throw err(s);
341 }
342 if constexpr (std::is_default_constructible_v<T>) {
343 val = T();
344 }
345 return false;
346 }
347
348 try {
349 decode_json_obj(val, *iter);
350 } catch (const err& e) {
351 std::string s = std::string(name) + ": ";
352 s.append(e.what());
353 throw err(s);
354 }
355
356 return true;
357 }
358
359 template<class C>
360 bool 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) {
367 std::string s = "missing mandatory field " + std::string(name);
368 throw err(s);
369 }
370 return false;
371 }
372
373 try {
374 decode_json_obj(container, cb, *iter);
375 } catch (const err& e) {
376 std::string s = std::string(name) + ": ";
377 s.append(e.what());
378 throw err(s);
379 }
380
381 return true;
382 }
383
384 template<class T>
385 void JSONDecoder::decode_json(const char *name, T& val, const T& default_val, JSONObj *obj)
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);
395 } catch (const err& e) {
396 val = default_val;
397 std::string s = std::string(name) + ": ";
398 s.append(e.what());
399 throw err(s);
400 }
401 }
402
403 template<class T>
404 bool 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) {
409 std::string s = "missing mandatory field " + std::string(name);
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);
419 } catch (const err& e) {
420 val.reset();
421 std::string s = std::string(name) + ": ";
422 s.append(e.what());
423 throw err(s);
424 }
425
426 return true;
427 }
428
429 template<class T>
430 bool 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
455 class JSONEncodeFilter
456 {
457 public:
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
476 private:
477 std::map<std::type_index, HandlerBase *> handlers;
478
479 public:
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
496 template<class T>
497 static void encode_json_impl(const char *name, const T& val, ceph::Formatter *f)
498 {
499 f->open_object_section(name);
500 val.dump(f);
501 f->close_section();
502 }
503
504 template<class T>
505 static 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
515 class utime_t;
516
517 void encode_json(const char *name, std::string_view val, ceph::Formatter *f);
518 void encode_json(const char *name, const std::string& val, ceph::Formatter *f);
519 void encode_json(const char *name, const char *val, ceph::Formatter *f);
520 void encode_json(const char *name, bool val, ceph::Formatter *f);
521 void encode_json(const char *name, int val, ceph::Formatter *f);
522 void encode_json(const char *name, unsigned val, ceph::Formatter *f);
523 void encode_json(const char *name, long val, ceph::Formatter *f);
524 void encode_json(const char *name, unsigned long val, ceph::Formatter *f);
525 void encode_json(const char *name, long long val, ceph::Formatter *f);
526 void encode_json(const char *name, const utime_t& val, ceph::Formatter *f);
527 void encode_json(const char *name, const ceph::buffer::list& bl, ceph::Formatter *f);
528 void encode_json(const char *name, long long unsigned val, ceph::Formatter *f);
529
530 void encode_json(const char *name, const ceph::real_time& val, ceph::Formatter *f);
531 void encode_json(const char *name, const ceph::coarse_real_time& val, ceph::Formatter *f);
532
533 template<class T>
534 static void encode_json(const char *name, const std::list<T>& l, ceph::Formatter *f)
535 {
536 f->open_array_section(name);
537 for (auto iter = l.cbegin(); iter != l.cend(); ++iter) {
538 encode_json("obj", *iter, f);
539 }
540 f->close_section();
541 }
542
543 template<class T>
544 static void encode_json(const char *name, const std::deque<T>& l, ceph::Formatter *f)
545 {
546 f->open_array_section(name);
547 for (auto iter = l.cbegin(); iter != l.cend(); ++iter) {
548 encode_json("obj", *iter, f);
549 }
550 f->close_section();
551 }
552
553 template<class T, class Compare = std::less<T> >
554 static void encode_json(const char *name, const std::set<T, Compare>& l, ceph::Formatter *f)
555 {
556 f->open_array_section(name);
557 for (auto iter = l.cbegin(); iter != l.cend(); ++iter) {
558 encode_json("obj", *iter, f);
559 }
560 f->close_section();
561 }
562
563 template<class T, class Compare, class Alloc>
564 static void encode_json(const char *name,
565 const boost::container::flat_set<T, Compare, Alloc>& l,
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
575 template<class T>
576 static void encode_json(const char *name, const std::vector<T>& l, ceph::Formatter *f)
577 {
578 f->open_array_section(name);
579 for (auto iter = l.cbegin(); iter != l.cend(); ++iter) {
580 encode_json("obj", *iter, f);
581 }
582 f->close_section();
583 }
584
585 template<class K, class V, class C = std::less<K>>
586 static void encode_json(const char *name, const std::map<K, V, C>& m, ceph::Formatter *f)
587 {
588 f->open_array_section(name);
589 for (auto i = m.cbegin(); i != m.cend(); ++i) {
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
598 template<class K, class V, class C = std::less<K> >
599 static 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
611 template<class K, class V>
612 static void encode_json(const char *name, const std::multimap<K, V>& m, ceph::Formatter *f)
613 {
614 f->open_array_section(name);
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
624 template<class K, class V>
625 static 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) {
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 }
636
637 template<class K, class V>
638 void encode_json_map(const char *name, const std::map<K, V>& m, ceph::Formatter *f)
639 {
640 f->open_array_section(name);
641 for (auto iter = m.cbegin(); iter != m.cend(); ++iter) {
642 encode_json("obj", iter->second, f);
643 }
644 f->close_section();
645 }
646
647
648 template<class K, class V>
649 void 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,
652 const std::map<K, V>& m, ceph::Formatter *f)
653 {
654 f->open_array_section(name);
655 for (auto iter = m.cbegin(); iter != m.cend(); ++iter) {
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
681 template<class K, class V>
682 void encode_json_map(const char *name, const char *index_name,
683 const char *object_name, const char *value_name,
684 const std::map<K, V>& m, ceph::Formatter *f)
685 {
686 encode_json_map<K, V>(name, index_name, object_name, value_name, NULL, NULL, m, f);
687 }
688
689 template<class K, class V>
690 void encode_json_map(const char *name, const char *index_name, const char *value_name,
691 const std::map<K, V>& m, ceph::Formatter *f)
692 {
693 encode_json_map<K, V>(name, index_name, NULL, value_name, NULL, NULL, m, f);
694 }
695
696 template <class T>
697 static 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
706 template<class K, class V>
707 void 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
717 template<class K, class V>
718 void 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
750 template<class K, class V>
751 void 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
758 template<class K, class V>
759 void 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
766 class JSONFormattable : public ceph::JSONFormatter {
767 JSONObj::data_val value;
768 std::vector<JSONFormattable> arr;
769 std::map<std::string, JSONFormattable> obj;
770
771 std::vector<JSONFormattable *> enc_stack;
772 JSONFormattable *cur_enc;
773
774 protected:
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;
777 bool handle_close_section() override;
778
779 public:
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
813 void encode(ceph::buffer::list& bl) const {
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
823 void decode(ceph::buffer::list::const_iterator& bl) {
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
848 const std::map<std::string, JSONFormattable> object() const {
849 return obj;
850 }
851
852 const std::vector<JSONFormattable>& array() const {
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
892 std::string operator ()(const char *def_val) const {
893 return def(std::string(def_val));
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
904 bool exists(const std::string& name) const;
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
918 int set(const std::string& name, const std::string& val);
919 int erase(const std::string& name);
920
921 void derive_from(const JSONFormattable& jf);
922
923 void encode_json(const char *name, ceph::Formatter *f) const;
924
925 bool is_array() const {
926 return (type == FMT_ARRAY);
927 }
928 };
929 WRITE_CLASS_ENCODER(JSONFormattable)
930
931 void encode_json(const char *name, const JSONFormattable& v, ceph::Formatter *f);
932
933 #endif