Update of /cvsroot/boost/boost/libs/property_tree/examples
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv27259/examples
Added Files:
custom_data_type.cpp debug_settings.cpp debug_settings.xml
empty_ptree_trick.cpp info_grammar_spirit.cpp
settings_fully-existent.info settings_non-existent.info
settings_partially-existent.info speed_test.cpp
Log Message:
Adding property_tree
--- NEW FILE: custom_data_type.cpp ---
// ----------------------------------------------------------------------------
// 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/property_tree/info_parser.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/any.hpp>
#include <list>
#include <string>
#include <iostream>
// Custom translator that works with boost::any instead of std::string
struct my_translator
{
// Custom extractor - converts data from boost::any to T
template<class Ptree, class T>
bool get_value(const Ptree &pt, T &value) const
{
value = boost::any_cast<T>(pt.data());
return true; // Success
}
// Custom inserter - converts data from T to boost::any
template<class Ptree, class T>
bool put_value(Ptree &pt, const T &value) const
{
pt.data() = value;
return true;
}
};
int main()
{
using namespace boost::property_tree;
// Property_tree with boost::any as data type
// Key comparison: std::less<std::string>
// Key type: std::string
// Path type: path
// Data type: boost::any
// Translator type: my_translator
typedef basic_ptree<std::less<std::string>, std::string, path, boost::any,
my_translator> my_ptree;
my_ptree pt;
// Put/get int value
pt.put("int value", 3);
int int_value = pt.get<int>("int value");
std::cout << "Int value: " << int_value << "\n";
// Put/get string value
pt.put<std::string>("string value", "foo bar");
std::string string_value = pt.get<std::string>("string value");
std::cout << "String value: " << string_value << "\n";
// Put/get list<int> value
int list_data[] = { 1, 2, 3, 4, 5 };
pt.put<std::list<int> >("list value", std::list<int>(list_data, list_data +
sizeof(list_data) / sizeof(*list_data)));
std::list<int> list_value = pt.get<std::list<int> >("list value");
std::cout << "List value: ";
for (std::list<int>::iterator it = list_value.begin(); it !=
list_value.end(); ++it)
std::cout << *it << ' ';
std::cout << '\n';
}
--- NEW FILE: debug_settings.cpp ---
// ----------------------------------------------------------------------------
// 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/xml_parser.hpp>
//#include <boost/foreach.hpp>
#include <string>
#include <set>
#include <exception>
#include <iostream>
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);
};
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.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.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::value_type &v, pt.get_child("debug.modules"))
// m_modules.insert(v.second.data());
}
void debug_settings::save(const std::string &filename)
{
// Create empty property tree object
using boost::property_tree::ptree;
ptree pt;
// Put log filename in property tree
pt.put("debug.filename", m_file);
// Put debug level in property tree
pt.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_value functions
//BOOST_FOREACH(const std::string &name, m_modules)
// pt.put("debug.modules.module", name, true);
// Write property tree to XML file
write_xml(filename, pt);
}
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;
}
--- NEW FILE: debug_settings.xml ---
<?xml version="1.0" encoding="utf-8"?>
<debug>
<filename>debug.log</filename>
<modules>
<module>Finance</module>
<module>Admin</module>
<module>HR</module>
</modules>
<level>2</level>
</debug>
--- NEW FILE: empty_ptree_trick.cpp ---
// ----------------------------------------------------------------------------
// 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;
}
--- NEW FILE: info_grammar_spirit.cpp ---
// ----------------------------------------------------------------------------
// 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);
}
--- NEW FILE: settings_fully-existent.info ---
(This appears to be a binary file; contents omitted.)
--- NEW FILE: settings_non-existent.info ---
(This appears to be a binary file; contents omitted.)
--- NEW FILE: settings_partially-existent.info ---
(This appears to be a binary file; contents omitted.)
--- NEW FILE: speed_test.cpp ---
// ----------------------------------------------------------------------------
// 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],
empty_ptree<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);
}
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Boost-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/boost-cvs