Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r51834 - trunk/libs/property_tree/doc
From: sebastian.redl_at_[hidden]
Date: 2009-03-18 09:16:06


Author: cornedbee
Date: 2009-03-18 09:16:05 EDT (Wed, 18 Mar 2009)
New Revision: 51834
URL: http://svn.boost.org/trac/boost/changeset/51834

Log:
Improve property_tree documentation.
Text files modified:
   trunk/libs/property_tree/doc/container.qbk | 17 ++++-
   trunk/libs/property_tree/doc/intro.qbk | 42 ++++++-------
   trunk/libs/property_tree/doc/synopsis.qbk | 12 +++
   trunk/libs/property_tree/doc/tutorial.qbk | 120 +++++++++++++++++++++------------------
   trunk/libs/property_tree/doc/xml_parser.qbk | 29 ++++++++-
   5 files changed, 133 insertions(+), 87 deletions(-)

Modified: trunk/libs/property_tree/doc/container.qbk
==============================================================================
--- trunk/libs/property_tree/doc/container.qbk (original)
+++ trunk/libs/property_tree/doc/container.qbk 2009-03-18 09:16:05 EDT (Wed, 18 Mar 2009)
@@ -1,8 +1,19 @@
 [section:container Property Tree as a Container]
 [/ __ptree_*__ macros expected from property_tree.qbk]
-Standard containers implement a concept of sequence. What is the sequence in case of property tree? It is a list of immediate children of given __ptree__. So, iterating over a __ptree__ will only reveal one level in hierarchy, not the whole tree. There is no iterator to iterate over all the nodes in tree, but it is not needed, so don't worry. The actual type of values stored by property tree is __ptree_value_type__. Property tree provides bidirectional __ptree_iterator__, both normal and reverse, to allow iteration over its elements.
+Every property tree node models the ReversibleSequence concept, providing
+access to its immediate children. This means that iterating over a __ptree__
+(which is the same as its root node - every __ptree__ node is also the
+subtree it starts) iterates only a single level of the hierarchy. There is no
+way to iterate over the entire tree.
 
-The sequence is not ordered by key. It is an important fact, and many mistakes can be avoided by keeping it in mind. The order of sequence is determined by the place where elements were inserted, like in `std::list`. That's why there are __ptree_push_back__, __ptree_push_front__ and __ptree_insert__ functions. But __ptree_find__ function, which searches for elements by name, has time complexity [^O(log n)] like in `std::map` - there is an additional indexing data structure inside property tree that allows fast searches. The implication of property tree not being sorted is that you cannot use algorithms that require sorted range, like for example `std::binary_search`.
+It is very important to remember that the property sequence is *not* ordered by
+the key. It preserves the order of insertion. It closely resembles a std::list.
+Fast access to children is provided via a separate lookup structure. Do not
+attempt to use algorithms that expect an ordered sequence (like binary_search)
+on a node's children.
 
-Property tree allows multiple elements to have equivalent keys, and the __ptree_find__ member function will always return the first of them. It is tempting to use `std::lower_bound` and `std::upper_bound` algorithms to find a range that encompasses all elements with equivalent keys, but it is a mistake - the sequence is not sorted by key and such a range probably does not even exist! You need to sort the sequence first, using a __ptree_sort__ member function (though by doing so you lose original ordering of the elements). Note that `std::sort` cannot be used, because it requires random access iterators, and property tree only provides bidirectional iterators.
+There may be multiple children with the same key value in a node. However, these
+children are not necessarily sequential. The iterator returned by __ptree_find__
+may refer to any of these, and there are no guarantees about the relative
+position of the other equally named children.
 [endsect] [/container]

Modified: trunk/libs/property_tree/doc/intro.qbk
==============================================================================
--- trunk/libs/property_tree/doc/intro.qbk (original)
+++ trunk/libs/property_tree/doc/intro.qbk 2009-03-18 09:16:05 EDT (Wed, 18 Mar 2009)
@@ -1,31 +1,29 @@
 [template ptree2codeImage[] [$images/ptree2code.png]]
 [section:intro What is Property Tree?]
