blob: 554238184c28d745ebe69dcfc4eaedb4ea40ca8f [file] [log] [blame]
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>Five Minute Tutorial</title>
<link rel="stylesheet" href="../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.78.1">
<link rel="home" href="../index.html" title="The Boost C++ Libraries BoostBook Documentation Subset">
<link rel="up" href="../property_tree.html" title="Chapter&#160;22.&#160;Boost.PropertyTree">
<link rel="prev" href="../property_tree.html" title="Chapter&#160;22.&#160;Boost.PropertyTree">
<link rel="next" href="container.html" title="Property Tree as a Container">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../boost.png"></td>
<td align="center"><a href="../../../index.html">Home</a></td>
<td align="center"><a href="../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../property_tree.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../property_tree.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="container.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
<a name="property_tree.tutorial"></a><a class="link" href="tutorial.html" title="Five Minute Tutorial">Five Minute Tutorial</a>
</h2></div></div></div>
<p>
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 the author thinks that a wide range of people is familiar
with it.
</p>
<p>
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:
</p>
<pre class="programlisting">&lt;debug&gt;
&lt;filename&gt;debug.log&lt;/filename&gt;
&lt;modules&gt;
&lt;module&gt;Finance&lt;/module&gt;
&lt;module&gt;Admin&lt;/module&gt;
&lt;module&gt;HR&lt;/module&gt;
&lt;/modules&gt;
&lt;level&gt;2&lt;/level&gt;
&lt;/debug&gt;
</pre>
<p>
It contains the log filename, a list of modules where logging is enabled, and
the debug level value.
</p>
<p>
First we need some includes:
</p>
<pre class="programlisting"><span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">property_tree</span><span class="special">/</span><span class="identifier">ptree</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">property_tree</span><span class="special">/</span><span class="identifier">xml_parser</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">foreach</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">string</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">set</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">exception</span><span class="special">&gt;</span>
<span class="preprocessor">#include</span> <span class="special">&lt;</span><span class="identifier">iostream</span><span class="special">&gt;</span>
<span class="keyword">namespace</span> <span class="identifier">pt</span> <span class="special">=</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">property_tree</span><span class="special">;</span>
</pre>
<p>
To store the logging configuration in the program we create a debug_settings
structure:
</p>
<pre class="programlisting"><span class="keyword">struct</span> <span class="identifier">debug_settings</span>
<span class="special">{</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="identifier">m_file</span><span class="special">;</span> <span class="comment">// log filename</span>
<span class="keyword">int</span> <span class="identifier">m_level</span><span class="special">;</span> <span class="comment">// debug level</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">set</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;</span> <span class="identifier">m_modules</span><span class="special">;</span> <span class="comment">// modules where logging is enabled</span>
<span class="keyword">void</span> <span class="identifier">load</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span><span class="identifier">filename</span><span class="special">);</span>
<span class="keyword">void</span> <span class="identifier">save</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span><span class="identifier">filename</span><span class="special">);</span>
<span class="special">};</span>
</pre>
<p>
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:
</p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">debug_settings</span><span class="special">::</span><span class="identifier">load</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span><span class="identifier">filename</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Create empty property tree object</span>
<span class="identifier">pt</span><span class="special">::</span><span class="identifier">ptree</span> <span class="identifier">tree</span><span class="special">;</span>
<span class="comment">// Parse the XML into the property tree.</span>
<span class="identifier">pt</span><span class="special">::</span><span class="identifier">read_xml</span><span class="special">(</span><span class="identifier">filename</span><span class="special">,</span> <span class="identifier">tree</span><span class="special">);</span>
<span class="comment">// Use the throwing version of get to find the debug filename.</span>
<span class="comment">// If the path cannot be resolved, an exception is thrown.</span>
<span class="identifier">m_file</span> <span class="special">=</span> <span class="identifier">tree</span><span class="special">.</span><span class="identifier">get</span><span class="special">&lt;</span><span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">&gt;(</span><span class="string">"debug.filename"</span><span class="special">);</span>
<span class="comment">// Use the default-value version of get to find the debug level.</span>
<span class="comment">// Note that the default value is used to deduce the target type.</span>
<span class="identifier">m_level</span> <span class="special">=</span> <span class="identifier">tree</span><span class="special">.</span><span class="identifier">get</span><span class="special">(</span><span class="string">"debug.level"</span><span class="special">,</span> <span class="number">0</span><span class="special">);</span>
<span class="comment">// Use get_child to find the node containing the modules, and iterate over</span>
<span class="comment">// its children. If the path cannot be resolved, get_child throws.</span>
<span class="comment">// A C++11 for-range loop would also work.</span>
<span class="identifier">BOOST_FOREACH</span><span class="special">(</span><span class="identifier">pt</span><span class="special">::</span><span class="identifier">ptree</span><span class="special">::</span><span class="identifier">value_type</span> <span class="special">&amp;</span><span class="identifier">v</span><span class="special">,</span> <span class="identifier">tree</span><span class="special">.</span><span class="identifier">get_child</span><span class="special">(</span><span class="string">"debug.modules"</span><span class="special">))</span> <span class="special">{</span>
<span class="comment">// The data function is used to access the data stored in a node.</span>
<span class="identifier">m_modules</span><span class="special">.</span><span class="identifier">insert</span><span class="special">(</span><span class="identifier">v</span><span class="special">.</span><span class="identifier">second</span><span class="special">.</span><span class="identifier">data</span><span class="special">());</span>
<span class="special">}</span>
<span class="special">}</span>
</pre>
<p>
Now the save() function. It is also 7 lines of code:
</p>
<pre class="programlisting"><span class="keyword">void</span> <span class="identifier">debug_settings</span><span class="special">::</span><span class="identifier">save</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span><span class="identifier">filename</span><span class="special">)</span>
<span class="special">{</span>
<span class="comment">// Create an empty property tree object.</span>
<span class="identifier">pt</span><span class="special">::</span><span class="identifier">ptree</span> <span class="identifier">tree</span><span class="special">;</span>
<span class="comment">// Put the simple values into the tree. The integer is automatically</span>
<span class="comment">// converted to a string. Note that the "debug" node is automatically</span>
<span class="comment">// created if it doesn't exist.</span>
<span class="identifier">tree</span><span class="special">.</span><span class="identifier">put</span><span class="special">(</span><span class="string">"debug.filename"</span><span class="special">,</span> <span class="identifier">m_file</span><span class="special">);</span>
<span class="identifier">tree</span><span class="special">.</span><span class="identifier">put</span><span class="special">(</span><span class="string">"debug.level"</span><span class="special">,</span> <span class="identifier">m_level</span><span class="special">);</span>
<span class="comment">// Add all the modules. Unlike put, which overwrites existing nodes, add</span>
<span class="comment">// adds a new node at the lowest level, so the "modules" node will have</span>
<span class="comment">// multiple "module" children.</span>
<span class="identifier">BOOST_FOREACH</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span> <span class="special">&amp;</span><span class="identifier">name</span><span class="special">,</span> <span class="identifier">m_modules</span><span class="special">)</span>
<span class="identifier">tree</span><span class="special">.</span><span class="identifier">add</span><span class="special">(</span><span class="string">"debug.modules.module"</span><span class="special">,</span> <span class="identifier">name</span><span class="special">);</span>
<span class="comment">// Write property tree to XML file</span>
<span class="identifier">pt</span><span class="special">::</span><span class="identifier">write_xml</span><span class="special">(</span><span class="identifier">filename</span><span class="special">,</span> <span class="identifier">tree</span><span class="special">);</span>
<span class="special">}</span>
</pre>
<p>
The full program <a href="../../../libs/property_tree/examples/debug_settings.cpp" target="_top">debug_settings.cpp</a>
is included in the examples directory.
</p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2008-2010 Marcin Kalicinski<br>Copyright &#169; 2010-2013 Sebastian
Redl<p>
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
</p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="../property_tree.html"><img src="../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../property_tree.html"><img src="../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../index.html"><img src="../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="container.html"><img src="../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>