]>
Commit | Line | Data |
---|---|---|
1 | #ifndef CEPH_JSON_H | |
2 | #define CEPH_JSON_H | |
3 | ||
4 | #include <include/types.h> | |
5 | ||
6 | #ifdef _ASSERT_H | |
7 | #define NEED_ASSERT_H | |
8 | #pragma push_macro("_ASSERT_H") | |
9 | #endif | |
10 | ||
11 | #include "json_spirit/json_spirit.h" | |
12 | #undef _ASSERT_H | |
13 | ||
14 | #ifdef NEED_ASSERT_H | |
15 | #pragma pop_macro("_ASSERT_H") | |
16 | #endif | |
17 | ||
18 | #include "Formatter.h" | |
19 | ||
20 | using namespace json_spirit; | |
21 | ||
22 | ||
23 | class JSONObj; | |
24 | ||
25 | class JSONObjIter { | |
26 | typedef map<string, JSONObj *>::iterator map_iter_t; | |
27 | map_iter_t cur; | |
28 | map_iter_t last; | |
29 | ||
30 | public: | |
31 | JSONObjIter(); | |
32 | ~JSONObjIter(); | |
33 | void set(const JSONObjIter::map_iter_t &_cur, const JSONObjIter::map_iter_t &_end); | |
34 | ||
35 | void operator++(); | |
36 | JSONObj *operator*(); | |
37 | ||
38 | bool end() const { | |
39 | return (cur == last); | |
40 | } | |
41 | }; | |
42 | ||
43 | class JSONObj | |
44 | { | |
45 | JSONObj *parent; | |
46 | protected: | |
47 | string name; // corresponds to obj_type in XMLObj | |
48 | Value data; | |
49 | string data_string; | |
50 | multimap<string, JSONObj *> children; | |
51 | map<string, string> attr_map; | |
52 | void handle_value(Value v); | |
53 | ||
54 | public: | |
55 | ||
56 | JSONObj() : parent(NULL){} | |
57 | ||
58 | virtual ~JSONObj(); | |
59 | ||
60 | void init(JSONObj *p, Value v, string n); | |
61 | ||
62 | string& get_name() { return name; } | |
63 | string& get_data() { return data_string; } | |
64 | bool get_data(const string& key, string *dest); | |
65 | JSONObj *get_parent(); | |
66 | void add_child(string el, JSONObj *child); | |
67 | bool get_attr(string name, string& attr); | |
68 | JSONObjIter find(const string& name); | |
69 | JSONObjIter find_first(); | |
70 | JSONObjIter find_first(const string& name); | |
71 | JSONObj *find_obj(const string& name); | |
72 | ||
73 | friend ostream& operator<<(ostream &out, | |
74 | const JSONObj &obj); // does not work, FIXME | |
75 | ||
76 | bool is_array(); | |
77 | bool is_object(); | |
78 | vector<string> get_array_elements(); | |
79 | }; | |
80 | ||
81 | class JSONParser : public JSONObj | |
82 | { | |
83 | int buf_len; | |
84 | string json_buffer; | |
85 | bool success; | |
86 | public: | |
87 | JSONParser(); | |
88 | ~JSONParser() override; | |
89 | void handle_data(const char *s, int len); | |
90 | ||
91 | bool parse(const char *buf_, int len); | |
92 | bool parse(int len); | |
93 | bool parse(); | |
94 | bool parse(const char *file_name); | |
95 | ||
96 | const char *get_json() { return json_buffer.c_str(); } | |
97 | void set_failure() { success = false; } | |
98 | }; | |
99 | ||
100 | ||
101 | class JSONDecoder { | |
102 | public: | |
103 | struct err { | |
104 | string message; | |
105 | ||
106 | err(const string& m) : message(m) {} | |
107 | }; | |
108 | ||
109 | JSONParser parser; | |
110 | ||
111 | JSONDecoder(bufferlist& bl) { | |
112 | if (!parser.parse(bl.c_str(), bl.length())) { | |
113 | cout << "JSONDecoder::err()" << std::endl; | |
114 | throw JSONDecoder::err("failed to parse JSON input"); | |
115 | } | |
116 | } | |
117 | ||
118 | template<class T> | |
119 | static bool decode_json(const char *name, T& val, JSONObj *obj, bool mandatory = false); | |
120 | ||
121 | template<class C> | |
122 | static bool decode_json(const char *name, C& container, void (*cb)(C&, JSONObj *obj), JSONObj *obj, bool mandatory = false); | |
123 | ||
124 | template<class T> | |
125 | static void decode_json(const char *name, T& val, const T& default_val, JSONObj *obj); | |
126 | }; | |
127 | ||
128 | template<class T> | |
129 | void decode_json_obj(T& val, JSONObj *obj) | |
130 | { | |
131 | val.decode_json(obj); | |
132 | } | |
133 | ||
134 | static inline void decode_json_obj(string& val, JSONObj *obj) | |
135 | { | |
136 | val = obj->get_data(); | |
137 | } | |
138 | ||
139 | void decode_json_obj(unsigned long long& val, JSONObj *obj); | |
140 | void decode_json_obj(long long& val, JSONObj *obj); | |
141 | void decode_json_obj(unsigned long& val, JSONObj *obj); | |
142 | void decode_json_obj(long& val, JSONObj *obj); | |
143 | void decode_json_obj(unsigned& val, JSONObj *obj); | |
144 | void decode_json_obj(int& val, JSONObj *obj); | |
145 | void decode_json_obj(bool& val, JSONObj *obj); | |
146 | void decode_json_obj(bufferlist& val, JSONObj *obj); | |
147 | class utime_t; | |
148 | void decode_json_obj(utime_t& val, JSONObj *obj); | |
149 | ||
150 | template<class T> | |
151 | void decode_json_obj(list<T>& l, JSONObj *obj) | |
152 | { | |
153 | l.clear(); | |
154 | ||
155 | JSONObjIter iter = obj->find_first(); | |
156 | ||
157 | for (; !iter.end(); ++iter) { | |
158 | T val; | |
159 | JSONObj *o = *iter; | |
160 | decode_json_obj(val, o); | |
161 | l.push_back(val); | |
162 | } | |
163 | } | |
164 | ||
165 | template<class T> | |
166 | void decode_json_obj(deque<T>& l, JSONObj *obj) | |
167 | { | |
168 | l.clear(); | |
169 | ||
170 | JSONObjIter iter = obj->find_first(); | |
171 | ||
172 | for (; !iter.end(); ++iter) { | |
173 | T val; | |
174 | JSONObj *o = *iter; | |
175 | decode_json_obj(val, o); | |
176 | l.push_back(val); | |
177 | } | |
178 | } | |
179 | ||
180 | template<class T> | |
181 | void decode_json_obj(set<T>& l, JSONObj *obj) | |
182 | { | |
183 | l.clear(); | |
184 | ||
185 | JSONObjIter iter = obj->find_first(); | |
186 | ||
187 | for (; !iter.end(); ++iter) { | |
188 | T val; | |
189 | JSONObj *o = *iter; | |
190 | decode_json_obj(val, o); | |
191 | l.insert(val); | |
192 | } | |
193 | } | |
194 | ||
195 | template<class T> | |
196 | void decode_json_obj(vector<T>& l, JSONObj *obj) | |
197 | { | |
198 | l.clear(); | |
199 | ||
200 | JSONObjIter iter = obj->find_first(); | |
201 | ||
202 | for (; !iter.end(); ++iter) { | |
203 | T val; | |
204 | JSONObj *o = *iter; | |
205 | decode_json_obj(val, o); | |
206 | l.push_back(val); | |
207 | } | |
208 | } | |
209 | ||
210 | template<class K, class V, class C = std::less<K> > | |
211 | void decode_json_obj(map<K, V, C>& m, JSONObj *obj) | |
212 | { | |
213 | m.clear(); | |
214 | ||
215 | JSONObjIter iter = obj->find_first(); | |
216 | ||
217 | for (; !iter.end(); ++iter) { | |
218 | K key; | |
219 | V val; | |
220 | JSONObj *o = *iter; | |
221 | JSONDecoder::decode_json("key", key, o); | |
222 | JSONDecoder::decode_json("val", val, o); | |
223 | m[key] = val; | |
224 | } | |
225 | } | |
226 | ||
227 | template<class K, class V> | |
228 | void decode_json_obj(multimap<K, V>& m, JSONObj *obj) | |
229 | { | |
230 | m.clear(); | |
231 | ||
232 | JSONObjIter iter = obj->find_first(); | |
233 | ||
234 | for (; !iter.end(); ++iter) { | |
235 | K key; | |
236 | V val; | |
237 | JSONObj *o = *iter; | |
238 | JSONDecoder::decode_json("key", key, o); | |
239 | JSONDecoder::decode_json("val", val, o); | |
240 | m.insert(make_pair(key, val)); | |
241 | } | |
242 | } | |
243 | ||
244 | template<class C> | |
245 | void decode_json_obj(C& container, void (*cb)(C&, JSONObj *obj), JSONObj *obj) | |
246 | { | |
247 | container.clear(); | |
248 | ||
249 | JSONObjIter iter = obj->find_first(); | |
250 | ||
251 | for (; !iter.end(); ++iter) { | |
252 | JSONObj *o = *iter; | |
253 | cb(container, o); | |
254 | } | |
255 | } | |
256 | ||
257 | template<class T> | |
258 | bool JSONDecoder::decode_json(const char *name, T& val, JSONObj *obj, bool mandatory) | |
259 | { | |
260 | JSONObjIter iter = obj->find_first(name); | |
261 | if (iter.end()) { | |
262 | if (mandatory) { | |
263 | string s = "missing mandatory field " + string(name); | |
264 | throw err(s); | |
265 | } | |
266 | val = T(); | |
267 | return false; | |
268 | } | |
269 | ||
270 | try { | |
271 | decode_json_obj(val, *iter); | |
272 | } catch (err& e) { | |
273 | string s = string(name) + ": "; | |
274 | s.append(e.message); | |
275 | throw err(s); | |
276 | } | |
277 | ||
278 | return true; | |
279 | } | |
280 | ||
281 | template<class C> | |
282 | bool JSONDecoder::decode_json(const char *name, C& container, void (*cb)(C&, JSONObj *), JSONObj *obj, bool mandatory) | |
283 | { | |
284 | container.clear(); | |
285 | ||
286 | JSONObjIter iter = obj->find_first(name); | |
287 | if (iter.end()) { | |
288 | if (mandatory) { | |
289 | string s = "missing mandatory field " + string(name); | |
290 | throw err(s); | |
291 | } | |
292 | return false; | |
293 | } | |
294 | ||
295 | try { | |
296 | decode_json_obj(container, cb, *iter); | |
297 | } catch (err& e) { | |
298 | string s = string(name) + ": "; | |
299 | s.append(e.message); | |
300 | throw err(s); | |
301 | } | |
302 | ||
303 | return true; | |
304 | } | |
305 | ||
306 | template<class T> | |
307 | void JSONDecoder::decode_json(const char *name, T& val, const T& default_val, JSONObj *obj) | |
308 | { | |
309 | JSONObjIter iter = obj->find_first(name); | |
310 | if (iter.end()) { | |
311 | val = default_val; | |
312 | return; | |
313 | } | |
314 | ||
315 | try { | |
316 | decode_json_obj(val, *iter); | |
317 | } catch (err& e) { | |
318 | val = default_val; | |
319 | string s = string(name) + ": "; | |
320 | s.append(e.message); | |
321 | throw err(s); | |
322 | } | |
323 | } | |
324 | ||
325 | template<class T> | |
326 | static void encode_json(const char *name, const T& val, ceph::Formatter *f) | |
327 | { | |
328 | f->open_object_section(name); | |
329 | val.dump(f); | |
330 | f->close_section(); | |
331 | } | |
332 | ||
333 | class utime_t; | |
334 | ||
335 | void encode_json(const char *name, const string& val, ceph::Formatter *f); | |
336 | void encode_json(const char *name, const char *val, ceph::Formatter *f); | |
337 | void encode_json(const char *name, bool val, ceph::Formatter *f); | |
338 | void encode_json(const char *name, int val, ceph::Formatter *f); | |
339 | void encode_json(const char *name, unsigned val, ceph::Formatter *f); | |
340 | void encode_json(const char *name, long val, ceph::Formatter *f); | |
341 | void encode_json(const char *name, unsigned long val, ceph::Formatter *f); | |
342 | void encode_json(const char *name, long long val, ceph::Formatter *f); | |
343 | void encode_json(const char *name, const utime_t& val, ceph::Formatter *f); | |
344 | void encode_json(const char *name, const bufferlist& bl, ceph::Formatter *f); | |
345 | void encode_json(const char *name, long long unsigned val, ceph::Formatter *f); | |
346 | ||
347 | template<class T> | |
348 | static void encode_json(const char *name, const std::list<T>& l, ceph::Formatter *f) | |
349 | { | |
350 | f->open_array_section(name); | |
351 | for (typename std::list<T>::const_iterator iter = l.begin(); iter != l.end(); ++iter) { | |
352 | encode_json("obj", *iter, f); | |
353 | } | |
354 | f->close_section(); | |
355 | } | |
356 | template<class T> | |
357 | static void encode_json(const char *name, const std::deque<T>& l, ceph::Formatter *f) | |
358 | { | |
359 | f->open_array_section(name); | |
360 | for (typename std::deque<T>::const_iterator iter = l.begin(); iter != l.end(); ++iter) { | |
361 | encode_json("obj", *iter, f); | |
362 | } | |
363 | f->close_section(); | |
364 | }template<class T> | |
365 | static void encode_json(const char *name, const std::set<T>& l, ceph::Formatter *f) | |
366 | { | |
367 | f->open_array_section(name); | |
368 | for (typename std::set<T>::const_iterator iter = l.begin(); iter != l.end(); ++iter) { | |
369 | encode_json("obj", *iter, f); | |
370 | } | |
371 | f->close_section(); | |
372 | } | |
373 | ||
374 | template<class T> | |
375 | static void encode_json(const char *name, const std::vector<T>& l, ceph::Formatter *f) | |
376 | { | |
377 | f->open_array_section(name); | |
378 | for (typename std::vector<T>::const_iterator iter = l.begin(); iter != l.end(); ++iter) { | |
379 | encode_json("obj", *iter, f); | |
380 | } | |
381 | f->close_section(); | |
382 | } | |
383 | ||
384 | template<class K, class V, class C = std::less<K> > | |
385 | static void encode_json(const char *name, const std::map<K, V, C>& m, ceph::Formatter *f) | |
386 | { | |
387 | f->open_array_section(name); | |
388 | for (typename std::map<K, V, C>::const_iterator i = m.begin(); i != m.end(); ++i) { | |
389 | f->open_object_section("entry"); | |
390 | encode_json("key", i->first, f); | |
391 | encode_json("val", i->second, f); | |
392 | f->close_section(); | |
393 | } | |
394 | f->close_section(); | |
395 | } | |
396 | ||
397 | template<class K, class V> | |
398 | static void encode_json(const char *name, const std::multimap<K, V>& m, ceph::Formatter *f) | |
399 | { | |
400 | f->open_array_section(name); | |
401 | for (typename std::multimap<K, V>::const_iterator i = m.begin(); i != m.end(); ++i) { | |
402 | f->open_object_section("entry"); | |
403 | encode_json("key", i->first, f); | |
404 | encode_json("val", i->second, f); | |
405 | f->close_section(); | |
406 | } | |
407 | f->close_section(); | |
408 | } | |
409 | template<class K, class V> | |
410 | void encode_json_map(const char *name, const map<K, V>& m, ceph::Formatter *f) | |
411 | { | |
412 | f->open_array_section(name); | |
413 | typename map<K,V>::const_iterator iter; | |
414 | for (iter = m.begin(); iter != m.end(); ++iter) { | |
415 | encode_json("obj", iter->second, f); | |
416 | } | |
417 | f->close_section(); | |
418 | } | |
419 | ||
420 | ||
421 | template<class K, class V> | |
422 | void encode_json_map(const char *name, const char *index_name, | |
423 | const char *object_name, const char *value_name, | |
424 | void (*cb)(const char *, const V&, ceph::Formatter *, void *), void *parent, | |
425 | const map<K, V>& m, ceph::Formatter *f) | |
426 | { | |
427 | f->open_array_section(name); | |
428 | typename map<K,V>::const_iterator iter; | |
429 | for (iter = m.begin(); iter != m.end(); ++iter) { | |
430 | if (index_name) { | |
431 | f->open_object_section("key_value"); | |
432 | f->dump_string(index_name, iter->first); | |
433 | } | |
434 | ||
435 | if (object_name) { | |
436 | f->open_object_section(object_name); | |
437 | } | |
438 | ||
439 | if (cb) { | |
440 | cb(value_name, iter->second, f, parent); | |
441 | } else { | |
442 | encode_json(value_name, iter->second, f); | |
443 | } | |
444 | ||
445 | if (object_name) { | |
446 | f->close_section(); | |
447 | } | |
448 | if (index_name) { | |
449 | f->close_section(); | |
450 | } | |
451 | } | |
452 | f->close_section(); | |
453 | } | |
454 | ||
455 | template<class K, class V> | |
456 | void encode_json_map(const char *name, const char *index_name, | |
457 | const char *object_name, const char *value_name, | |
458 | const map<K, V>& m, ceph::Formatter *f) | |
459 | { | |
460 | encode_json_map<K, V>(name, index_name, object_name, value_name, NULL, NULL, m, f); | |
461 | } | |
462 | ||
463 | template<class K, class V> | |
464 | void encode_json_map(const char *name, const char *index_name, const char *value_name, | |
465 | const map<K, V>& m, ceph::Formatter *f) | |
466 | { | |
467 | encode_json_map<K, V>(name, index_name, NULL, value_name, NULL, NULL, m, f); | |
468 | } | |
469 | ||
470 | #endif |