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