1#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_STANDARD_CALLBACKS_HPP
2#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_STANDARD_CALLBACKS_HPP
3
4#include <boost/assert.hpp>
5#include <boost/property_tree/ptree.hpp>
6#include <vector>
7
8namespace boost { namespace property_tree {
9 namespace json_parser { namespace detail
10{
11
12 namespace constants
13 {
14 template <typename Ch> const Ch* null_value();
15 template <> inline const char* null_value() { return "null"; }
16 template <> inline const wchar_t* null_value() { return L"null"; }
17
18 template <typename Ch> const Ch* true_value();
19 template <> inline const char* true_value() { return "true"; }
20 template <> inline const wchar_t* true_value() { return L"true"; }
21
22 template <typename Ch> const Ch* false_value();
23 template <> inline const char* false_value() { return "false"; }
24 template <> inline const wchar_t* false_value() { return L"false"; }
25 }
26
27 template <typename Ptree>
28 class standard_callbacks {
29 public:
30 typedef typename Ptree::data_type string;
31 typedef typename string::value_type char_type;
32
33 void on_null() {
34 new_value() = constants::null_value<char_type>();
35 }
36
37 void on_boolean(bool b) {
38 new_value() = b ? constants::true_value<char_type>()
39 : constants::false_value<char_type>();
40 }
41
42 template <typename Range>
43 void on_number(Range code_units) {
44 new_value().assign(code_units.begin(), code_units.end());
45 }
46 void on_begin_number() {
47 new_value();
48 }
49 void on_digit(char_type d) {
50 current_value() += d;
51 }
52 void on_end_number() {}
53
54 void on_begin_string() {
55 new_value();
56 }
57 template <typename Range>
58 void on_code_units(Range code_units) {
59 current_value().append(code_units.begin(), code_units.end());
60 }
61 void on_code_unit(char_type c) {
62 current_value() += c;
63 }
64 void on_end_string() {}
65
66 void on_begin_array() {
67 new_tree();
68 stack.back().k = array;
69 }
70 void on_end_array() {
71 if (stack.back().k == leaf) stack.pop_back();
72 stack.pop_back();
73 }
74
75 void on_begin_object() {
76 new_tree();
77 stack.back().k = object;
78 }
79 void on_end_object() {
80 if (stack.back().k == leaf) stack.pop_back();
81 stack.pop_back();
82 }
83
84 Ptree& output() { return root; }
85
86 protected:
87 bool is_key() const {
88 return stack.back().k == key;
89 }
90 string& current_value() {
91 layer& l = stack.back();
92 switch (l.k) {
93 case key: return key_buffer;
94 default: return l.t->data();
95 }
96 }
97
98 private:
99 Ptree root;
100 string key_buffer;
101 enum kind { array, object, key, leaf };
102 struct layer { kind k; Ptree* t; };
103 std::vector<layer> stack;
104
105 Ptree& new_tree() {
106 if (stack.empty()) {
107 layer l = {leaf, &root};
108 stack.push_back(l);
109 return root;
110 }
111 layer& l = stack.back();
112 switch (l.k) {
113 case array: {
114 l.t->push_back(std::make_pair(string(), Ptree()));
115 layer nl = {leaf, &l.t->back().second};
116 stack.push_back(nl);
117 return *stack.back().t;
118 }
119 case object:
120 BOOST_ASSERT(false); // must start with string, i.e. call new_value
121 case key: {
122 l.t->push_back(std::make_pair(key_buffer, Ptree()));
123 l.k = object;
124 layer nl = {leaf, &l.t->back().second};
125 stack.push_back(nl);
126 return *stack.back().t;
127 }
128 case leaf:
129 stack.pop_back();
130 return new_tree();
131 }
132 BOOST_ASSERT(false);
133 BOOST_UNREACHABLE_RETURN(root);
134 }
135 string& new_value() {
136 if (stack.empty()) return new_tree().data();
137 layer& l = stack.back();
138 switch (l.k) {
139 case leaf:
140 stack.pop_back();
141 return new_value();
142 case object:
143 l.k = key;
144 key_buffer.clear();
145 return key_buffer;
146 default:
147 return new_tree().data();
148 }
149 }
150 };
151
152}}}}
153
154#endif
155

source code of boost/libs/property_tree/include/boost/property_tree/json_parser/detail/standard_callbacks.hpp