Squashed 'third_party/boostorg/property_tree/' content from commit bdfe275

Change-Id: I075a5e242aaddc356ecc81e756c4a0907fc38130
git-subtree-dir: third_party/boostorg/property_tree
git-subtree-split: bdfe275d172ac30bc5e89a6375a5a64dea20b3c0
diff --git a/examples/Jamfile.v2 b/examples/Jamfile.v2
new file mode 100644
index 0000000..07c382a
--- /dev/null
+++ b/examples/Jamfile.v2
@@ -0,0 +1,12 @@
+# Boost PropertyTree Library Example Jamfile
+# Copyright (c) 2013 Sebastian Redl
+# Distributed under the Boost Software License, Version 1.0.
+# See http://www.boost.org/LICENSE_1_0.txt
+
+project
+    : requirements
+      <include>../../../
+    :
+		;
+
+exe debug_settings : debug_settings.cpp ;
diff --git a/examples/custom_data_type.cpp b/examples/custom_data_type.cpp
new file mode 100644
index 0000000..dbc905f
--- /dev/null
+++ b/examples/custom_data_type.cpp
@@ -0,0 +1,88 @@
+// ----------------------------------------------------------------------------
+// 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
+// ----------------------------------------------------------------------------
+
+// This example shows what need to be done to customize data_type of ptree.
+//
+// It creates my_ptree type, which is a basic_ptree having boost::any as its data
+// container (instead of std::string that standard ptree has).
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/any.hpp>
+#include <list>
+#include <string>
+#include <iostream>
+
+// Custom translator that works with boost::any instead of std::string
+template <class Ext, class Int = boost::any>
+struct variant_translator
+{
+    typedef Ext external_type;
+    typedef Int internal_type;
+
+    external_type
+    get_value(const internal_type &value) const
+    {
+        return boost::any_cast<external_type>(value);
+    }
+    internal_type
+    put_value(const external_type &value) const
+    {
+        return value;
+    }
+};
+
+int main()
+{
+    
+    using namespace boost::property_tree;
+    
+    // Property_tree with boost::any as data type
+    // Key type:        std::string
+    // Data type:       boost::any
+    // Key comparison:  default (std::less<std::string>)
+    typedef basic_ptree<std::string, boost::any> my_ptree;
+    my_ptree pt;
+
+    // Put/get int value
+    typedef variant_translator<int> int_tran;
+    pt.put("int value", 3, int_tran());
+    int int_value = pt.get<int>("int value", int_tran());
+    std::cout << "Int value: " << int_value << "\n";
+
+    // Put/get string value
+    typedef variant_translator<std::string> string_tran;
+    pt.put<std::string>("string value", "foo bar", string_tran());
+    std::string string_value = pt.get<std::string>(
+        "string value"
+      , string_tran()
+    );
+    std::cout << "String value: " << string_value << "\n";
+
+    // Put/get list<int> value
+    typedef std::list<int> intlist;
+    typedef variant_translator<intlist> intlist_tran;
+    int list_data[] = { 1, 2, 3, 4, 5 };
+    pt.put<intlist>(
+        "list value"
+      , intlist(
+            list_data
+          , list_data + sizeof(list_data) / sizeof(*list_data)
+        )
+      , intlist_tran()
+    );
+    intlist list_value = pt.get<intlist>(
+        "list value"
+      , intlist_tran()
+    );
+    std::cout << "List value: ";
+    for (intlist::iterator it = list_value.begin(); it != list_value.end(); ++it)
+        std::cout << *it << ' ';
+    std::cout << '\n';
+}
diff --git a/examples/debug_settings.cpp b/examples/debug_settings.cpp
new file mode 100644
index 0000000..5e21429
--- /dev/null
+++ b/examples/debug_settings.cpp
@@ -0,0 +1,95 @@
+// ----------------------------------------------------------------------------
+// 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
+// ----------------------------------------------------------------------------
+
+//[debug_settings_includes
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/xml_parser.hpp>
+#include <boost/foreach.hpp>
+#include <string>
+#include <set>
+#include <exception>
+#include <iostream>
+namespace pt = boost::property_tree;
+//]
+//[debug_settings_data
+struct debug_settings
+{
+    std::string m_file;               // log filename
+    int m_level;                      // debug level
+    std::set<std::string> m_modules;  // modules where logging is enabled
+    void load(const std::string &filename);
+    void save(const std::string &filename);
+};
+//]
+//[debug_settings_load
+void debug_settings::load(const std::string &filename)
+{
+    // Create empty property tree object
+    pt::ptree tree;
+
+    // Parse the XML into the property tree.
+    pt::read_xml(filename, tree);
+
+    // Use the throwing version of get to find the debug filename.
+    // If the path cannot be resolved, an exception is thrown.
+    m_file = tree.get<std::string>("debug.filename");
+
+    // Use the default-value version of get to find the debug level.
+    // Note that the default value is used to deduce the target type.
+    m_level = tree.get("debug.level", 0);
+
+    // Use get_child to find the node containing the modules, and iterate over
+    // its children. If the path cannot be resolved, get_child throws.
+    // A C++11 for-range loop would also work.
+    BOOST_FOREACH(pt::ptree::value_type &v, tree.get_child("debug.modules")) {
+        // The data function is used to access the data stored in a node.
+        m_modules.insert(v.second.data());
+    }
+
+}
+//]
+//[debug_settings_save
+void debug_settings::save(const std::string &filename)
+{
+    // Create an empty property tree object.
+    pt::ptree tree;
+
+    // Put the simple values into the tree. The integer is automatically
+    // converted to a string. Note that the "debug" node is automatically
+    // created if it doesn't exist.
+    tree.put("debug.filename", m_file);
+    tree.put("debug.level", m_level);
+
+    // Add all the modules. Unlike put, which overwrites existing nodes, add
+    // adds a new node at the lowest level, so the "modules" node will have
+    // multiple "module" children.
+    BOOST_FOREACH(const std::string &name, m_modules)
+        tree.add("debug.modules.module", name);
+
+    // Write property tree to XML file
+    pt::write_xml(filename, tree);
+}
+//]
+
+int main()
+{
+    try
+    {
+        debug_settings ds;
+        ds.load("debug_settings.xml");
+        ds.save("debug_settings_out.xml");
+        std::cout << "Success\n";
+    }
+    catch (std::exception &e)
+    {
+        std::cout << "Error: " << e.what() << "\n";
+    }
+    return 0;
+}
diff --git a/examples/debug_settings.xml b/examples/debug_settings.xml
new file mode 100644
index 0000000..2ac170e
--- /dev/null
+++ b/examples/debug_settings.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2006 Marcin Kalicinski
+Distributed under the Boost Software License, Version 1.0.
+See http://www.boost.org/LICENSE_1_0.txt
+-->
+<debug>
+    <filename>debug.log</filename>
+    <modules>
+        <module>Finance</module>
+        <module>Admin</module>
+        <module>HR</module>
+    </modules>
+    <level>2</level>
+</debug>
diff --git a/examples/empty_ptree_trick.cpp b/examples/empty_ptree_trick.cpp
new file mode 100644
index 0000000..37285b2
--- /dev/null
+++ b/examples/empty_ptree_trick.cpp
@@ -0,0 +1,71 @@
+// ----------------------------------------------------------------------------
+// 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
+// ----------------------------------------------------------------------------
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/info_parser.hpp>
+#include <iostream>
+#include <iomanip>
+#include <string>
+
+using namespace boost::property_tree;
+
+// Process settings using empty ptree trick. Note that it is considerably simpler 
+// than version which does not use the "trick"
+void process_settings(const std::string &filename)
+{
+    ptree pt;
+    read_info(filename, pt);    
+    const ptree &settings = pt.get_child("settings", empty_ptree<ptree>());
+    std::cout << "\n    Processing " << filename << std::endl;
+    std::cout << "        Setting 1 is " << settings.get("setting1", 0) << std::endl;
+    std::cout << "        Setting 2 is " << settings.get("setting2", 0.0) << std::endl;
+    std::cout << "        Setting 3 is " << settings.get("setting3", "default") << std::endl;
+}
+
+// Process settings not using empty ptree trick. This one must duplicate much of the code.
+void process_settings_without_trick(const std::string &filename)
+{
+    ptree pt;
+    read_info(filename, pt);    
+    if (boost::optional<ptree &> settings = pt.get_child_optional("settings"))
+    {
+        std::cout << "\n    Processing " << filename << std::endl;
+        std::cout << "        Setting 1 is " << settings.get().get("setting1", 0) << std::endl;
+        std::cout << "        Setting 2 is " << settings.get().get("setting2", 0.0) << std::endl;
+        std::cout << "        Setting 3 is " << settings.get().get("setting3", "default") << std::endl;
+    }
+    else
+    {
+        std::cout << "\n    Processing " << filename << std::endl;
+        std::cout << "        Setting 1 is " << 0 << std::endl;
+        std::cout << "        Setting 2 is " << 0.0 << std::endl;
+        std::cout << "        Setting 3 is " << "default" << std::endl;
+    }
+}
+
+int main()
+{
+    try
+    {
+        std::cout << "Processing settings with empty-ptree-trick:\n";
+        process_settings("settings_fully-existent.info");
+        process_settings("settings_partially-existent.info");
+        process_settings("settings_non-existent.info");
+        std::cout << "\nProcessing settings without empty-ptree-trick:\n";
+        process_settings_without_trick("settings_fully-existent.info");
+        process_settings_without_trick("settings_partially-existent.info");
+        process_settings_without_trick("settings_non-existent.info");
+    }
+    catch (std::exception &e)
+    {
+        std::cout << "Error: " << e.what() << "\n";
+    }
+    return 0;
+}
diff --git a/examples/info_grammar_spirit.cpp b/examples/info_grammar_spirit.cpp
new file mode 100644
index 0000000..0702534
--- /dev/null
+++ b/examples/info_grammar_spirit.cpp
@@ -0,0 +1,152 @@
+// ----------------------------------------------------------------------------
+// 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
+// ----------------------------------------------------------------------------
+
+/* This is grammar of INFO file format written in form of boost::spirit rules.
+   For simplicity, it does not parse #include directive. Note that INFO parser 
+   included in property_tree library does not use Spirit.
+*/
+
+//#define BOOST_SPIRIT_DEBUG        // uncomment to enable debug output
+#include <boost/spirit.hpp>
+
+struct info_grammar: public boost::spirit::grammar<info_grammar>
+{
+    
+    template<class Scanner>
+    struct definition
+    {
+        
+        boost::spirit::rule<typename boost::spirit::lexeme_scanner<Scanner>::type> chr, qchr, escape_seq;
+        boost::spirit::rule<Scanner> string, qstring, cstring, key, value, entry, info;
+
+        definition(const info_grammar &self)
+        {
+
+            using namespace boost::spirit;
+
+            escape_seq = chset_p("0abfnrtv\"\'\\");
+            chr = (anychar_p - space_p - '\\' - '{' - '}' - '#' - '"') | ('\\' >> escape_seq);
+            qchr = (anychar_p - '"' - '\n' - '\\') | ('\\' >> escape_seq);
+            string = lexeme_d[+chr];
+            qstring = lexeme_d['"' >> *qchr >> '"'];
+            cstring = lexeme_d['"' >> *qchr >> '"' >> '\\'];
+            key = string | qstring;
+            value = string | qstring | (+cstring >> qstring) | eps_p;
+            entry = key >> value >> !('{' >> *entry >> '}');
+            info = *entry >> end_p;
+
+            // Debug nodes
+            BOOST_SPIRIT_DEBUG_NODE(escape_seq);
+            BOOST_SPIRIT_DEBUG_NODE(chr);
+            BOOST_SPIRIT_DEBUG_NODE(qchr);
+            BOOST_SPIRIT_DEBUG_NODE(string);
+            BOOST_SPIRIT_DEBUG_NODE(qstring);
+            BOOST_SPIRIT_DEBUG_NODE(key);
+            BOOST_SPIRIT_DEBUG_NODE(value);
+            BOOST_SPIRIT_DEBUG_NODE(entry);
+            BOOST_SPIRIT_DEBUG_NODE(info);
+
+        }
+
+        const boost::spirit::rule<Scanner> &start() const
+        {
+            return info;
+        }
+
+    };
+};
+
+void info_parse(const char *s)
+{
+
+    using namespace boost::spirit;
+
+    // Parse and display result
+    info_grammar g;
+    parse_info<const char *> pi = parse(s, g, space_p | comment_p(";"));
+    std::cout << "Parse result: " << (pi.hit ? "Success" : "Failure") << "\n";
+    
+}
+
+int main()
+{
+
+    // Sample data 1
+    const char *data1 = 
+        "\n"
+        "key1 data1\n"
+        "{\n"
+        "\tkey data\n"
+        "}\n"
+        "key2 \"data2  \" {\n"
+        "\tkey data\n"
+        "}\n"
+        "key3 \"data\"\n"
+        "\t \"3\" {\n"
+        "\tkey data\n"
+        "}\n"
+        "\n"
+        "\"key4\" data4\n"
+        "{\n"
+        "\tkey data\n"
+        "}\n"
+        "\"key.5\" \"data.5\" { \n"
+        "\tkey data \n"
+        "}\n"
+        "\"key6\" \"data\"\n"
+        "\t   \"6\" {\n"
+        "\tkey data\n"
+        "}\n"
+        "   \n"
+        "key1 data1\n"
+        "{\n"
+        "\tkey data\n"
+        "}\n"
+        "key2 \"data2  \" {\n"
+        "\tkey data\n"
+        "}\n"
+        "key3 \"data\"\n"
+        "\t \"3\" {\n"
+        "\tkey data\n"
+        "}\n"
+        "\n"
+        "\"key4\" data4\n"
+        "{\n"
+        "\tkey data\n"
+        "}\n"
+        "\"key.5\" \"data.5\" {\n"
+        "\tkey data\n"
+        "}\n"
+        "\"key6\" \"data\"\n"
+        "\t   \"6\" {\n"
+        "\tkey data\n"
+        "}\n"
+        "\\\\key\\t7 data7\\n\\\"data7\\\"\n"
+        "{\n"
+        "\tkey data\n"
+        "}\n"
+        "\"\\\\key\\t8\" \"data8\\n\\\"data8\\\"\"\n"
+        "{\n"
+        "\tkey data\n"
+        "}\n"
+        "\n";
+
+    // Sample data 2
+    const char *data2 = 
+        "key1\n"
+        "key2\n"
+        "key3\n"
+        "key4\n";
+
+    // Parse sample data
+    info_parse(data1);
+    info_parse(data2);
+
+}
diff --git a/examples/settings_fully-existent.info b/examples/settings_fully-existent.info
new file mode 100644
index 0000000..bec7a64
--- /dev/null
+++ b/examples/settings_fully-existent.info
@@ -0,0 +1,6 @@
+settings
+{
+	setting1 15
+	setting2 9.876
+	setting3 Alice in Wonderland
+}
diff --git a/examples/settings_non-existent.info b/examples/settings_non-existent.info
new file mode 100644
index 0000000..4f76b2a
--- /dev/null
+++ b/examples/settings_non-existent.info
@@ -0,0 +1,6 @@
+;settings							// non-existent
+;{
+;	setting1 15
+;	setting2 9.876
+;	setting3 Alice in Wonderland
+;}
diff --git a/examples/settings_partially-existent.info b/examples/settings_partially-existent.info
new file mode 100644
index 0000000..ed5e8c2
--- /dev/null
+++ b/examples/settings_partially-existent.info
@@ -0,0 +1,6 @@
+settings
+{
+	setting1 15
+	;setting2 9.876						// non-existent
+	;setting3 Alice in Wonderland		// non-existent
+}
diff --git a/examples/speed_test.cpp b/examples/speed_test.cpp
new file mode 100644
index 0000000..4d5efd8
--- /dev/null
+++ b/examples/speed_test.cpp
@@ -0,0 +1,130 @@
+// ----------------------------------------------------------------------------
+// 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
+// ----------------------------------------------------------------------------
+
+#define _HAS_ITERATOR_DEBUGGING 0
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/format.hpp>
+#include <boost/shared_array.hpp>
+#include <iostream>
+#include <ctime>
+#include <algorithm>
+
+using namespace std;
+using namespace boost;
+using namespace boost::property_tree;
+
+string dummy;
+vector<string> keys;
+vector<string> shuffled_keys;
+
+void prepare_keys(int size)
+{
+    // Prepare keys
+    keys.clear();
+    for (int i = 0; i < size; ++i)
+        keys.push_back((format("%d") % i).str());
+    shuffled_keys = keys;
+    srand(0);
+    random_shuffle(shuffled_keys.begin(), shuffled_keys.end());
+}
+
+void clock_push_back(int size)
+{
+    prepare_keys(size);
+    int max_repeats = 1000000 / size;
+    shared_array<ptree> pt_array(new ptree[max_repeats]);
+
+    int n = 0;
+    clock_t t1 = clock(), t2;
+    do
+    {
+        if (n >= max_repeats)
+            break;
+        ptree &pt = pt_array[n];
+        for (int i = 0; i < size; ++i)
+            pt.push_back(ptree::value_type(shuffled_keys[i], ptree()));
+        t2 = clock();
+        ++n;
+    } while (t2 - t1 < CLOCKS_PER_SEC);
+
+    cout << "  push_back (" << size << "): " << double(t2 - t1) / CLOCKS_PER_SEC / n * 1000 << " ms\n";
+
+}
+
+void clock_find(int size)
+{
+    prepare_keys(size);
+
+    ptree pt;
+    for (int i = 0; i < size; ++i)
+        pt.push_back(ptree::value_type(keys[i], ptree("data")));
+
+    int n = 0;
+    clock_t t1 = clock(), t2;
+    do
+    {
+        for (int i = 0; i < size; ++i)
+            pt.find(shuffled_keys[i]);
+        t2 = clock();
+        ++n;
+    } while (t2 - t1 < CLOCKS_PER_SEC);
+
+    cout << "  find (" << size << "): " << double(t2 - t1) / CLOCKS_PER_SEC / n * 1000 << " ms\n";
+
+}
+
+void clock_erase(int size)
+{
+    prepare_keys(size);
+
+    int max_repeats = 100000 / size;
+    shared_array<ptree> pt_array(new ptree[max_repeats]);
+
+    ptree pt;
+    for (int n = 0; n < max_repeats; ++n)
+        for (int i = 0; i < size; ++i)
+            pt_array[n].push_back(ptree::value_type(keys[i], ptree("data")));
+
+    int n = 0;
+    clock_t t1 = clock(), t2;
+    do
+    {
+        if (n >= max_repeats)
+            break;
+        ptree &pt = pt_array[n];
+        for (int i = 0; i < size; ++i)
+            pt.erase(shuffled_keys[i]);
+        t2 = clock();
+        ++n;
+    } while (t2 - t1 < CLOCKS_PER_SEC);
+
+    cout << "  erase (" << size << "): " << double(t2 - t1) / CLOCKS_PER_SEC / n * 1000 << " ms\n";
+}
+
+int main()
+{
+
+    // push_back
+    clock_push_back(10);
+    clock_push_back(100);
+    clock_push_back(1000);
+
+    // erase
+    clock_erase(10);
+    clock_erase(100);
+    clock_erase(1000);
+
+    // find
+    clock_find(10);
+    clock_find(100);
+    clock_find(1000);
+
+}