-Property tree is a recursive data structure that stores a single data string,
-and an ordered list of [^(key, value)] pairs, where value is a property tree
-itself. It therefore forms a tree, hence the name. It is a versatile structure
-that can store in uniform way data coming from various sources, such as XML,
-INI or JSON files, as well as windows registry, program command line etc.
-The correspondence between a data source (here XML file) and property tree is
-illustrated in the following diagram:
-[ptree2codeImage]
-
-Each node of property tree may be conceptually treated as the following
-structure (note that due to recursive nature of the tree, nodes are property
-trees):
+The Property Tree library provides a data structure that stores an arbitrarily
+deeply nested tree of values, indexed at each level by some key. Each node of
+the tree stores its own value, plus an ordered list of its subnodes and their
+keys. The tree allows easy access to any of its nodes by means of a path, which
+is a concatenation of multiple keys.
+
+In addition, the library provides parsers and generators for a number of data
+formats that can be represented by such a tree, including XML, INI, and JSON.
+
+Property trees are versatile data structures, but are particularly suited for
+holding configuration data. The tree provides its own, tree-specific interface,
+and each node is also an STL-compatible Sequence for its child nodes.
+
+Conceptually, then, a node can be thought of as the following structure:
 
    struct ptree
    {
- string data; // data associated with the node
- list< pair<string, ptree> > children; // ordered list of named children
+ data_type data; // data associated with the node
+ list< pair<key_type, ptree> > children; // ordered list of named children
    };
 
-Both key type and data type are configurable.
+Both key_type and data_type are configurable, but will usually be std::string.
 
-The property tree interface is similar to the interface of a standard C++
-container. It supports iterators, insertion, erasing, searching etc. One can
-think of it as a sort of Document Object Model, which is minimalistic, not
-bound to any specific file format, designed to be easy to use, and comes as
-Boost-compatible, headers only C++ library. Many software projects develop a
-similar tool at some point of their lifetime, and property tree originated the
-same way. I hope the library can save many from reinventing the wheel.
+Many software projects develop a similar tool at some point of their lifetime,
+and property tree originated the same way. We hope the library can save many
+from reinventing the wheel.
 [endsect] [/intro]

Modified: trunk/libs/property_tree/doc/synopsis.qbk
==============================================================================
--- trunk/libs/property_tree/doc/synopsis.qbk (original)
+++ trunk/libs/property_tree/doc/synopsis.qbk 2009-03-18 09:16:05 EDT (Wed, 18 Mar 2009)
@@ -12,7 +12,17 @@
 [def __ptree_get_child__ [memberref boost::property_tree::basic_ptree::get_child get_child]]
 [def __ptree_put_child__ [memberref boost::property_tree::basic_ptree::put_child put_child]]
 [def __ptree_data__ [memberref boost::property_tree::basic_ptree::data data]]
-The central component of the library is __basic_ptree__ class template. Instances of this class are property trees. It is parametrized on character type and key comparison policy; __ptree__, __wptree__, __iptree__ and __wiptree__ are typedefs of __basic_ptree__ using predefined combinations of template parameters. Property tree is basically a somewhat simplified standard container (the closest being std::list), plus a bunch of extra member functions. These functions allow easy and effective access to the data stored in property tree. They are various variants of __ptree_get__, __ptree_put__, __ptree_get_value__, __ptree_put_value__, __ptree_get_child__, __ptree_put_child__. Additionally, there is __ptree_data__ function to access node data directly.
+The central component of the library is __basic_ptree__ class template.
+Instances of this class are property trees. It is parametrized on character
+type and key comparison policy; __ptree__, __wptree__, __iptree__ and
+__wiptree__ are typedefs of __basic_ptree__ using predefined combinations of
+template parameters. Property tree is basically a somewhat simplified standard
+container (the closest being std::list), plus a bunch of extra member
+functions. These functions allow easy and effective access to the data stored
+in property tree. They are various variants of __ptree_get__, __ptree_put__,
+__ptree_get_value__, __ptree_put_value__, __ptree_get_child__,
+__ptree_put_child__. Additionally, there is __ptree_data__ function to access
+node data directly.
 
 See the [classref boost::property_tree::basic_ptree basic_ptree class template synopsis] for more information.
 [endsect]

Modified: trunk/libs/property_tree/doc/tutorial.qbk
==============================================================================
--- trunk/libs/property_tree/doc/tutorial.qbk (original)
+++ trunk/libs/property_tree/doc/tutorial.qbk 2009-03-18 09:16:05 EDT (Wed, 18 Mar 2009)
@@ -1,7 +1,12 @@
 [section:tutorial Five Minute Tutorial]
-This tutorial uses XML file format. Note that the library is not specifically bound to XML, and any other supported format (such as INI or JSON) could be used as well. XML was chosen because author thinks that wide range of people is familiar with it.
-
-Suppose we are writing a logging system for some application, and need to read log configuration from a file when program starts. The file with log configuration looks like that:
+This tutorial uses XML. Note that the library is not specifically bound to XML,
+and any other supported format (such as INI or JSON) could be used instead.
+XML was chosen because author thinks that wide range of people is familiar
+with it.
+
+Suppose we are writing a logging system for some application, and need to read
+log configuration from a file when the program starts. The file with the log
+configuration looks like this:
 
 [pre
 <debug>
@@ -15,7 +20,9 @@
 </debug>
 ]
 
