Skip to content

Commit

Permalink
Somewhat improve PTree documentation.
Browse files Browse the repository at this point in the history
[SVN r70665]
  • Loading branch information
Sebastian Redl committed Mar 28, 2011
1 parent 794c1e1 commit ef95113
Show file tree
Hide file tree
Showing 9 changed files with 57 additions and 33 deletions.
38 changes: 27 additions & 11 deletions doc/accessing.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Property tree resembles (almost is) a standard container with value type of `pai
To find the value of `pi` we might do the following:

__ptree__::__ptree_const_iterator__ it = pt.__ptree_find__("pi");
double pi = boost::lexical_cast<double>(it->second._ptree_data__());
double pi = boost::lexical_cast<double>(it->second.__ptree_data__());

This looks quite cumbersome, and would be even more so if `pi` value was not stored so near the top of the tree, and we cared just a little bit more about errors. Fortunately, there is another, correct way of doing it:

Expand Down Expand Up @@ -53,26 +53,42 @@ boost::optional<float> v = pt.__ptree_get_optional__<float>("a.path.to.float.val
``
This version uses boost::optional class to handle extraction failure. On successful extraction, it will return boost::optional initialized with extracted value. Otherwise, it will return uninitialized boost::optional.

To retrieve value from this tree (not some subkey), use __ptree_get_value__, __ptree_get_value__ (default-value version), and __ptree_get_value_optional__. They have identical semantics to __ptree_get__ functions, except they don't take the __path__ parameter. Don't call __ptree_get__ with and empty __path__ to do this as it will try to extract contents of subkey with empty name.
To retrieve a value from this tree (not some subkey), use __ptree_get_value__, __ptree_get_value__ (default-value version), and __ptree_get_value_optional__. They have identical semantics to __ptree_get__ functions, except they don't take the __path__ parameter. Don't call __ptree_get__ with and empty __path__ to do this as it will try to extract contents of subkey with empty name.

To use separator character other than default '[^.]', each of the __ptree_get__ versions has another form, which takes an additional parameter in front of path. This parameter of type `char/wchar_t` specifies the separating character. This is a lifesaving device for those who may have dots in their keys:
To use a separator character other than default '[^.]', you need to construct
a path object explicitly. The path type for a __ptree__ is a string_path
instantiation, so the easiest way to refer to it is __ptree__::path_type.
This way you can use trees that have dots in their keys:

pt.get<float>('/', "p.a.t.h/t.o/v.a.l.u.e");
pt.get('/', "p.a.t.h/t.o/v.a.l.u.e", 0, NULL);
pt.get_optional<std::string>('/', "p.a.t.h/t.o/v.a.l.u.e");
typedef ptree::path_type path;
pt.get<float>(path("p.a.t.h/t.o/v.a.l.u.e", '/'));
pt.get(path("p.a.t.h/t.o/v.a.l.u.e", '/'), 0, NULL);
pt.get_optional<std::string>(path("p.a.t.h/t.o/v.a.l.u.e", '/'));

[heading One Way of Putting Data]
Note: the special overloads of __ptree_get__ and __ptree_get_optional__ taking
a separator character that existed in pre-release versions of PropertyTree have
been removed. This is because the overloads conflicted with using per-call data
translators.

To complement __ptree_get__, there is a __ptree_put__ function. Contrary to __ptree_get__, it has only one variant. The reason is, there is no need to handle put failures so often (normally, __ptree_put__ will only fail if conversion of the supplied value to __ptree_data_type__ fails or the system runs out of memory. In the former case, __ptree_put__ will throw __ptree_bad_data__). Sample usage of __ptree_put__ might appear as:
[heading Two Ways of Putting Data]

To complement __ptree_get__, there are __ptree_put__ and __ptree_add__. Contrary to __ptree_get__, they have only one variant each. This is because there is no need to deal with missing values when adding data. If the supplied value cannot be converted to the tree's data type, the functions will throw __ptree_bad_data__.

__ptree__ pt;
pt.__ptree_put__("a.path.to.float.value", 3.14f);
// Overwrites the value
pt.__ptree_put__("a.path.to.float.value", 2.72f);
// Adds a second node with the new value.
pt.__ptree_add__("a.path.to.float.value", 3.14f);

Calling __ptree_put__ will insert a new value at specified path, so that a call to __ptree_get__ specifying the same path will retrieve it. Further, __ptree_put__ will insert any missing path elements during path traversal. For example, calling `__ptree_put__("key1.key2.key3", 3.14f)` on an empty tree will insert three new children: `key1`, `key1.key2` and `key1.key2.key3`. The last one will receive a string `"3.14"` as data, while the two former ones will have empty data strings. __ptree_put__ always inserts new keys at the back of the existing sequences.
The difference between __ptree_put__ and __ptree_add__ is that put will overwrite existing values if there are any, while add will create a new node to hold the value even if the specified path references an existing node.

Similar to __ptree_get_value__, there is also a __ptree_put_value__ function. It does the same for this property tree what __ptree_put__ does for its children. Thus, it does not require __path__:
Similar to __ptree_get_value__, there is also a __ptree_put_value__ function. It does the same for this property tree what __ptree_put__ does for its children. Thus, it does not receive a __path__:

__ptree__ pt;
pt.__ptree_put_own__(3.14f);
pt.__ptree_put_value__(3.14f);

There is no add_value function.

[endsect]
[endsect]
21 changes: 14 additions & 7 deletions doc/container.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@ way to iterate over the entire tree.

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 by name 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.
Fast access to children by name 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.

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.
The property tree exposes a second container-like interface, called the
associative view. Its iterator type is the nested type assoc_iterator (and its
const counterpart const_assoc_iterator). You can get an ordered view of all
children by using ordered_begin() and ordered_end().

The associative view also provides find() and equal_range() members, which
return assoc_iterators, but otherwise have the same semantics as the members
of std::map of the same name.

You can get a normal iterator from an assoc_iterator by using the to_iterator()
member function. Converting the other way is not possible.
[endsect] [/container]
4 changes: 2 additions & 2 deletions doc/json_parser.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
The __json__ is a data interchange format derived from the object literal
notation of JavaScript. (JSON stands for JavaScript Object Notation.)
JSON is a simple, compact format for loosely structured node trees of any depth,
very similar to the property tree dataset. It is less stuctured than XML and has
no schema support, but has the advantage of being simpler, smaller and typed
very similar to the property tree dataset. It is less structured than XML and
has no schema support, but has the advantage of being simpler, smaller and typed
without the need for a complex schema.

The property tree dataset is not typed, and does not support arrays as such.
Expand Down
8 changes: 4 additions & 4 deletions doc/parsers.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@

[include info_parser.qbk]

# These parsers will be dropped for now.
#[include cmd_line_parser.qbk]
[/ These parsers will be dropped for now.]
[/ include cmd_line_parser.qbk]

#[include windows_registry_parser.qbk]
[/ include windows_registry_parser.qbk]

#[include system_environment_parser.qbk]
[/ include system_environment_parser.qbk]

[endsect] [/parsers]
4 changes: 2 additions & 2 deletions doc/property_tree.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
[def __ptree_data_type__ [classref boost::property_tree::basic_ptree::data_type data_type]]
[def __ptree_iterator__ [classref boost::property_tree::basic_ptree::iterator iterator]]
[def __ptree_const_iterator__ [classref boost::property_tree::basic_ptree::const_iterator const_iterator]]
[def __path__ [classref boost::property_tree::path path]]
[def __path__ [classref boost::property_tree::string_path path]]
[def __ptree_error__ [classref boost::property_tree::ptree_error ptree_error]]
[def __ptree_bad_data__ [classref boost::property_tree::ptree_bad_data ptree_bad_data]]
[def __ptree_bad_path__ [classref boost::property_tree::ptree_bad_path ptree_bad_path]]
Expand All @@ -53,7 +53,7 @@
[def __ptree_get_value_optional__ [memberref boost::property_tree::basic_ptree::get_value_optional get_value_optional]]
[def __ptree_get_child__ [memberref boost::property_tree::basic_ptree::get_child get_child]]
[def __ptree_put__ [memberref boost::property_tree::basic_ptree::put put]]
[def __ptree_put__ [memberref boost::property_tree::basic_ptree::add add]]
[def __ptree_add__ [memberref boost::property_tree::basic_ptree::add add]]
[def __ptree_put_value__ [memberref boost::property_tree::basic_ptree::put_value put_value]]

[/ free-functions]
Expand Down
2 changes: 1 addition & 1 deletion doc/synopsis.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ 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
__ptree_put_child__. Additionally, there is a __ptree_data__ function to access
node data directly.

See the [classref boost::property_tree::basic_ptree basic_ptree class template synopsis] for more information.
Expand Down
4 changes: 2 additions & 2 deletions doc/xml_parser.qbk
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ XML / property tree conversion schema (__read_xml__ and __write_xml__):
* XML comments are stored in nodes named [^<xmlcomment>], unless comment
ignoring is enabled via the flags.
* Text content is stored in one of two ways, depending on the flags. The default
way concatenates all text nodes and stores them in a single node called
[^<xmltext>]. This way, the entire content can be conveniently read, but the
way concatenates all text nodes and stores them as the data of the element
node. This way, the entire content can be conveniently read, but the
relative ordering of text and child elements is lost. The other way stores
each text content as a separate node, all called [^<xmltext>].

Expand Down
4 changes: 2 additions & 2 deletions examples/debug_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ void debug_settings::load(const std::string &filename)
// child, it throws. Property tree iterator can be used in
// the same way as standard container iterator. Category
// is bidirectional_iterator.
//BOOST_FOREACH(ptree::value_type &v, pt.get_child("debug.modules"))
// m_modules.insert(v.second.data());
BOOST_FOREACH(ptree::value_type &v, pt.get_child("debug.modules"))
m_modules.insert(v.second.data());

}

Expand Down
5 changes: 3 additions & 2 deletions include/boost/property_tree/ptree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,9 @@ namespace boost { namespace property_tree

// Associative view

/** Returns an iterator to the first child, in order. */
/** Returns an iterator to the first child, in key order. */
assoc_iterator ordered_begin();
/** Returns an iterator to the first child, in order. */
/** Returns an iterator to the first child, in key order. */
const_assoc_iterator ordered_begin() const;

/** Returns the not-found iterator. Equivalent to end() in a real
Expand Down Expand Up @@ -432,6 +432,7 @@ namespace boost { namespace property_tree
* return node->get_value_optional();
* return boost::null;
* @endcode
* That is, return the value if it exists and can be converted, or nil.
*/
template<class Type>
optional<Type> get_optional(const path_type &path) const;
Expand Down

0 comments on commit ef95113

Please sign in to comment.