summaryrefslogtreecommitdiff
path: root/boost/property_tree
diff options
context:
space:
mode:
Diffstat (limited to 'boost/property_tree')
-rw-r--r--boost/property_tree/detail/json_parser/narrow_encoding.hpp159
-rw-r--r--boost/property_tree/detail/json_parser/parser.hpp524
-rw-r--r--boost/property_tree/detail/json_parser/read.hpp55
-rw-r--r--boost/property_tree/detail/json_parser/standard_callbacks.hpp152
-rw-r--r--boost/property_tree/detail/json_parser/wide_encoding.hpp171
-rw-r--r--boost/property_tree/detail/json_parser_read.hpp332
-rw-r--r--boost/property_tree/detail/rapidxml.hpp2
-rw-r--r--boost/property_tree/json_parser.hpp9
-rw-r--r--boost/property_tree/ptree_serialization.hpp51
9 files changed, 1106 insertions, 349 deletions
diff --git a/boost/property_tree/detail/json_parser/narrow_encoding.hpp b/boost/property_tree/detail/json_parser/narrow_encoding.hpp
new file mode 100644
index 0000000000..13218743d1
--- /dev/null
+++ b/boost/property_tree/detail/json_parser/narrow_encoding.hpp
@@ -0,0 +1,159 @@
+#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_NARROW_ENCODING_HPP
+#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_NARROW_ENCODING_HPP
+
+#include <boost/range/iterator_range_core.hpp>
+
+#include <cassert>
+#include <utility>
+
+namespace boost { namespace property_tree {
+ namespace json_parser { namespace detail
+{
+
+ struct external_ascii_superset_encoding
+ {
+ typedef char external_char;
+
+ bool is_nl(char c) const { return c == '\n'; }
+ bool is_ws(char c) const {
+ return c == ' ' || c == '\t' || c == '\n' || c == '\r';
+ }
+
+ bool is_minus(char c) const { return c == '-'; }
+ bool is_plusminus(char c) const { return c == '+' || c == '-'; }
+ bool is_dot(char c) const { return c == '.'; }
+ bool is_eE(char c) const { return c == 'e' || c == 'E'; }
+ bool is_0(char c) const { return c == '0'; }
+ bool is_digit(char c) const { return c >= '0' && c <= '9'; }
+ bool is_digit0(char c) const { return c >= '1' && c <= '9'; }
+
+ bool is_quote(char c) const { return c == '"'; }
+ bool is_backslash(char c) const { return c == '\\'; }
+ bool is_slash(char c) const { return c == '/'; }
+
+ bool is_comma(char c) const { return c == ','; }
+ bool is_open_bracket(char c) const { return c == '['; }
+ bool is_close_bracket(char c) const { return c == ']'; }
+ bool is_colon(char c) const { return c == ':'; }
+ bool is_open_brace(char c) const { return c == '{'; }
+ bool is_close_brace(char c) const { return c == '}'; }
+
+ bool is_a(char c) const { return c == 'a'; }
+ bool is_b(char c) const { return c == 'b'; }
+ bool is_e(char c) const { return c == 'e'; }
+ bool is_f(char c) const { return c == 'f'; }
+ bool is_l(char c) const { return c == 'l'; }
+ bool is_n(char c) const { return c == 'n'; }
+ bool is_r(char c) const { return c == 'r'; }
+ bool is_s(char c) const { return c == 's'; }
+ bool is_t(char c) const { return c == 't'; }
+ bool is_u(char c) const { return c == 'u'; }
+
+ int decode_hexdigit(char c) {
+ if (c >= '0' && c <= '9') return c - '0';
+ if (c >= 'A' && c <= 'F') return c - 'A' + 10;
+ if (c >= 'a' && c <= 'f') return c - 'a' + 10;
+ return -1;
+ }
+ };
+
+ struct utf8_utf8_encoding : external_ascii_superset_encoding
+ {
+ typedef char internal_char;
+
+ template <typename Iterator>
+ boost::iterator_range<Iterator>
+ to_internal(Iterator first, Iterator last) const {
+ return boost::make_iterator_range(first, last);
+ }
+
+ char to_internal_trivial(char c) const {
+ assert(c <= 0x7f);
+ return c;
+ }
+
+ template <typename Iterator, typename Sentinel,
+ typename EncodingErrorFn>
+ void skip_codepoint(Iterator& cur, Sentinel end,
+ EncodingErrorFn error_fn) const {
+ transcode_codepoint(cur, end, DoNothing(), error_fn);
+ }
+
+ template <typename Iterator, typename Sentinel, typename TranscodedFn,
+ typename EncodingErrorFn>
+ void transcode_codepoint(Iterator& cur, Sentinel end,
+ TranscodedFn transcoded_fn, EncodingErrorFn error_fn) const {
+ unsigned char c = *cur;
+ ++cur;
+ if (c <= 0x7f) {
+ // Solo byte, filter out disallowed codepoints.
+ if (c < 0x20) {
+ error_fn();
+ }
+ transcoded_fn(c);
+ return;
+ }
+ int trailing = trail_table(c);
+ if (trailing == -1) {
+ // Standalone trailing byte or overly long sequence.
+ error_fn();
+ }
+ transcoded_fn(c);
+ for (int i = 0; i < trailing; ++i) {
+ if (cur == end || !is_trail(*cur)) {
+ error_fn();
+ }
+ transcoded_fn(*cur);
+ ++cur;
+ }
+ }
+
+ template <typename TranscodedFn>
+ void feed_codepoint(unsigned codepoint,
+ TranscodedFn transcoded_fn) const {
+ if (codepoint <= 0x7f) {
+ transcoded_fn(static_cast<char>(codepoint));
+ } else if (codepoint <= 0x7ff) {
+ transcoded_fn(static_cast<char>(0xc0 | (codepoint >> 6)));
+ transcoded_fn(trail(codepoint));
+ } else if (codepoint <= 0xffff) {
+ transcoded_fn(static_cast<char>(0xe0 | (codepoint >> 12)));
+ transcoded_fn(trail(codepoint >> 6));
+ transcoded_fn(trail(codepoint));
+ } else if (codepoint <= 0x10ffff) {
+ transcoded_fn(static_cast<char>(0xf0 | (codepoint >> 18)));
+ transcoded_fn(trail(codepoint >> 12));
+ transcoded_fn(trail(codepoint >> 6));
+ transcoded_fn(trail(codepoint));
+ }
+ }
+
+ private:
+ struct DoNothing {
+ void operator ()(char) const {}
+ };
+
+ bool is_trail(unsigned char c) const {
+ return (c & 0xc0) == 0x80;
+ }
+
+ int trail_table(unsigned char c) const {
+ static const signed char table[] = {
+ /* not a lead byte */
+ /* 0x10???sss */ -1, -1, -1, -1, -1, -1, -1, -1,
+ /* 0x110??sss */ 1, 1, 1, 1, /* 1 trailing byte */
+ /* 0x1110?sss */ 2, 2, /* 2 trailing bytes */
+ /* 0x11110sss */ 3, /* 3 trailing bytes */
+ /* 0x11111sss */ -1 /* 4 or 5 trailing bytes, disallowed */
+ };
+ return table[(c & 0x7f) >> 3];
+ }
+
+ char trail(unsigned unmasked) const {
+ return static_cast<char>(0x80 | (unmasked & 0x3f));
+ }
+ };
+
+}}}}
+
+#endif
diff --git a/boost/property_tree/detail/json_parser/parser.hpp b/boost/property_tree/detail/json_parser/parser.hpp
new file mode 100644
index 0000000000..c44b99291d
--- /dev/null
+++ b/boost/property_tree/detail/json_parser/parser.hpp
@@ -0,0 +1,524 @@
+#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_PARSER_HPP
+#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_PARSER_HPP
+
+#include <boost/property_tree/detail/json_parser_error.hpp>
+
+#include <boost/bind.hpp>
+#include <boost/format.hpp>
+
+#include <iterator>
+#include <sstream>
+#include <string>
+
+namespace boost { namespace property_tree {
+ namespace json_parser { namespace detail
+{
+
+ template <typename Encoding, typename Iterator, typename Sentinel>
+ class source
+ {
+ public:
+ typedef typename std::iterator_traits<Iterator>::value_type
+ code_unit;
+ typedef bool (Encoding::*encoding_predicate)(code_unit c) const;
+
+ explicit source(Encoding& encoding) : encoding(encoding) {}
+
+ template <typename Range>
+ void set_input(const std::string& filename, const Range& r)
+ {
+ this->filename = filename;
+ cur = r.begin();
+ end = r.end();
+ line = 1;
+ offset = 0;
+ }
+
+ bool done() const { return cur == end; }
+
+ void parse_error(const char* msg) {
+ BOOST_PROPERTY_TREE_THROW(
+ json_parser_error(msg, filename, line));
+ }
+
+ void next() {
+ if (encoding.is_nl(*cur)) {
+ ++line;
+ offset = 0;
+ } else {
+ ++offset;
+ }
+ ++cur;
+ }
+
+ template <typename Action>
+ bool have(encoding_predicate p, Action& a) {
+ bool found = cur != end && (encoding.*p)(*cur);
+ if (found) {
+ a(*cur);
+ next();
+ }
+ return found;
+ }
+
+ bool have(encoding_predicate p) {
+ DoNothing n;
+ return have(p, n);
+ }
+
+ template <typename Action>
+ void expect(encoding_predicate p, const char* msg, Action& a) {
+ if (!have(p, a)) {
+ parse_error(msg);
+ }
+ }
+
+ void expect(encoding_predicate p, const char* msg) {
+ DoNothing n;
+ expect(p, msg, n);
+ }
+
+ code_unit need_cur(const char* msg) {
+ if (cur == end) {
+ parse_error(msg);
+ }
+ return *cur;
+ }
+
+ Iterator& raw_cur() { return cur; }
+ Sentinel raw_end() { return end; }
+
+ private:
+ struct DoNothing {
+ void operator ()(code_unit) const {}
+ };
+
+ Encoding& encoding;
+ Iterator cur;
+ Sentinel end;
+ std::string filename;
+ int line;
+ int offset;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator,
+ typename = typename std::iterator_traits<Iterator>
+ ::iterator_category>
+ class number_callback_adapter
+ {
+ public:
+ number_callback_adapter(Callbacks& callbacks, Encoding& encoding,
+ Iterator& cur)
+ : callbacks(callbacks), encoding(encoding), first(cur), cur(cur)
+ {}
+
+ void operator ()(typename Encoding::external_char) {}
+
+ void finish() const {
+ callbacks.on_number(encoding.to_internal(first, cur));
+ }
+
+ private:
+ number_callback_adapter(const number_callback_adapter&);
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ Iterator first;
+ Iterator& cur;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator>
+ class number_callback_adapter<Callbacks, Encoding, Iterator,
+ std::input_iterator_tag>
+ {
+ public:
+ number_callback_adapter(Callbacks& callbacks, Encoding& encoding,
+ Iterator&)
+ : callbacks(callbacks), encoding(encoding), first(true)
+ {}
+
+ void operator ()(typename Encoding::external_char c) {
+ if (first) {
+ callbacks.on_begin_number();
+ first = false;
+ }
+ callbacks.on_digit(encoding.to_internal_trivial(c));
+ }
+
+ void finish() const {
+ callbacks.on_end_number();
+ }
+ private:
+ number_callback_adapter(const number_callback_adapter&);
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ bool first;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator,
+ typename = typename std::iterator_traits<Iterator>
+ ::iterator_category>
+ class string_callback_adapter
+ {
+ public:
+ string_callback_adapter(Callbacks& callbacks, Encoding& encoding,
+ Iterator& cur)
+ : callbacks(callbacks), encoding(encoding), cur(cur),
+ run_begin(cur)
+ {}
+
+ void start_run() {
+ run_begin = cur;
+ }
+
+ void finish_run() {
+ callbacks.on_code_units(encoding.to_internal(run_begin, cur));
+ }
+
+ template <typename Sentinel, typename EncodingErrorFn>
+ void process_codepoint(Sentinel end, EncodingErrorFn error_fn) {
+ encoding.skip_codepoint(cur, end, error_fn);
+ }
+
+ private:
+ string_callback_adapter(const string_callback_adapter&);
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ Iterator& cur;
+ Iterator run_begin;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator>
+ class string_callback_adapter<Callbacks, Encoding, Iterator,
+ std::input_iterator_tag>
+ {
+ public:
+ string_callback_adapter(Callbacks& callbacks, Encoding& encoding,
+ Iterator& cur)
+ : callbacks(callbacks), encoding(encoding), cur(cur)
+ {}
+
+ void start_run() {}
+
+ void finish_run() {}
+
+ template <typename Sentinel, typename EncodingErrorFn>
+ void process_codepoint(Sentinel end, EncodingErrorFn error_fn) {
+ encoding.transcode_codepoint(cur, end,
+ boost::bind(&Callbacks::on_code_unit,
+ boost::ref(callbacks), _1),
+ error_fn);
+ }
+
+ private:
+ string_callback_adapter(const string_callback_adapter&);
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ Iterator& cur;
+ };
+
+ template <typename Callbacks, typename Encoding, typename Iterator,
+ typename Sentinel>
+ class parser
+ {
+ typedef detail::number_callback_adapter<Callbacks, Encoding, Iterator>
+ number_adapter;
+ typedef detail::string_callback_adapter<Callbacks, Encoding, Iterator>
+ string_adapter;
+ typedef detail::source<Encoding, Iterator, Sentinel> source;
+ typedef typename source::code_unit code_unit;
+
+ public:
+ parser(Callbacks& callbacks, Encoding& encoding)
+ : callbacks(callbacks), encoding(encoding), src(encoding)
+ {}
+
+ template <typename Range>
+ void set_input(const std::string& filename, const Range& r) {
+ src.set_input(filename, r);
+ }
+
+ void finish() {
+ skip_ws();
+ if (!src.done()) {
+ parse_error("garbage after data");
+ }
+ }
+
+ void parse_value() {
+ if (parse_object()) return;
+ if (parse_array()) return;
+ if (parse_string()) return;
+ if (parse_boolean()) return;
+ if (parse_null()) return;
+ if (parse_number()) return;
+ parse_error("expected value");
+ }
+
+ bool parse_null() {
+ skip_ws();
+ if (!have(&Encoding::is_n)) {
+ return false;
+ }
+ expect(&Encoding::is_u, "expected 'null'");
+ expect(&Encoding::is_l, "expected 'null'");
+ expect(&Encoding::is_l, "expected 'null'");
+ callbacks.on_null();
+ return true;
+ }
+
+ bool parse_boolean() {
+ skip_ws();
+ if (have(&Encoding::is_t)) {
+ expect(&Encoding::is_r, "expected 'true'");
+ expect(&Encoding::is_u, "expected 'true'");
+ expect(&Encoding::is_e, "expected 'true'");
+ callbacks.on_boolean(true);
+ return true;
+ }
+ if (have(&Encoding::is_f)) {
+ expect(&Encoding::is_a, "expected 'false'");
+ expect(&Encoding::is_l, "expected 'false'");
+ expect(&Encoding::is_s, "expected 'false'");
+ expect(&Encoding::is_e, "expected 'false'");
+ callbacks.on_boolean(false);
+ return true;
+ }
+ return false;
+ }
+
+ bool parse_number() {
+ skip_ws();
+
+ number_adapter adapter(callbacks, encoding, src.raw_cur());
+ bool started = false;
+ if (have(&Encoding::is_minus, adapter)) {
+ started = true;
+ }
+ if (!have(&Encoding::is_0, adapter) && !parse_int_part(adapter)) {
+ if (started) {
+ parse_error("expected digits after -");
+ }
+ return false;
+ }
+ parse_frac_part(adapter);
+ parse_exp_part(adapter);
+ adapter.finish();
+ return true;
+ }
+
+ bool parse_string() {
+ skip_ws();
+
+ if (!have(&Encoding::is_quote)) {
+ return false;
+ }
+
+ callbacks.on_begin_string();
+ string_adapter adapter(callbacks, encoding, src.raw_cur());
+ while (!encoding.is_quote(need_cur("unterminated string"))) {
+ if (encoding.is_backslash(*src.raw_cur())) {
+ adapter.finish_run();
+ next();
+ parse_escape();
+ adapter.start_run();
+ } else {
+ adapter.process_codepoint(src.raw_end(),
+ boost::bind(&parser::parse_error,
+ this, "invalid code sequence"));
+ }
+ }
+ adapter.finish_run();
+ callbacks.on_end_string();
+ next();
+ return true;
+ }
+
+ bool parse_array() {
+ skip_ws();
+
+ if (!have(&Encoding::is_open_bracket)) {
+ return false;
+ }
+
+ callbacks.on_begin_array();
+ skip_ws();
+ if (have(&Encoding::is_close_bracket)) {
+ callbacks.on_end_array();
+ return true;
+ }
+ do {
+ parse_value();
+ skip_ws();
+ } while (have(&Encoding::is_comma));
+ expect(&Encoding::is_close_bracket, "expected ']' or ','");
+ callbacks.on_end_array();
+ return true;
+ }
+
+ bool parse_object() {
+ skip_ws();
+
+ if (!have(&Encoding::is_open_brace)) {
+ return false;
+ }
+
+ callbacks.on_begin_object();
+ skip_ws();
+ if (have(&Encoding::is_close_brace)) {
+ callbacks.on_end_object();
+ return true;
+ }
+ do {
+ if (!parse_string()) {
+ parse_error("expected key string");
+ }
+ skip_ws();
+ expect(&Encoding::is_colon, "expected ':'");
+ parse_value();
+ skip_ws();
+ } while (have(&Encoding::is_comma));
+ expect(&Encoding::is_close_brace, "expected '}' or ','");
+ callbacks.on_end_object();
+ return true;
+ }
+
+ private:
+ typedef typename source::encoding_predicate encoding_predicate;
+
+ void parse_error(const char* msg) { src.parse_error(msg); }
+ void next() { src.next(); }
+ template <typename Action>
+ bool have(encoding_predicate p, Action& a) { return src.have(p, a); }
+ bool have(encoding_predicate p) { return src.have(p); }
+ template <typename Action>
+ void expect(encoding_predicate p, const char* msg, Action& a) {
+ src.expect(p, msg, a);
+ }
+ void expect(encoding_predicate p, const char* msg) {
+ src.expect(p, msg);
+ }
+ code_unit need_cur(const char* msg) { return src.need_cur(msg); }
+
+ void skip_ws() {
+ while (have(&Encoding::is_ws)) {
+ }
+ }
+
+ bool parse_int_part(number_adapter& action) {
+ if (!have(&Encoding::is_digit0, action)) {
+ return false;
+ }
+ parse_digits(action);
+ return true;
+ }
+
+ void parse_frac_part(number_adapter& action) {
+ if (!have(&Encoding::is_dot, action)) {
+ return;
+ }
+ expect(&Encoding::is_digit, "need at least one digit after '.'",
+ action);
+ parse_digits(action);
+ }
+
+ void parse_exp_part(number_adapter& action) {
+ if (!have(&Encoding::is_eE, action)) {
+ return;
+ }
+ have(&Encoding::is_plusminus, action);
+ expect(&Encoding::is_digit, "need at least one digit in exponent",
+ action);
+ parse_digits(action);
+ }
+
+ void parse_digits(number_adapter& action) {
+ while (have(&Encoding::is_digit, action)) {
+ }
+ }
+
+ void parse_escape() {
+ if (have(&Encoding::is_quote)) {
+ feed(0x22);
+ } else if (have(&Encoding::is_backslash)) {
+ feed(0x5c);
+ } else if (have(&Encoding::is_slash)) {
+ feed(0x2f);
+ } else if (have(&Encoding::is_b)) {
+ feed(0x08); // backspace
+ } else if (have(&Encoding::is_f)) {
+ feed(0x0c); // formfeed
+ } else if (have(&Encoding::is_n)) {
+ feed(0x0a); // line feed
+ } else if (have(&Encoding::is_r)) {
+ feed(0x0d); // carriage return
+ } else if (have(&Encoding::is_t)) {
+ feed(0x09); // horizontal tab
+ } else if (have(&Encoding::is_u)) {
+ parse_codepoint_ref();
+ } else {
+ parse_error("invalid escape sequence");
+ }
+ }
+
+ unsigned parse_hex_quad() {
+ unsigned codepoint = 0;
+ for (int i = 0; i < 4; ++i) {
+ int value = encoding.decode_hexdigit(
+ need_cur("invalid escape sequence"));
+ if (value < 0) {
+ parse_error("invalid escape sequence");
+ }
+ codepoint *= 16;
+ codepoint += value;
+ next();
+ }
+ return codepoint;
+ }
+
+ static bool is_surrogate_high(unsigned codepoint) {
+ return (codepoint & 0xfc00) == 0xd800;
+ }
+ static bool is_surrogate_low(unsigned codepoint) {
+ return (codepoint & 0xfc00) == 0xdc00;
+ }
+ static unsigned combine_surrogates(unsigned high, unsigned low) {
+ return 0x010000 + (((high & 0x3ff) << 10) | (low & 0x3ff));
+ }
+
+ void parse_codepoint_ref() {
+ unsigned codepoint = parse_hex_quad();
+ if (is_surrogate_low(codepoint)) {
+ parse_error("invalid codepoint, stray low surrogate");
+ }
+ if (is_surrogate_high(codepoint)) {
+ expect(&Encoding::is_backslash,
+ "invalid codepoint, stray high surrogate");
+ expect(&Encoding::is_u,
+ "expected codepoint reference after high surrogate");
+ int low = parse_hex_quad();
+ if (!is_surrogate_low(low)) {
+ parse_error("expected low surrogate after high surrogate");
+ }
+ codepoint = combine_surrogates(codepoint, low);
+ }
+ feed(codepoint);
+ }
+
+ void feed(unsigned codepoint) {
+ encoding.feed_codepoint(codepoint,
+ boost::bind(&Callbacks::on_code_unit,
+ boost::ref(callbacks), _1));
+ }
+
+ Callbacks& callbacks;
+ Encoding& encoding;
+ source src;
+ };
+
+}}}}
+
+#endif
diff --git a/boost/property_tree/detail/json_parser/read.hpp b/boost/property_tree/detail/json_parser/read.hpp
new file mode 100644
index 0000000000..61c0162781
--- /dev/null
+++ b/boost/property_tree/detail/json_parser/read.hpp
@@ -0,0 +1,55 @@
+// ----------------------------------------------------------------------------
+// Copyright (C) 2015 Sebastian Redl
+//
+// Distributed under the Boost Software License, Version 1.0.
+// (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see www.boost.org
+// ----------------------------------------------------------------------------
+#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP
+#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP
+
+#include <boost/property_tree/detail/json_parser/parser.hpp>
+#include <boost/property_tree/detail/json_parser/narrow_encoding.hpp>
+#include <boost/property_tree/detail/json_parser/wide_encoding.hpp>
+#include <boost/property_tree/detail/json_parser/standard_callbacks.hpp>
+
+#include <boost/range/iterator_range_core.hpp>
+
+#include <istream>
+#include <iterator>
+#include <string>
+
+namespace boost { namespace property_tree {
+ namespace json_parser { namespace detail
+{
+
+ template <typename Ch> struct encoding;
+ template <> struct encoding<char> : utf8_utf8_encoding {};
+ template <> struct encoding<wchar_t> : wide_wide_encoding {};
+
+ template <typename Ptree>
+ void read_json_internal(
+ std::basic_istream<typename Ptree::key_type::value_type> &stream,
+ Ptree &pt, const std::string &filename)
+ {
+ typedef typename Ptree::key_type::value_type char_type;
+ typedef standard_callbacks<Ptree> callbacks_type;
+ typedef detail::encoding<char_type> encoding_type;
+ typedef std::istreambuf_iterator<char_type> iterator;
+ callbacks_type callbacks;
+ encoding_type encoding;
+ detail::parser<callbacks_type, encoding_type, iterator, iterator>
+ parser(callbacks, encoding);
+ parser.set_input(filename,
+ boost::make_iterator_range(iterator(stream), iterator()));
+ parser.parse_value();
+ parser.finish();
+
+ pt.swap(callbacks.output());
+ }
+
+}}}}
+
+#endif
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
diff --git a/boost/property_tree/detail/json_parser/wide_encoding.hpp b/boost/property_tree/detail/json_parser/wide_encoding.hpp
new file mode 100644
index 0000000000..0dec1c03b0
--- /dev/null
+++ b/boost/property_tree/detail/json_parser/wide_encoding.hpp
@@ -0,0 +1,171 @@
+#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WIDE_ENCODING_HPP
+#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_WIDE_ENCODING_HPP
+
+#include <boost/range/iterator_range_core.hpp>
+
+#include <cassert>
+#include <utility>
+
+namespace boost { namespace property_tree {
+ namespace json_parser { namespace detail
+{
+
+ struct external_wide_encoding
+ {
+ typedef wchar_t external_char;
+
+ bool is_nl(wchar_t c) const { return c == L'\n'; }
+ bool is_ws(wchar_t c) const {
+ return c == L' ' || c == L'\t' || c == L'\n' || c == L'\r';
+ }
+
+ bool is_minus(wchar_t c) const { return c == L'-'; }
+ bool is_plusminus(wchar_t c) const { return c == L'+' || c == L'-'; }
+ bool is_dot(wchar_t c) const { return c == L'.'; }
+ bool is_eE(wchar_t c) const { return c == L'e' || c == L'E'; }
+ bool is_0(wchar_t c) const { return c == L'0'; }
+ bool is_digit(wchar_t c) const { return c >= L'0' && c <= L'9'; }
+ bool is_digit0(wchar_t c) const { return c >= L'1' && c <= L'9'; }
+
+ bool is_quote(wchar_t c) const { return c == L'"'; }
+ bool is_backslash(wchar_t c) const { return c == L'\\'; }
+ bool is_slash(wchar_t c) const { return c == L'/'; }
+
+ bool is_comma(wchar_t c) const { return c == L','; }
+ bool is_open_bracket(wchar_t c) const { return c == L'['; }
+ bool is_close_bracket(wchar_t c) const { return c == L']'; }
+ bool is_colon(wchar_t c) const { return c == L':'; }
+ bool is_open_brace(wchar_t c) const { return c == L'{'; }
+ bool is_close_brace(wchar_t c) const { return c == L'}'; }
+
+ bool is_a(wchar_t c) const { return c == L'a'; }
+ bool is_b(wchar_t c) const { return c == L'b'; }
+ bool is_e(wchar_t c) const { return c == L'e'; }
+ bool is_f(wchar_t c) const { return c == L'f'; }
+ bool is_l(wchar_t c) const { return c == L'l'; }
+ bool is_n(wchar_t c) const { return c == L'n'; }
+ bool is_r(wchar_t c) const { return c == L'r'; }
+ bool is_s(wchar_t c) const { return c == L's'; }
+ bool is_t(wchar_t c) const { return c == L't'; }
+ bool is_u(wchar_t c) const { return c == L'u'; }
+
+ int decode_hexdigit(wchar_t c) {
+ if (c >= L'0' && c <= L'9') return c - L'0';
+ if (c >= L'A' && c <= L'F') return c - L'A' + 10;
+ if (c >= L'a' && c <= L'f') return c - L'a' + 10;
+ return -1;
+ }
+ };
+
+ template <bool B> struct is_utf16 {};
+
+ class wide_wide_encoding : public external_wide_encoding
+ {
+ typedef is_utf16<sizeof(wchar_t) == 2> test_utf16;
+ public:
+ typedef wchar_t internal_char;
+
+ template <typename Iterator>
+ boost::iterator_range<Iterator>
+ to_internal(Iterator first, Iterator last) const {
+ return boost::make_iterator_range(first, last);
+ }
+
+ wchar_t to_internal_trivial(wchar_t c) const {
+ assert(!is_surrogate_high(c) && !is_surrogate_low(c));
+ return c;
+ }
+
+ template <typename Iterator, typename Sentinel,
+ typename EncodingErrorFn>
+ void skip_codepoint(Iterator& cur, Sentinel end,
+ EncodingErrorFn error_fn) const {
+ transcode_codepoint(cur, end, DoNothing(), error_fn);
+ }
+
+ template <typename Iterator, typename Sentinel, typename TranscodedFn,
+ typename EncodingErrorFn>
+ void transcode_codepoint(Iterator& cur, Sentinel end,
+ TranscodedFn transcoded_fn, EncodingErrorFn error_fn) const {
+ return transcode_codepoint(cur, end, transcoded_fn, error_fn,
+ test_utf16());
+ }
+
+ template <typename TranscodedFn>
+ void feed_codepoint(unsigned codepoint,
+ TranscodedFn transcoded_fn) const {
+ feed_codepoint(codepoint, transcoded_fn, test_utf16());
+ }
+
+ private:
+ struct DoNothing {
+ void operator ()(wchar_t) const {}
+ };
+
+ template <typename Iterator, typename Sentinel, typename TranscodedFn,
+ typename EncodingErrorFn>
+ void transcode_codepoint(Iterator& cur, Sentinel end,
+ TranscodedFn transcoded_fn,
+ EncodingErrorFn error_fn,
+ is_utf16<false>) const {
+ wchar_t c = *cur;
+ if (c < 0x20) {
+ error_fn();
+ }
+ transcoded_fn(c);
+ ++cur;
+ }
+ template <typename Iterator, typename Sentinel, typename TranscodedFn,
+ typename EncodingErrorFn>
+ void transcode_codepoint(Iterator& cur, Sentinel end,
+ TranscodedFn transcoded_fn,
+ EncodingErrorFn error_fn,
+ is_utf16<true>) const {
+ wchar_t c = *cur;
+ if (c < 0x20) {
+ error_fn();
+ }
+ if (is_surrogate_low(c)) {
+ error_fn();
+ }
+ transcoded_fn(c);
+ ++cur;
+ if (is_surrogate_high(c)) {
+ c = *cur;
+ if (!is_surrogate_low(c)) {
+ error_fn();
+ }
+ transcoded_fn(c);
+ ++cur;
+ }
+ }
+
+ template <typename TranscodedFn>
+ void feed_codepoint(unsigned codepoint, TranscodedFn transcoded_fn,
+ is_utf16<false>) const {
+ transcoded_fn(static_cast<wchar_t>(codepoint));
+ }
+ template <typename TranscodedFn>
+ void feed_codepoint(unsigned codepoint, TranscodedFn transcoded_fn,
+ is_utf16<true>) const {
+ if (codepoint < 0x10000) {
+ transcoded_fn(static_cast<wchar_t>(codepoint));
+ } else {
+ codepoint -= 0x10000;
+ transcoded_fn(static_cast<wchar_t>((codepoint >> 10) | 0xd800));
+ transcoded_fn(static_cast<wchar_t>(
+ (codepoint & 0x3ff) | 0xdc00));
+ }
+ }
+
+ static bool is_surrogate_high(unsigned codepoint) {
+ return (codepoint & 0xfc00) == 0xd800;
+ }
+ static bool is_surrogate_low(unsigned codepoint) {
+ return (codepoint & 0xfc00) == 0xdc00;
+ }
+ };
+
+}}}}
+
+#endif
diff --git a/boost/property_tree/detail/json_parser_read.hpp b/boost/property_tree/detail/json_parser_read.hpp
deleted file mode 100644
index 798552f6f1..0000000000
--- a/boost/property_tree/detail/json_parser_read.hpp
+++ /dev/null
@@ -1,332 +0,0 @@
-// ----------------------------------------------------------------------------
-// Copyright (C) 2002-2006 Marcin Kalicinski
-//
-// Distributed under the Boost Software License, Version 1.0.
-// (See accompanying file LICENSE_1_0.txt or copy at
-// http://www.boost.org/LICENSE_1_0.txt)
-//
-// For more information, see www.boost.org
-// ----------------------------------------------------------------------------
-#ifndef BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP_INCLUDED
-#define BOOST_PROPERTY_TREE_DETAIL_JSON_PARSER_READ_HPP_INCLUDED
-
-//#define BOOST_SPIRIT_DEBUG
-
-#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/detail/ptree_utils.hpp>
-#include <boost/property_tree/detail/json_parser_error.hpp>
-#include <boost/spirit/include/classic.hpp>
-#include <boost/limits.hpp>
-#include <string>
-#include <locale>
-#include <istream>
-#include <vector>
-#include <algorithm>
-
-namespace boost { namespace property_tree { namespace json_parser
-{
-
- ///////////////////////////////////////////////////////////////////////
- // Json parser context
-
- template<class Ptree>
- struct context
- {
- typedef typename Ptree::key_type Str;
- typedef typename Str::value_type Ch;
- typedef typename std::vector<Ch>::iterator It;
-
- Str string;
- Str name;
- Ptree root;
- std::vector<Ptree *> stack;
-
- struct a_object_s
- {
- context &c;
- a_object_s(context &c): c(c) { }
- void operator()(Ch) const
- {
- if (c.stack.empty())
- c.stack.push_back(&c.root);
- else
- {
- Ptree *parent = c.stack.back();
- Ptree *child = &parent->push_back(std::make_pair(c.name, Ptree()))->second;
- c.stack.push_back(child);
- c.name.clear();
- }
- }
- };
-
- struct a_object_e
- {
- context &c;
- a_object_e(context &c): c(c) { }
- void operator()(Ch) const
- {
- BOOST_ASSERT(c.stack.size() >= 1);
- c.stack.pop_back();
- }
- };
-
- struct a_name
- {
- context &c;
- a_name(context &c): c(c) { }
- void operator()(It, It) const
- {
- c.name.swap(c.string);
- c.string.clear();
- }
- };
-
- struct a_string_val
- {
- context &c;
- a_string_val(context &c): c(c) { }
- void operator()(It, It) const
- {
- BOOST_ASSERT(c.stack.size() >= 1);
- c.stack.back()->push_back(std::make_pair(c.name, Ptree(c.string)));
- c.name.clear();
- c.string.clear();
- }
- };
-
- struct a_literal_val
- {
- context &c;
- a_literal_val(context &c): c(c) { }
- void operator()(It b, It e) const
- {
- BOOST_ASSERT(c.stack.size() >= 1);
- c.stack.back()->push_back(std::make_pair(c.name,
- Ptree(Str(b, e))));
- c.name.clear();
- c.string.clear();
- }
- };
-
- struct a_char
- {
- context &c;
- a_char(context &c): c(c) { }
- void operator()(It b, It) const
- {
- c.string += *b;
- }
- };
-
- struct a_escape
- {
- context &c;
- a_escape(context &c): c(c) { }
- void operator()(Ch ch) const
- {
- switch (ch)
- {
- case Ch('\"'): c.string += Ch('\"'); break;
- case Ch('\\'): c.string += Ch('\\'); break;
- case Ch('/'): c.string += Ch('/'); break;
- case Ch('b'): c.string += Ch('\b'); break;
- case Ch('f'): c.string += Ch('\f'); break;
- case Ch('n'): c.string += Ch('\n'); break;
- case Ch('r'): c.string += Ch('\r'); break;
- case Ch('t'): c.string += Ch('\t'); break;
- default: BOOST_ASSERT(0);
- }
- }
- };
-
- struct a_unicode
- {
- context &c;
- a_unicode(context &c): c(c) { }
- void operator()(unsigned long u) const
- {
- u = (std::min)(u, static_cast<unsigned long>((std::numeric_limits<Ch>::max)()));
- c.string += Ch(u);
- }
- };
-
- };
-
- ///////////////////////////////////////////////////////////////////////
- // Json grammar
-
- template<class Ptree>
- struct json_grammar :
- public boost::spirit::classic::grammar<json_grammar<Ptree> >
- {
-
- typedef context<Ptree> Context;
- typedef typename Ptree::key_type Str;
- typedef typename Str::value_type Ch;
-
- mutable Context c;
-
- template<class Scanner>
- struct definition
- {
-
- boost::spirit::classic::rule<Scanner>
- root, object, member, array, item, value, string, number;
- boost::spirit::classic::rule<
- typename boost::spirit::classic::lexeme_scanner<Scanner>::type>
- character, escape;
-
- definition(const json_grammar &self)
- {
-
- using namespace boost::spirit::classic;
- // There's a boost::assertion too, so another explicit using
- // here:
- using boost::spirit::classic::assertion;
-
- // Assertions
- assertion<std::string> expect_root("expected object or array");
- assertion<std::string> expect_eoi("expected end of input");
- assertion<std::string> expect_objclose("expected ',' or '}'");
- assertion<std::string> expect_arrclose("expected ',' or ']'");
- assertion<std::string> expect_name("expected object name");
- assertion<std::string> expect_colon("expected ':'");
- assertion<std::string> expect_value("expected value");
- assertion<std::string> expect_escape("invalid escape sequence");
-
- // JSON grammar rules
- root
- = expect_root(object | array)
- >> expect_eoi(end_p)
- ;
-
- object
- = ch_p('{')[typename Context::a_object_s(self.c)]
- >> (ch_p('}')[typename Context::a_object_e(self.c)]
- | (list_p(member, ch_p(','))
- >> expect_objclose(ch_p('}')[typename Context::a_object_e(self.c)])
- )
- )
- ;
-
- member
- = expect_name(string[typename Context::a_name(self.c)])
- >> expect_colon(ch_p(':'))
- >> expect_value(value)
- ;
-
- array
- = ch_p('[')[typename Context::a_object_s(self.c)]
- >> (ch_p(']')[typename Context::a_object_e(self.c)]
- | (list_p(item, ch_p(','))
- >> expect_arrclose(ch_p(']')[typename Context::a_object_e(self.c)])
- )
- )
- ;
-
- item
- = expect_value(value)
- ;
-
- value
- = string[typename Context::a_string_val(self.c)]
- | (number | str_p("true") | "false" | "null")[typename Context::a_literal_val(self.c)]
- | object
- | array
- ;
-
- number
- = !ch_p("-") >>
- (ch_p("0") | (range_p(Ch('1'), Ch('9')) >> *digit_p)) >>
- !(ch_p(".") >> +digit_p) >>
- !(chset_p(detail::widen<Str>("eE").c_str()) >>
- !chset_p(detail::widen<Str>("-+").c_str()) >>
- +digit_p)
- ;
-
- string
- = +(lexeme_d[confix_p('\"', *character, '\"')])
- ;
-
- character
- = (anychar_p - "\\" - "\"")
- [typename Context::a_char(self.c)]
- | ch_p("\\") >> expect_escape(escape)
- ;
-
- escape
- = chset_p(detail::widen<Str>("\"\\/bfnrt").c_str())
- [typename Context::a_escape(self.c)]
- | 'u' >> uint_parser<unsigned long, 16, 4, 4>()
- [typename Context::a_unicode(self.c)]
- ;
-
- // Debug
- BOOST_SPIRIT_DEBUG_RULE(root);
- BOOST_SPIRIT_DEBUG_RULE(object);
- BOOST_SPIRIT_DEBUG_RULE(member);
- BOOST_SPIRIT_DEBUG_RULE(array);
- BOOST_SPIRIT_DEBUG_RULE(item);
- BOOST_SPIRIT_DEBUG_RULE(value);
- BOOST_SPIRIT_DEBUG_RULE(string);
- BOOST_SPIRIT_DEBUG_RULE(number);
- BOOST_SPIRIT_DEBUG_RULE(escape);
- BOOST_SPIRIT_DEBUG_RULE(character);
-
- }
-
- const boost::spirit::classic::rule<Scanner> &start() const
- {
- return root;
- }
-
- };
-
- };
-
- template<class It, class Ch>
- unsigned long count_lines(It begin, It end)
- {
- return static_cast<unsigned long>(std::count(begin, end, Ch('\n')) + 1);
- }
-
- template<class Ptree>
- void read_json_internal(std::basic_istream<typename Ptree::key_type::value_type> &stream,
- Ptree &pt,
- const std::string &filename)
- {
-
- using namespace boost::spirit::classic;
- typedef typename Ptree::key_type::value_type Ch;
- typedef typename std::vector<Ch>::iterator It;
-
- // Load data into vector
- std::vector<Ch> v(std::istreambuf_iterator<Ch>(stream.rdbuf()),
- std::istreambuf_iterator<Ch>());
- if (!stream.good())
- BOOST_PROPERTY_TREE_THROW(json_parser_error("read error", filename, 0));
-
- // Prepare grammar
- json_grammar<Ptree> g;
-
- // Parse
- try
- {
- parse_info<It> pi = parse(v.begin(), v.end(), g,
- space_p | comment_p("//") | comment_p("/*", "*/"));
- if (!pi.hit || !pi.full)
- BOOST_PROPERTY_TREE_THROW((parser_error<std::string, It>(v.begin(), "syntax error")));
- }
- catch (parser_error<std::string, It> &e)
- {
- BOOST_PROPERTY_TREE_THROW(json_parser_error(e.descriptor, filename, count_lines<It, Ch>(v.begin(), e.where)));
- }
-
- // Swap grammar context root and pt
- pt.swap(g.c.root);
-
- }
-
-} } }
-
-#endif
diff --git a/boost/property_tree/detail/rapidxml.hpp b/boost/property_tree/detail/rapidxml.hpp
index d3615c1193..9e3d76af9d 100644
--- a/boost/property_tree/detail/rapidxml.hpp
+++ b/boost/property_tree/detail/rapidxml.hpp
@@ -65,7 +65,7 @@ namespace boost { namespace property_tree { namespace detail {namespace rapidxml
//! Gets pointer to character data where error happened.
//! Ch should be the same as char type of xml_document that produced the error.
- //! \return Pointer to location within the parsed string where error occured.
+ //! \return Pointer to location within the parsed string where error occurred.
template<class Ch>
Ch *where() const
{
diff --git a/boost/property_tree/json_parser.hpp b/boost/property_tree/json_parser.hpp
index d3bc32edb1..d8a3e1025f 100644
--- a/boost/property_tree/json_parser.hpp
+++ b/boost/property_tree/json_parser.hpp
@@ -1,5 +1,6 @@
// ----------------------------------------------------------------------------
// Copyright (C) 2002-2006 Marcin Kalicinski
+// Copyright (C) 2015 Sebastian Redl
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
@@ -11,9 +12,9 @@
#define BOOST_PROPERTY_TREE_JSON_PARSER_HPP_INCLUDED
#include <boost/property_tree/ptree.hpp>
-#include <boost/property_tree/detail/json_parser_read.hpp>
-#include <boost/property_tree/detail/json_parser_write.hpp>
#include <boost/property_tree/detail/json_parser_error.hpp>
+#include <boost/property_tree/detail/json_parser/read.hpp>
+#include <boost/property_tree/detail/json_parser_write.hpp>
#include <fstream>
#include <string>
@@ -42,7 +43,7 @@ namespace boost { namespace property_tree { namespace json_parser
> &stream,
Ptree &pt)
{
- read_json_internal(stream, pt, std::string());
+ detail::read_json_internal(stream, pt, std::string());
}
/**
@@ -71,7 +72,7 @@ namespace boost { namespace property_tree { namespace json_parser
BOOST_PROPERTY_TREE_THROW(json_parser_error(
"cannot open file", filename, 0));
stream.imbue(loc);
- read_json_internal(stream, pt, filename);
+ detail::read_json_internal(stream, pt, filename);
}
/**
diff --git a/boost/property_tree/ptree_serialization.hpp b/boost/property_tree/ptree_serialization.hpp
index 4dc916c0d0..a8181ca3b7 100644
--- a/boost/property_tree/ptree_serialization.hpp
+++ b/boost/property_tree/ptree_serialization.hpp
@@ -14,7 +14,7 @@
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/collections_save_imp.hpp>
-#include <boost/serialization/collections_load_imp.hpp>
+#include <boost/serialization/detail/stack_constructor.hpp>
#include <boost/serialization/split_free.hpp>
#include <boost/serialization/utility.hpp>
@@ -48,6 +48,41 @@ namespace boost { namespace property_tree
ar << make_nvp("data", t.data());
}
+ namespace detail
+ {
+ template <class Archive, class K, class D, class C>
+ inline void load_children(Archive &ar,
+ basic_ptree<K, D, C> &t)
+ {
+ namespace bsl = boost::serialization;
+ namespace bsa = boost::archive;
+
+ typedef basic_ptree<K, D, C> tree;
+ typedef typename tree::value_type value_type;
+
+ bsl::collection_size_type count;
+ ar >> BOOST_SERIALIZATION_NVP(count);
+ bsl::item_version_type item_version(0);
+ const bsa::library_version_type library_version(
+ ar.get_library_version()
+ );
+ if(bsa::library_version_type(3) < library_version){
+ ar >> BOOST_SERIALIZATION_NVP(item_version);
+ }
+ // Can't use the serialization helper, it expects resize() to exist
+ // for default-constructible elements.
+ // This is a copy/paste of the fallback version.
+ t.clear();
+ while(count-- > 0){
+ bsl::detail::stack_construct<Archive, value_type>
+ u(ar, item_version);
+ ar >> bsl::make_nvp("item", u.reference());
+ t.push_back(u.reference());
+ ar.reset_object_address(& t.back() , & u.reference());
+ }
+ }
+ }
+
/**
* De-serialize the property tree to the given archive.
* @note In addition to de-serializing from regular archives, this supports
@@ -66,18 +101,10 @@ namespace boost { namespace property_tree
basic_ptree<K, D, C> &t,
const unsigned int file_version)
{
- using namespace boost::serialization;
- // Load children
- stl::load_collection<Archive,
- basic_ptree<K, D, C>,
- stl::archive_input_seq<Archive,
- basic_ptree<K, D, C> >,
- stl::no_reserve_imp<
- basic_ptree<K, D, C> >
- >(ar, t);
+ namespace bsl = boost::serialization;
- // Load data (must be after load_collection, as it calls clear())
- ar >> make_nvp("data", t.data());
+ detail::load_children(ar, t);
+ ar >> bsl::make_nvp("data", t.data());
}
/**