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 | |
8 | namespace 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 | |