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();
null_value()15         template <> inline const char* null_value() { return "null"; }
null_value()16         template <> inline const wchar_t* null_value() { return L"null"; }
17 
18         template <typename Ch> const Ch* true_value();
true_value()19         template <> inline const char* true_value() { return "true"; }
true_value()20         template <> inline const wchar_t* true_value() { return L"true"; }
21 
22         template <typename Ch> const Ch* false_value();
false_value()23         template <> inline const char* false_value() { return "false"; }
false_value()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 
on_null()33         void on_null() {
34             new_value() = constants::null_value<char_type>();
35         }
36 
on_boolean(bool b)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>
on_number(Range code_units)43         void on_number(Range code_units) {
44             new_value().assign(code_units.begin(), code_units.end());
45         }
on_begin_number()46         void on_begin_number() {
47             new_value();
48         }
on_digit(char_type d)49         void on_digit(char_type d) {
50             current_value() += d;
51         }
on_end_number()52         void on_end_number() {}
53 
on_begin_string()54         void on_begin_string() {
55             new_value();
56         }
57         template <typename Range>
on_code_units(Range code_units)58         void on_code_units(Range code_units) {
59             current_value().append(code_units.begin(), code_units.end());
60         }
on_code_unit(char_type c)61         void on_code_unit(char_type c) {
62             current_value() += c;
63         }
on_end_string()64         void on_end_string() {}
65 
on_begin_array()66         void on_begin_array() {
67             new_tree();
68             stack.back().k = array;
69         }
on_end_array()70         void on_end_array() {
71             if (stack.back().k == leaf) stack.pop_back();
72             stack.pop_back();
73         }
74 
on_begin_object()75         void on_begin_object() {
76             new_tree();
77             stack.back().k = object;
78         }
on_end_object()79         void on_end_object() {
80             if (stack.back().k == leaf) stack.pop_back();
81             stack.pop_back();
82         }
83 
output()84         Ptree& output() { return root; }
85 
86     protected:
is_key() const87         bool is_key() const {
88             return stack.back().k == key;
89         }
current_value()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 
new_tree()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             default:
121                 BOOST_ASSERT(false); // must start with string, i.e. call new_value
122             case key: {
123                 l.t->push_back(std::make_pair(key_buffer, Ptree()));
124                 l.k = object;
125                 layer nl = {leaf, &l.t->back().second};
126                 stack.push_back(nl);
127                 return *stack.back().t;
128             }
129             case leaf:
130                 stack.pop_back();
131                 return new_tree();
132             }
133         }
new_value()134         string& new_value() {
135             if (stack.empty()) return new_tree().data();
136             layer& l = stack.back();
137             switch (l.k) {
138             case leaf:
139                 stack.pop_back();
140                 return new_value();
141             case object:
142                 l.k = key;
143                 key_buffer.clear();
144                 return key_buffer;
145             default:
146                 return new_tree().data();
147             }
148         }
149     };
150 
151 }}}}
152 
153 #endif
154