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