-It contains log filename, list of modules where logging is enabled, and debug level value. To store logging configuration in the program we created debug_settings structure:
+It contains the log filename, a list of modules where logging is enabled, and
+the debug level value. To store the logging configuration in the program we
+created a debug_settings structure:
 
    struct debug_settings
    {
@@ -26,52 +33,52 @@
        void save(const std::string &filename);
    };
 
-All that needs to be done now is to write implementations of load() and save() member functions. Let's first deal with load(). It contains just 7 lines of code, although it does all the necessary things, including error handling:
-
- // Loads debug_settings structure from specified XML file
- void debug_settings::load(const std::string &filename)
- {
- // Create empty property tree object
- using boost::property_tree::__ptree__;
- __ptree__ pt;
-
- // Load XML file and put its contents in property tree.
- // No namespace qualification is needed, because of Koenig
- // lookup on the second argument. If reading fails, exception
- // is thrown.
- __read_xml__(filename, pt);
-
- // Get filename and store it in m_file variable. Note that
- // we specify a path to the value using notation where keys
- // are separated with dots (different separator may be used
- // if keys themselves contain dots). If debug.filename key is
- // not found, exception is thrown.
- m_file = pt.__ptree_get__<std::string>("debug.filename");
-
- // Get debug level and store it in m_level variable. This is
- // another version of get method: if debug.level key is not
- // found, it will return default value (specified by second
- // parameter) instead of throwing. Type of the value extracted
- // is determined by type of second parameter, so we can simply
- // write get(...) instead of get<int>(...)
- m_level = pt.__ptree_get__("debug.level", 0);
-
- // Iterate over debug.modules section and store all found
- // modules in m_modules set. get_child() function returns a
- // reference to child at specified path; if there is no such
- // child, it throws. Property tree iterator can be used in
- // the same way as standard container iterator. Category
- // is bidirectional_iterator.
- BOOST_FOREACH(__ptree__::__ptree_value_type__ &v, pt.__ptree_get_child__("debug.modules"))
- m_modules.__ptree_insert__(v.second.data());
- }
+All that needs to be done now is to write implementations of load() and save()
+member functions. Let's first deal with load(). It contains just 7 lines of
+code, although it does all the necessary things, including error reporting:
+
+ // Loads debug_settings structure from the specified XML file
+ void debug_settings::load(const std::string &filename)
+ {
+ // Create an empty property tree object
+ using boost::property_tree::__ptree__;
+ __ptree__ pt;
+
+ // Load the XML file into the property tree. If reading fails
+ // (cannot open file, parse error), an exception is thrown.
+ __read_xml__(filename, pt);
+
+ // Get the filename and store it in the m_file variable.
+ // Note that we construct the path to the value by separating
+ // the individual keys with dots. If dots appear in the keys,
+ // a path type with a different separator can be used.
+ // If debug.filename key is not found, exception is thrown.
+ m_file = pt.__ptree_get__<std::string>("debug.filename");
+
+ // Get the debug level and store it in the m_level variable.
+ // This is another version of the get method: if the value is
+ // not found, the default value (specified by the second
+ // parameter) is returned instead. The type of the value
+ // extracted is determined by the type of the second parameter,
+ // so we can simply write get(...) instead of get<int>(...).
+ m_level = pt.__ptree_get__("debug.level", 0);
+
+ // Iterate over the debug.modules section and store all found
+ // modules in the m_modules set. The get_child() function
+ // returns a reference to the child at the specified path; if
+ // there is no such child, it throws. Property tree iterators
+ // are models of BidirectionalIterator.
+ BOOST_FOREACH(__ptree__::__ptree_value_type__ &v,
+ pt.__ptree_get_child__("debug.modules"))
+ m_modules.__ptree_insert__(v.second.data());
+ }
 
-Now save() function. It is also 7 lines of code:
+Now the save() function. It is also 7 lines of code:
 
