123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- #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:
- 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();
- }
- BOOST_ASSERT(false);
- BOOST_UNREACHABLE_RETURN(root);
- }
- 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
|