summaryrefslogtreecommitdiff
path: root/boost/property_tree/detail/json_parser/standard_callbacks.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/property_tree/detail/json_parser/standard_callbacks.hpp')
-rw-r--r--boost/property_tree/detail/json_parser/standard_callbacks.hpp152
1 files changed, 152 insertions, 0 deletions
diff --git a/boost/property_tree/detail/json_parser/standard_callbacks.hpp b/boost/property_tree/detail/json_parser/standard_callbacks.hpp
new file mode 100644
index 0000000000..56c378ec9c
--- /dev/null
+++ b/boost/property_tree/detail/json_parser/standard_callbacks.hpp
@@ -0,0 +1,152 @@
+#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_STANDARD_CALLBACKS_HPP
+#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_STANDARD_CALLBACKS_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:
+ 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();
+ }
+ assert(false);
+ }
+ 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