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