blob: 0ece28089105403adb288d5a0b1d6b681fa17a1b [file] [log] [blame]
#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