- // Saves debug_settings structure to specified XML file
+ // Saves the debug_settings structure to the specified XML file
    void debug_settings::save(const std::string &filename)
    {
- // Create empty property tree object
+ // Create an empty property tree object
       using boost::property_tree::__ptree__;
       __ptree__ pt;
    
@@ -81,19 +88,20 @@
       // Put debug level in property tree
       pt.__ptree_put__("debug.level", m_level);
    
- // Iterate over modules in set and put them in property
- // tree. Note that put function places new key at the
- // end of list of keys. This is fine in most of the
- // situations. If you want to place item at some other
- // place (i.e. at front or somewhere in the middle),
- // this can be achieved using combination of insert
- // and put_own functions
+ // Iterate over the modules in the set and put them in the
+ // property tree. Note that the put function places the new
+ // key at the end of the list of keys. This is fine most of
+ // the time. If you want to place an item at some other place
+ // (i.e. at the front or somewhere in the middle), this can
+ // be achieved using a combination of the insert and put_own
+ // functions.
       BOOST_FOREACH(const std::string &name, m_modules)
          pt.__ptree_put__("debug.modules.module", name, true);
-
- // Write property tree to XML file
+
+ // Write the property tree to the XML file.
       __write_xml__(filename, pt);
    }
 
-The full program [@../../examples/debug_settings.cpp debug_settings.cpp] is included in examples directory.
+The full program [@../../examples/debug_settings.cpp debug_settings.cpp] is
+included in the examples directory.
 [endsect] [/tutorial]

Modified: trunk/libs/property_tree/doc/xml_parser.qbk
==============================================================================
--- trunk/libs/property_tree/doc/xml_parser.qbk (original)
+++ trunk/libs/property_tree/doc/xml_parser.qbk 2009-03-18 09:16:05 EDT (Wed, 18 Mar 2009)
@@ -3,13 +3,32 @@
 [def __xml_parser.hpp__ [headerref boost/property_tree/xml_parser.hpp xml_parser.hpp]]
 [def __TinyXML__ [@http://sourceforge.net/projects/tinyxml TinyXML]]
 [def __boost_homepage__ [@http://www.boost.org Boost]]
-The __xml_wiki__ is an industry standard for storing information in textual form. Unfortunately, there is no XML parser in __boost_homepage__ as of the time of this writing. Therefore, a custom parser was created. It only supports a core subset of XML standard. For example, declarations and entity references are not supported. The parser is built with Spirit, and bases on XML grammar sample by Daniel Nuffer. As a reinforcement to it, a parser based on __TinyXML__ is also provided. To enable it define [^BOOST_PROPERTY_TREE_XML_PARSER_TINYXML] before including the __xml_parser.hpp__ file. __TinyXML__ library has to be obtained separately.
+The __xml_wiki__ is an industry standard for storing information in textual
+form. Unfortunately, there is no XML parser in __boost_homepage__ as of the
+time of this writing. Therefore, a custom parser was created. It only supports
+a core subset of XML standard. For example, declarations and entity references
+are not supported. The parser is built with Spirit, and based on XML grammar
+sample by Daniel Nuffer. As a reinforcement to it, a parser based on
+__TinyXML__ is also provided. To enable it define
+[^BOOST_PROPERTY_TREE_XML_PARSER_TINYXML] before including the
+__xml_parser.hpp__ file. __TinyXML__ library has to be obtained separately.
 
 How XML is translated to property tree (__read_xml__):
 
-* Attributes of each XML key are stored in a subkey with name [^<xmlattr>]. Each subkey of [^<xmlattr>] is one attribute. If [^<xmlattr>] subkey does not exist or is empty, there are no attributes.
-* XML comments are stored in keys named [^<xmlcomment>], unless a flag is specified that disables parsing of comments.
-* Data of XML node may be stored in two ways, depending on the flags parameter setting. The default way is to have all data nodes concatenated and put in data string of appropriate property tree key. The other way is to have them put in separate subkeys named [^<xmltext>] each.
+* Attributes of each XML key are stored in a subkey with name [^<xmlattr>].
+ Each subkey of [^<xmlattr>] is one attribute. If [^<xmlattr>] subkey does
+ not exist or is empty, there are no attributes.
+* XML comments are stored in keys named [^<xmlcomment>], unless a flag is
+ specified that disables parsing of comments.
+* Data of XML node may be stored in two ways, depending on the flags parameter
+ setting. The default way is to have all data nodes concatenated and put in
+ data string of appropriate property tree key. The other way is to have them
+ put in separate subkeys named [^<xmltext>] each.
 
-Translation of property tree back into XML (__write_xml__) assumes the same structure as outlined above. That means, for example, that if you want to have attributes, you need to create [^<xmlattr>] subkey and put them there. With appropriate flags setting, reading an XML file and writing it back will not change the contents (but may change formatting), unless XML file uses some unsupported constructs.
+Translation of property tree back into XML (__write_xml__) assumes the same
+structure as outlined above. That means, for example, that if you want to have
+attributes, you need to create [^<xmlattr>] subkey and put them there. With
+appropriate flags setting, reading an XML file and writing it back will not
+change the contents (but may change formatting), unless XML file uses some
+unsupported constructs.
 [endsect] [/xml_parser]


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk