154 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
		
			4.6 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
#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
 |