stabilize build system: depends, installer, boost/bdb fixes, cross targets groundwork
This commit is contained in:
+83
@@ -0,0 +1,83 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright (C) 2002-2006 Marcin Kalicinski
|
||||
// Copyright (C) 2009 Sebastian Redl
|
||||
//
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_EXCEPTIONS_IMPLEMENTATION_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_EXCEPTIONS_IMPLEMENTATION_HPP_INCLUDED
|
||||
|
||||
namespace boost { namespace property_tree
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
// Helper for preparing what string in ptree_bad_path exception
|
||||
template<class P> inline
|
||||
std::string prepare_bad_path_what(const std::string &what,
|
||||
const P &path)
|
||||
{
|
||||
return what + " (" + path.dump() + ")";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ptree_error
|
||||
|
||||
inline ptree_error::ptree_error(const std::string &w):
|
||||
std::runtime_error(w)
|
||||
{
|
||||
}
|
||||
|
||||
inline ptree_error::~ptree_error() throw()
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ptree_bad_data
|
||||
|
||||
template<class D> inline
|
||||
ptree_bad_data::ptree_bad_data(const std::string &w, const D &d):
|
||||
ptree_error(w), m_data(d)
|
||||
{
|
||||
}
|
||||
|
||||
inline ptree_bad_data::~ptree_bad_data() throw()
|
||||
{
|
||||
}
|
||||
|
||||
template<class D> inline
|
||||
D ptree_bad_data::data() const
|
||||
{
|
||||
return boost::any_cast<D>(m_data);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// ptree_bad_path
|
||||
|
||||
template<class P> inline
|
||||
ptree_bad_path::ptree_bad_path(const std::string &w, const P &p):
|
||||
ptree_error(detail::prepare_bad_path_what(w, p)), m_path(p)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
inline ptree_bad_path::~ptree_bad_path() throw()
|
||||
{
|
||||
}
|
||||
|
||||
template<class P> inline
|
||||
P ptree_bad_path::path() const
|
||||
{
|
||||
return boost::any_cast<P>(m_path);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
||||
@@ -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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_FILE_PARSER_ERROR_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_FILE_PARSER_ERROR_HPP_INCLUDED
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace property_tree
|
||||
{
|
||||
|
||||
//! File parse error
|
||||
class file_parser_error: public ptree_error
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Construction & destruction
|
||||
|
||||
// Construct error
|
||||
file_parser_error(const std::string &msg,
|
||||
const std::string &file,
|
||||
unsigned long l) :
|
||||
ptree_error(format_what(msg, file, l)),
|
||||
m_message(msg), m_filename(file), m_line(l)
|
||||
{
|
||||
}
|
||||
|
||||
~file_parser_error() throw()
|
||||
// gcc 3.4.2 complains about lack of throw specifier on compiler
|
||||
// generated dtor
|
||||
{
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////
|
||||
// Data access
|
||||
|
||||
// Get error message (without line and file - use what() to get
|
||||
// full message)
|
||||
std::string message() const
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
// Get error filename
|
||||
std::string filename() const
|
||||
{
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
// Get error line number
|
||||
unsigned long line() const
|
||||
{
|
||||
return m_line;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::string m_message;
|
||||
std::string m_filename;
|
||||
unsigned long m_line;
|
||||
|
||||
// Format error message to be returned by std::runtime_error::what()
|
||||
static std::string format_what(const std::string &msg,
|
||||
const std::string &file,
|
||||
unsigned long l)
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << (file.empty() ? "<unspecified file>" : file.c_str());
|
||||
if (l > 0)
|
||||
stream << '(' << l << ')';
|
||||
stream << ": " << msg;
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_ERROR_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_ERROR_HPP_INCLUDED
|
||||
|
||||
#include <boost/property_tree/detail/file_parser_error.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace property_tree { namespace info_parser
|
||||
{
|
||||
|
||||
class info_parser_error: public file_parser_error
|
||||
{
|
||||
public:
|
||||
info_parser_error(const std::string &message,
|
||||
const std::string &filename,
|
||||
unsigned long line) :
|
||||
file_parser_error(message, filename, line)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,391 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_READ_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_READ_HPP_INCLUDED
|
||||
|
||||
#include "boost/property_tree/ptree.hpp"
|
||||
#include "boost/property_tree/detail/info_parser_error.hpp"
|
||||
#include "boost/property_tree/detail/info_parser_utils.hpp"
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <stack>
|
||||
#include <fstream>
|
||||
#include <cctype>
|
||||
|
||||
namespace boost { namespace property_tree { namespace info_parser
|
||||
{
|
||||
|
||||
// Expand known escape sequences
|
||||
template<class It>
|
||||
std::basic_string<typename std::iterator_traits<It>::value_type>
|
||||
expand_escapes(It b, It e)
|
||||
{
|
||||
typedef typename std::iterator_traits<It>::value_type Ch;
|
||||
std::basic_string<Ch> result;
|
||||
while (b != e)
|
||||
{
|
||||
if (*b == Ch('\\'))
|
||||
{
|
||||
++b;
|
||||
if (b == e)
|
||||
{
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"character expected after backslash", "", 0));
|
||||
}
|
||||
else if (*b == Ch('0')) result += Ch('\0');
|
||||
else if (*b == Ch('a')) result += Ch('\a');
|
||||
else if (*b == Ch('b')) result += Ch('\b');
|
||||
else if (*b == Ch('f')) result += Ch('\f');
|
||||
else if (*b == Ch('n')) result += Ch('\n');
|
||||
else if (*b == Ch('r')) result += Ch('\r');
|
||||
else if (*b == Ch('t')) result += Ch('\t');
|
||||
else if (*b == Ch('v')) result += Ch('\v');
|
||||
else if (*b == Ch('"')) result += Ch('"');
|
||||
else if (*b == Ch('\'')) result += Ch('\'');
|
||||
else if (*b == Ch('\\')) result += Ch('\\');
|
||||
else
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"unknown escape sequence", "", 0));
|
||||
}
|
||||
else
|
||||
result += *b;
|
||||
++b;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Detect whitespace in a not very smart way.
|
||||
template <class Ch>
|
||||
bool is_ascii_space(Ch c)
|
||||
{
|
||||
// Everything outside ASCII is not space.
|
||||
unsigned n = c;
|
||||
if (n > 127)
|
||||
return false;
|
||||
return std::isspace(c) != 0;
|
||||
}
|
||||
|
||||
// Advance pointer past whitespace
|
||||
template<class Ch>
|
||||
void skip_whitespace(const Ch *&text)
|
||||
{
|
||||
using namespace std;
|
||||
while (is_ascii_space(*text))
|
||||
++text;
|
||||
}
|
||||
|
||||
// Extract word (whitespace delimited) and advance pointer accordingly
|
||||
template<class Ch>
|
||||
std::basic_string<Ch> read_word(const Ch *&text)
|
||||
{
|
||||
using namespace std;
|
||||
skip_whitespace(text);
|
||||
const Ch *start = text;
|
||||
while (!is_ascii_space(*text) && *text != Ch(';') && *text != Ch('\0'))
|
||||
++text;
|
||||
return expand_escapes(start, text);
|
||||
}
|
||||
|
||||
// Extract line (eol delimited) and advance pointer accordingly
|
||||
template<class Ch>
|
||||
std::basic_string<Ch> read_line(const Ch *&text)
|
||||
{
|
||||
using namespace std;
|
||||
skip_whitespace(text);
|
||||
const Ch *start = text;
|
||||
while (*text != Ch('\0') && *text != Ch(';'))
|
||||
++text;
|
||||
while (text > start && is_ascii_space(*(text - 1)))
|
||||
--text;
|
||||
return expand_escapes(start, text);
|
||||
}
|
||||
|
||||
// Extract string (inside ""), and advance pointer accordingly
|
||||
// Set need_more_lines to true if \ continuator found
|
||||
template<class Ch>
|
||||
std::basic_string<Ch> read_string(const Ch *&text, bool *need_more_lines)
|
||||
{
|
||||
skip_whitespace(text);
|
||||
if (*text == Ch('\"'))
|
||||
{
|
||||
|
||||
// Skip "
|
||||
++text;
|
||||
|
||||
// Find end of string, but skip escaped "
|
||||
bool escaped = false;
|
||||
const Ch *start = text;
|
||||
while ((escaped || *text != Ch('\"')) && *text != Ch('\0'))
|
||||
{
|
||||
escaped = (!escaped && *text == Ch('\\'));
|
||||
++text;
|
||||
}
|
||||
|
||||
// If end of string found
|
||||
if (*text == Ch('\"'))
|
||||
{
|
||||
std::basic_string<Ch> result = expand_escapes(start, text++);
|
||||
skip_whitespace(text);
|
||||
if (*text == Ch('\\'))
|
||||
{
|
||||
if (!need_more_lines)
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"unexpected \\", "", 0));
|
||||
++text;
|
||||
skip_whitespace(text);
|
||||
if (*text == Ch('\0') || *text == Ch(';'))
|
||||
*need_more_lines = true;
|
||||
else
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"expected end of line after \\", "", 0));
|
||||
}
|
||||
else
|
||||
if (need_more_lines)
|
||||
*need_more_lines = false;
|
||||
return result;
|
||||
}
|
||||
else
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"unexpected end of line", "", 0));
|
||||
|
||||
}
|
||||
else
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error("expected \"", "", 0));
|
||||
}
|
||||
|
||||
// Extract key
|
||||
template<class Ch>
|
||||
std::basic_string<Ch> read_key(const Ch *&text)
|
||||
{
|
||||
skip_whitespace(text);
|
||||
if (*text == Ch('\"'))
|
||||
return read_string(text, NULL);
|
||||
else
|
||||
return read_word(text);
|
||||
}
|
||||
|
||||
// Extract data
|
||||
template<class Ch>
|
||||
std::basic_string<Ch> read_data(const Ch *&text, bool *need_more_lines)
|
||||
{
|
||||
skip_whitespace(text);
|
||||
if (*text == Ch('\"'))
|
||||
return read_string(text, need_more_lines);
|
||||
else
|
||||
{
|
||||
*need_more_lines = false;
|
||||
return read_word(text);
|
||||
}
|
||||
}
|
||||
|
||||
// Build ptree from info stream
|
||||
template<class Ptree, class Ch>
|
||||
void read_info_internal(std::basic_istream<Ch> &stream,
|
||||
Ptree &pt,
|
||||
const std::string &filename,
|
||||
int include_depth)
|
||||
{
|
||||
typedef std::basic_string<Ch> str_t;
|
||||
// Possible parser states
|
||||
enum state_t {
|
||||
s_key, // Parser expects key
|
||||
s_data, // Parser expects data
|
||||
s_data_cont // Parser expects data continuation
|
||||
};
|
||||
|
||||
unsigned long line_no = 0;
|
||||
state_t state = s_key; // Parser state
|
||||
Ptree *last = NULL; // Pointer to last created ptree
|
||||
// Define line here to minimize reallocations
|
||||
str_t line;
|
||||
|
||||
// Initialize ptree stack (used to handle nesting)
|
||||
std::stack<Ptree *> stack;
|
||||
stack.push(&pt); // Push root ptree on stack initially
|
||||
|
||||
try {
|
||||
// While there are characters in the stream
|
||||
while (stream.good()) {
|
||||
// Read one line from stream
|
||||
++line_no;
|
||||
std::getline(stream, line);
|
||||
if (!stream.good() && !stream.eof())
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"read error", filename, line_no));
|
||||
const Ch *text = line.c_str();
|
||||
|
||||
// If directive found
|
||||
skip_whitespace(text);
|
||||
if (*text == Ch('#')) {
|
||||
// Determine directive type
|
||||
++text; // skip #
|
||||
std::basic_string<Ch> directive = read_word(text);
|
||||
if (directive == convert_chtype<Ch, char>("include")) {
|
||||
// #include
|
||||
if (include_depth > 100) {
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"include depth too large, "
|
||||
"probably recursive include",
|
||||
filename, line_no));
|
||||
}
|
||||
str_t s = read_string(text, NULL);
|
||||
std::string inc_name =
|
||||
convert_chtype<char, Ch>(s.c_str());
|
||||
std::basic_ifstream<Ch> inc_stream(inc_name.c_str());
|
||||
if (!inc_stream.good())
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"cannot open include file " + inc_name,
|
||||
filename, line_no));
|
||||
read_info_internal(inc_stream, *stack.top(),
|
||||
inc_name, include_depth + 1);
|
||||
} else { // Unknown directive
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"unknown directive", filename, line_no));
|
||||
}
|
||||
|
||||
// Directive must be followed by end of line
|
||||
skip_whitespace(text);
|
||||
if (*text != Ch('\0')) {
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(
|
||||
"expected end of line", filename, line_no));
|
||||
}
|
||||
|
||||
// Go to next line
|
||||
continue;
|
||||
}
|
||||
|
||||
// While there are characters left in line
|
||||
while (1) {
|
||||
|
||||
// Stop parsing on end of line or comment
|
||||
skip_whitespace(text);
|
||||
if (*text == Ch('\0') || *text == Ch(';')) {
|
||||
if (state == s_data) // If there was no data set state to s_key
|
||||
state = s_key;
|
||||
break;
|
||||
}
|
||||
|
||||
// Process according to current parser state
|
||||
switch (state)
|
||||
{
|
||||
|
||||
// Parser expects key
|
||||
case s_key:
|
||||
{
|
||||
|
||||
if (*text == Ch('{')) // Brace opening found
|
||||
{
|
||||
if (!last)
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error("unexpected {", "", 0));
|
||||
stack.push(last);
|
||||
last = NULL;
|
||||
++text;
|
||||
}
|
||||
else if (*text == Ch('}')) // Brace closing found
|
||||
{
|
||||
if (stack.size() <= 1)
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error("unmatched }", "", 0));
|
||||
stack.pop();
|
||||
last = NULL;
|
||||
++text;
|
||||
}
|
||||
else // Key text found
|
||||
{
|
||||
std::basic_string<Ch> key = read_key(text);
|
||||
last = &stack.top()->push_back(
|
||||
std::make_pair(key, Ptree()))->second;
|
||||
state = s_data;
|
||||
}
|
||||
|
||||
}; break;
|
||||
|
||||
// Parser expects data
|
||||
case s_data:
|
||||
{
|
||||
|
||||
// Last ptree must be defined because we are going to add data to it
|
||||
BOOST_ASSERT(last);
|
||||
|
||||
if (*text == Ch('{')) // Brace opening found
|
||||
{
|
||||
stack.push(last);
|
||||
last = NULL;
|
||||
++text;
|
||||
state = s_key;
|
||||
}
|
||||
else if (*text == Ch('}')) // Brace closing found
|
||||
{
|
||||
if (stack.size() <= 1)
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error("unmatched }", "", 0));
|
||||
stack.pop();
|
||||
last = NULL;
|
||||
++text;
|
||||
state = s_key;
|
||||
}
|
||||
else // Data text found
|
||||
{
|
||||
bool need_more_lines;
|
||||
std::basic_string<Ch> data = read_data(text, &need_more_lines);
|
||||
last->data() = data;
|
||||
state = need_more_lines ? s_data_cont : s_key;
|
||||
}
|
||||
|
||||
|
||||
}; break;
|
||||
|
||||
// Parser expects continuation of data after \ on previous line
|
||||
case s_data_cont:
|
||||
{
|
||||
|
||||
// Last ptree must be defined because we are going to update its data
|
||||
BOOST_ASSERT(last);
|
||||
|
||||
if (*text == Ch('\"')) // Continuation must start with "
|
||||
{
|
||||
bool need_more_lines;
|
||||
std::basic_string<Ch> data = read_string(text, &need_more_lines);
|
||||
last->put_value(last->template get_value<std::basic_string<Ch> >() + data);
|
||||
state = need_more_lines ? s_data_cont : s_key;
|
||||
}
|
||||
else
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error("expected \" after \\ in previous line", "", 0));
|
||||
|
||||
}; break;
|
||||
|
||||
// Should never happen
|
||||
default:
|
||||
BOOST_ASSERT(0);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if stack has initial size, otherwise some {'s have not been closed
|
||||
if (stack.size() != 1)
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error("unmatched {", "", 0));
|
||||
|
||||
}
|
||||
catch (info_parser_error &e)
|
||||
{
|
||||
// If line undefined rethrow error with correct filename and line
|
||||
if (e.line() == 0)
|
||||
{
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error(e.message(), filename, line_no));
|
||||
}
|
||||
else
|
||||
BOOST_PROPERTY_TREE_THROW(e);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,32 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_CHCONV_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_CHCONV_HPP_INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace property_tree { namespace info_parser
|
||||
{
|
||||
|
||||
template<class ChDest, class ChSrc>
|
||||
std::basic_string<ChDest> convert_chtype(const ChSrc *text)
|
||||
{
|
||||
std::basic_string<ChDest> result;
|
||||
while (*text)
|
||||
{
|
||||
result += ChDest(*text);
|
||||
++text;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,147 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_WRITE_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_WRITE_HPP_INCLUDED
|
||||
|
||||
#include "boost/property_tree/ptree.hpp"
|
||||
#include "boost/property_tree/detail/info_parser_utils.hpp"
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace property_tree { namespace info_parser
|
||||
{
|
||||
template<class Ch>
|
||||
void write_info_indent(std::basic_ostream<Ch> &stream,
|
||||
int indent,
|
||||
const info_writer_settings<Ch> &settings
|
||||
)
|
||||
{
|
||||
stream << std::basic_string<Ch>(indent * settings.indent_count, settings.indent_char);
|
||||
}
|
||||
|
||||
// Create necessary escape sequences from illegal characters
|
||||
template<class Ch>
|
||||
std::basic_string<Ch> create_escapes(const std::basic_string<Ch> &s)
|
||||
{
|
||||
std::basic_string<Ch> result;
|
||||
typename std::basic_string<Ch>::const_iterator b = s.begin();
|
||||
typename std::basic_string<Ch>::const_iterator e = s.end();
|
||||
while (b != e)
|
||||
{
|
||||
if (*b == Ch('\0')) result += Ch('\\'), result += Ch('0');
|
||||
else if (*b == Ch('\a')) result += Ch('\\'), result += Ch('a');
|
||||
else if (*b == Ch('\b')) result += Ch('\\'), result += Ch('b');
|
||||
else if (*b == Ch('\f')) result += Ch('\\'), result += Ch('f');
|
||||
else if (*b == Ch('\n')) result += Ch('\\'), result += Ch('n');
|
||||
else if (*b == Ch('\r')) result += Ch('\\'), result += Ch('r');
|
||||
else if (*b == Ch('\v')) result += Ch('\\'), result += Ch('v');
|
||||
else if (*b == Ch('"')) result += Ch('\\'), result += Ch('"');
|
||||
else if (*b == Ch('\\')) result += Ch('\\'), result += Ch('\\');
|
||||
else
|
||||
result += *b;
|
||||
++b;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class Ch>
|
||||
bool is_simple_key(const std::basic_string<Ch> &key)
|
||||
{
|
||||
const static std::basic_string<Ch> chars = convert_chtype<Ch, char>(" \t{};\n\"");
|
||||
return !key.empty() && key.find_first_of(chars) == key.npos;
|
||||
}
|
||||
|
||||
template<class Ch>
|
||||
bool is_simple_data(const std::basic_string<Ch> &data)
|
||||
{
|
||||
const static std::basic_string<Ch> chars = convert_chtype<Ch, char>(" \t{};\n\"");
|
||||
return !data.empty() && data.find_first_of(chars) == data.npos;
|
||||
}
|
||||
|
||||
template<class Ptree>
|
||||
void write_info_helper(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
|
||||
const Ptree &pt,
|
||||
int indent,
|
||||
const info_writer_settings<typename Ptree::key_type::value_type> &settings)
|
||||
{
|
||||
|
||||
// Character type
|
||||
typedef typename Ptree::key_type::value_type Ch;
|
||||
|
||||
// Write data
|
||||
if (indent >= 0)
|
||||
{
|
||||
if (!pt.data().empty())
|
||||
{
|
||||
std::basic_string<Ch> data = create_escapes(pt.template get_value<std::basic_string<Ch> >());
|
||||
if (is_simple_data(data))
|
||||
stream << Ch(' ') << data << Ch('\n');
|
||||
else
|
||||
stream << Ch(' ') << Ch('\"') << data << Ch('\"') << Ch('\n');
|
||||
}
|
||||
else if (pt.empty())
|
||||
stream << Ch(' ') << Ch('\"') << Ch('\"') << Ch('\n');
|
||||
else
|
||||
stream << Ch('\n');
|
||||
}
|
||||
|
||||
// Write keys
|
||||
if (!pt.empty())
|
||||
{
|
||||
|
||||
// Open brace
|
||||
if (indent >= 0)
|
||||
{
|
||||
write_info_indent( stream, indent, settings);
|
||||
stream << Ch('{') << Ch('\n');
|
||||
}
|
||||
|
||||
// Write keys
|
||||
typename Ptree::const_iterator it = pt.begin();
|
||||
for (; it != pt.end(); ++it)
|
||||
{
|
||||
|
||||
// Output key
|
||||
std::basic_string<Ch> key = create_escapes(it->first);
|
||||
write_info_indent( stream, indent+1, settings);
|
||||
if (is_simple_key(key))
|
||||
stream << key;
|
||||
else
|
||||
stream << Ch('\"') << key << Ch('\"');
|
||||
|
||||
// Output data and children
|
||||
write_info_helper(stream, it->second, indent + 1, settings);
|
||||
|
||||
}
|
||||
|
||||
// Close brace
|
||||
if (indent >= 0)
|
||||
{
|
||||
write_info_indent( stream, indent, settings);
|
||||
stream << Ch('}') << Ch('\n');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Write ptree to info stream
|
||||
template<class Ptree>
|
||||
void write_info_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
|
||||
const Ptree &pt,
|
||||
const std::string &filename,
|
||||
const info_writer_settings<typename Ptree::key_type::value_type> &settings)
|
||||
{
|
||||
write_info_helper(stream, pt, -1, settings);
|
||||
if (!stream.good())
|
||||
BOOST_PROPERTY_TREE_THROW(info_parser_error("write error", filename, 0));
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright (C) 2002-2006 Marcin Kalicinski
|
||||
// Copyright (C) 2007 Alexey Baskakov
|
||||
//
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_WRITER_SETTINGS_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_INFO_PARSER_WRITER_SETTINGS_HPP_INCLUDED
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace property_tree { namespace info_parser
|
||||
{
|
||||
|
||||
template <class Ch>
|
||||
class info_writer_settings
|
||||
{
|
||||
public:
|
||||
info_writer_settings(Ch indent_char = Ch(' '), unsigned indent_count = 4):
|
||||
indent_char(indent_char),
|
||||
indent_count(indent_count)
|
||||
{
|
||||
}
|
||||
Ch indent_char;
|
||||
int indent_count;
|
||||
};
|
||||
|
||||
template <class Ch>
|
||||
info_writer_settings<Ch> info_writer_make_settings(Ch indent_char = Ch(' '), unsigned indent_count = 4)
|
||||
{
|
||||
return info_writer_settings<Ch>(indent_char, indent_count);
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
+933
@@ -0,0 +1,933 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright (C) 2002-2006 Marcin Kalicinski
|
||||
// Copyright (C) 2009 Sebastian Redl
|
||||
//
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_PTREE_IMPLEMENTATION_HPP_INCLUDED
|
||||
|
||||
#include <boost/iterator/iterator_adaptor.hpp>
|
||||
#include <boost/iterator/reverse_iterator.hpp>
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/utility/swap.hpp>
|
||||
#include <memory>
|
||||
|
||||
#if (defined(BOOST_MSVC) && \
|
||||
(_MSC_FULL_VER >= 160000000 && _MSC_FULL_VER < 170000000)) || \
|
||||
(defined(BOOST_INTEL_WIN) && \
|
||||
defined(BOOST_DINKUMWARE_STDLIB))
|
||||
#define BOOST_PROPERTY_TREE_PAIR_BUG
|
||||
#endif
|
||||
|
||||
namespace boost { namespace property_tree
|
||||
{
|
||||
template <class K, class D, class C>
|
||||
struct basic_ptree<K, D, C>::subs
|
||||
{
|
||||
struct by_name {};
|
||||
// The actual child container.
|
||||
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
||||
// MSVC 10 has moved std::pair's members to a base
|
||||
// class. Unfortunately this does break the interface.
|
||||
BOOST_STATIC_CONSTANT(unsigned,
|
||||
first_offset = offsetof(value_type, first));
|
||||
#endif
|
||||
typedef multi_index_container<value_type,
|
||||
multi_index::indexed_by<
|
||||
multi_index::sequenced<>,
|
||||
multi_index::ordered_non_unique<multi_index::tag<by_name>,
|
||||
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
||||
multi_index::member_offset<value_type, const key_type,
|
||||
first_offset>,
|
||||
#else
|
||||
multi_index::member<value_type, const key_type,
|
||||
&value_type::first>,
|
||||
#endif
|
||||
key_compare
|
||||
>
|
||||
>
|
||||
> base_container;
|
||||
|
||||
// The by-name lookup index.
|
||||
typedef typename base_container::template index<by_name>::type
|
||||
by_name_index;
|
||||
|
||||
// Access functions for getting to the children of a tree.
|
||||
static base_container& ch(self_type *s) {
|
||||
return *static_cast<base_container*>(s->m_children);
|
||||
}
|
||||
static const base_container& ch(const self_type *s) {
|
||||
return *static_cast<const base_container*>(s->m_children);
|
||||
}
|
||||
static by_name_index& assoc(self_type *s) {
|
||||
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
|
||||
}
|
||||
static const by_name_index& assoc(const self_type *s) {
|
||||
return ch(s).BOOST_NESTED_TEMPLATE get<by_name>();
|
||||
}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::iterator : public boost::iterator_adaptor<
|
||||
iterator, typename subs::base_container::iterator, value_type>
|
||||
{
|
||||
friend class boost::iterator_core_access;
|
||||
typedef boost::iterator_adaptor<
|
||||
iterator, typename subs::base_container::iterator, value_type>
|
||||
baset;
|
||||
public:
|
||||
typedef typename baset::reference reference;
|
||||
iterator() {}
|
||||
explicit iterator(typename iterator::base_type b)
|
||||
: iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
reference dereference() const
|
||||
{
|
||||
// multi_index doesn't allow modification of its values, because
|
||||
// indexes could sort by anything, and modification screws that up.
|
||||
// However, we only sort by the key, and it's protected against
|
||||
// modification in the value_type, so this const_cast is safe.
|
||||
return const_cast<reference>(*this->base_reference());
|
||||
}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::const_iterator : public boost::iterator_adaptor<
|
||||
const_iterator, typename subs::base_container::const_iterator>
|
||||
{
|
||||
public:
|
||||
const_iterator() {}
|
||||
explicit const_iterator(typename const_iterator::base_type b)
|
||||
: const_iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
const_iterator(iterator b)
|
||||
: const_iterator::iterator_adaptor_(b.base())
|
||||
{}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::reverse_iterator
|
||||
: public boost::reverse_iterator<iterator>
|
||||
{
|
||||
public:
|
||||
reverse_iterator() {}
|
||||
explicit reverse_iterator(iterator b)
|
||||
: boost::reverse_iterator<iterator>(b)
|
||||
{}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::const_reverse_iterator
|
||||
: public boost::reverse_iterator<const_iterator>
|
||||
{
|
||||
public:
|
||||
const_reverse_iterator() {}
|
||||
explicit const_reverse_iterator(const_iterator b)
|
||||
: boost::reverse_iterator<const_iterator>(b)
|
||||
{}
|
||||
const_reverse_iterator(
|
||||
typename basic_ptree<K, D, C>::reverse_iterator b)
|
||||
: boost::reverse_iterator<const_iterator>(b)
|
||||
{}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::assoc_iterator
|
||||
: public boost::iterator_adaptor<assoc_iterator,
|
||||
typename subs::by_name_index::iterator,
|
||||
value_type>
|
||||
{
|
||||
friend class boost::iterator_core_access;
|
||||
typedef boost::iterator_adaptor<assoc_iterator,
|
||||
typename subs::by_name_index::iterator,
|
||||
value_type>
|
||||
baset;
|
||||
public:
|
||||
typedef typename baset::reference reference;
|
||||
assoc_iterator() {}
|
||||
explicit assoc_iterator(typename assoc_iterator::base_type b)
|
||||
: assoc_iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
reference dereference() const
|
||||
{
|
||||
return const_cast<reference>(*this->base_reference());
|
||||
}
|
||||
};
|
||||
template <class K, class D, class C>
|
||||
class basic_ptree<K, D, C>::const_assoc_iterator
|
||||
: public boost::iterator_adaptor<const_assoc_iterator,
|
||||
typename subs::by_name_index::const_iterator>
|
||||
{
|
||||
public:
|
||||
const_assoc_iterator() {}
|
||||
explicit const_assoc_iterator(
|
||||
typename const_assoc_iterator::base_type b)
|
||||
: const_assoc_iterator::iterator_adaptor_(b)
|
||||
{}
|
||||
const_assoc_iterator(assoc_iterator b)
|
||||
: const_assoc_iterator::iterator_adaptor_(b.base())
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
// Big five
|
||||
|
||||
// Perhaps the children collection could be created on-demand only, to
|
||||
// reduce heap traffic. But that's a lot more work to implement.
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C>::basic_ptree()
|
||||
: m_children(new typename subs::base_container)
|
||||
{
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C>::basic_ptree(const data_type &d)
|
||||
: m_data(d), m_children(new typename subs::base_container)
|
||||
{
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C>::basic_ptree(const basic_ptree<K, D, C> &rhs)
|
||||
: m_data(rhs.m_data),
|
||||
m_children(new typename subs::base_container(subs::ch(&rhs)))
|
||||
{
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::operator =(const basic_ptree<K, D, C> &rhs)
|
||||
{
|
||||
self_type(rhs).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C>::~basic_ptree()
|
||||
{
|
||||
delete &subs::ch(this);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::swap(basic_ptree<K, D, C> &rhs)
|
||||
{
|
||||
boost::swap(m_data, rhs.m_data);
|
||||
// Void pointers, no ADL necessary
|
||||
std::swap(m_children, rhs.m_children);
|
||||
}
|
||||
|
||||
// Container view
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::size() const
|
||||
{
|
||||
return subs::ch(this).size();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::max_size() const
|
||||
{
|
||||
return subs::ch(this).max_size();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
bool basic_ptree<K, D, C>::empty() const
|
||||
{
|
||||
return subs::ch(this).empty();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::begin()
|
||||
{
|
||||
return iterator(subs::ch(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_iterator
|
||||
basic_ptree<K, D, C>::begin() const
|
||||
{
|
||||
return const_iterator(subs::ch(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::end()
|
||||
{
|
||||
return iterator(subs::ch(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_iterator
|
||||
basic_ptree<K, D, C>::end() const
|
||||
{
|
||||
return const_iterator(subs::ch(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::reverse_iterator
|
||||
basic_ptree<K, D, C>::rbegin()
|
||||
{
|
||||
return reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_reverse_iterator
|
||||
basic_ptree<K, D, C>::rbegin() const
|
||||
{
|
||||
return const_reverse_iterator(this->end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::reverse_iterator
|
||||
basic_ptree<K, D, C>::rend()
|
||||
{
|
||||
return reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_reverse_iterator
|
||||
basic_ptree<K, D, C>::rend() const
|
||||
{
|
||||
return const_reverse_iterator(this->begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::front()
|
||||
{
|
||||
return const_cast<value_type&>(subs::ch(this).front());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::front() const
|
||||
{
|
||||
return subs::ch(this).front();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::back()
|
||||
{
|
||||
return const_cast<value_type&>(subs::ch(this).back());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const typename basic_ptree<K, D, C>::value_type &
|
||||
basic_ptree<K, D, C>::back() const
|
||||
{
|
||||
return subs::ch(this).back();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::insert(iterator where, const value_type &value)
|
||||
{
|
||||
return iterator(subs::ch(this).insert(where.base(), value).first);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class It> inline
|
||||
void basic_ptree<K, D, C>::insert(iterator where, It first, It last)
|
||||
{
|
||||
subs::ch(this).insert(where.base(), first, last);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::erase(iterator where)
|
||||
{
|
||||
return iterator(subs::ch(this).erase(where.base()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::erase(iterator first, iterator last)
|
||||
{
|
||||
return iterator(subs::ch(this).erase(first.base(), last.base()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::push_front(const value_type &value)
|
||||
{
|
||||
return iterator(subs::ch(this).push_front(value).first);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::push_back(const value_type &value)
|
||||
{
|
||||
return iterator(subs::ch(this).push_back(value).first);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::pop_front()
|
||||
{
|
||||
subs::ch(this).pop_front();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::pop_back()
|
||||
{
|
||||
subs::ch(this).pop_back();
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::reverse()
|
||||
{
|
||||
subs::ch(this).reverse();
|
||||
}
|
||||
|
||||
namespace impl
|
||||
{
|
||||
struct by_first
|
||||
{
|
||||
template <typename P>
|
||||
bool operator ()(const P& lhs, const P& rhs) const {
|
||||
return lhs.first < rhs.first;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename C>
|
||||
struct equal_pred
|
||||
{
|
||||
template <typename P>
|
||||
bool operator ()(const P& lhs, const P& rhs) const {
|
||||
C c;
|
||||
return !c(lhs.first, rhs.first) &&
|
||||
!c(rhs.first, lhs.first) &&
|
||||
lhs.second == rhs.second;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename C, typename MI>
|
||||
bool equal_children(const MI& ch1, const MI& ch2) {
|
||||
// Assumes ch1.size() == ch2.size()
|
||||
return std::equal(ch1.begin(), ch1.end(),
|
||||
ch2.begin(), equal_pred<C>());
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::sort()
|
||||
{
|
||||
sort(impl::by_first());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Compare> inline
|
||||
void basic_ptree<K, D, C>::sort(Compare comp)
|
||||
{
|
||||
subs::ch(this).sort(comp);
|
||||
}
|
||||
|
||||
// Equality
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
bool basic_ptree<K, D, C>::operator ==(
|
||||
const basic_ptree<K, D, C> &rhs) const
|
||||
{
|
||||
// The size test is cheap, so add it as an optimization
|
||||
return size() == rhs.size() && data() == rhs.data() &&
|
||||
impl::equal_children<C>(subs::ch(this), subs::ch(&rhs));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
bool basic_ptree<K, D, C>::operator !=(
|
||||
const basic_ptree<K, D, C> &rhs) const
|
||||
{
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
// Associative view
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
basic_ptree<K, D, C>::ordered_begin()
|
||||
{
|
||||
return assoc_iterator(subs::assoc(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
basic_ptree<K, D, C>::ordered_begin() const
|
||||
{
|
||||
return const_assoc_iterator(subs::assoc(this).begin());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
basic_ptree<K, D, C>::not_found()
|
||||
{
|
||||
return assoc_iterator(subs::assoc(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
basic_ptree<K, D, C>::not_found() const
|
||||
{
|
||||
return const_assoc_iterator(subs::assoc(this).end());
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
basic_ptree<K, D, C>::find(const key_type &key)
|
||||
{
|
||||
return assoc_iterator(subs::assoc(this).find(key));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
basic_ptree<K, D, C>::find(const key_type &key) const
|
||||
{
|
||||
return const_assoc_iterator(subs::assoc(this).find(key));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
std::pair<
|
||||
typename basic_ptree<K, D, C>::assoc_iterator,
|
||||
typename basic_ptree<K, D, C>::assoc_iterator
|
||||
> basic_ptree<K, D, C>::equal_range(const key_type &key)
|
||||
{
|
||||
std::pair<typename subs::by_name_index::iterator,
|
||||
typename subs::by_name_index::iterator> r(
|
||||
subs::assoc(this).equal_range(key));
|
||||
return std::pair<assoc_iterator, assoc_iterator>(
|
||||
assoc_iterator(r.first), assoc_iterator(r.second));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
std::pair<
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator,
|
||||
typename basic_ptree<K, D, C>::const_assoc_iterator
|
||||
> basic_ptree<K, D, C>::equal_range(const key_type &key) const
|
||||
{
|
||||
std::pair<typename subs::by_name_index::const_iterator,
|
||||
typename subs::by_name_index::const_iterator> r(
|
||||
subs::assoc(this).equal_range(key));
|
||||
return std::pair<const_assoc_iterator, const_assoc_iterator>(
|
||||
const_assoc_iterator(r.first), const_assoc_iterator(r.second));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::count(const key_type &key) const
|
||||
{
|
||||
return subs::assoc(this).count(key);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::size_type
|
||||
basic_ptree<K, D, C>::erase(const key_type &key)
|
||||
{
|
||||
return subs::assoc(this).erase(key);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::iterator
|
||||
basic_ptree<K, D, C>::to_iterator(assoc_iterator ai)
|
||||
{
|
||||
return iterator(subs::ch(this).
|
||||
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::const_iterator
|
||||
basic_ptree<K, D, C>::to_iterator(const_assoc_iterator ai) const
|
||||
{
|
||||
return const_iterator(subs::ch(this).
|
||||
BOOST_NESTED_TEMPLATE project<0>(ai.base()));
|
||||
}
|
||||
|
||||
// Property tree view
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
typename basic_ptree<K, D, C>::data_type &
|
||||
basic_ptree<K, D, C>::data()
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const typename basic_ptree<K, D, C>::data_type &
|
||||
basic_ptree<K, D, C>::data() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
void basic_ptree<K, D, C>::clear()
|
||||
{
|
||||
m_data = data_type();
|
||||
subs::ch(this).clear();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
if (!n) {
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_path("No such node", path));
|
||||
}
|
||||
return *n;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path) const
|
||||
{
|
||||
return const_cast<self_type*>(this)->get_child(path);
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path,
|
||||
self_type &default_value)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
return n ? *n : default_value;
|
||||
}
|
||||
|
||||
template<class K, class D, class C> inline
|
||||
const basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::get_child(const path_type &path,
|
||||
const self_type &default_value) const
|
||||
{
|
||||
return const_cast<self_type*>(this)->get_child(path,
|
||||
const_cast<self_type&>(default_value));
|
||||
}
|
||||
|
||||
|
||||
template<class K, class D, class C>
|
||||
optional<basic_ptree<K, D, C> &>
|
||||
basic_ptree<K, D, C>::get_child_optional(const path_type &path)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
if (!n) {
|
||||
return optional<self_type&>();
|
||||
}
|
||||
return *n;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
optional<const basic_ptree<K, D, C> &>
|
||||
basic_ptree<K, D, C>::get_child_optional(const path_type &path) const
|
||||
{
|
||||
path_type p(path);
|
||||
self_type *n = walk_path(p);
|
||||
if (!n) {
|
||||
return optional<const self_type&>();
|
||||
}
|
||||
return *n;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::put_child(const path_type &path,
|
||||
const self_type &value)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type &parent = force_path(p);
|
||||
// Got the parent. Now get the correct child.
|
||||
key_type fragment = p.reduce();
|
||||
assoc_iterator el = parent.find(fragment);
|
||||
// If the new child exists, replace it.
|
||||
if(el != parent.not_found()) {
|
||||
return el->second = value;
|
||||
} else {
|
||||
return parent.push_back(value_type(fragment, value))->second;
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> &
|
||||
basic_ptree<K, D, C>::add_child(const path_type &path,
|
||||
const self_type &value)
|
||||
{
|
||||
path_type p(path);
|
||||
self_type &parent = force_path(p);
|
||||
// Got the parent.
|
||||
key_type fragment = p.reduce();
|
||||
return parent.push_back(value_type(fragment, value))->second;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator>
|
||||
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
|
||||
basic_ptree<K, D, C>::get_value(Translator tr) const
|
||||
{
|
||||
if(boost::optional<Type> o = get_value_optional<Type>(tr)) {
|
||||
return *o;
|
||||
}
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
||||
std::string("conversion of data to type \"") +
|
||||
typeid(Type).name() + "\" failed", data()));
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
Type basic_ptree<K, D, C>::get_value() const
|
||||
{
|
||||
return get_value<Type>(
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
Type basic_ptree<K, D, C>::get_value(const Type &default_value,
|
||||
Translator tr) const
|
||||
{
|
||||
return get_value_optional<Type>(tr).get_value_or(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch, class Translator>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get_value(const Ch *default_value, Translator tr)const
|
||||
{
|
||||
return get_value<std::basic_string<Ch>, Translator>(default_value, tr);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
typename boost::disable_if<detail::is_translator<Type>, Type>::type
|
||||
basic_ptree<K, D, C>::get_value(const Type &default_value) const
|
||||
{
|
||||
return get_value(default_value,
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get_value(const Ch *default_value) const
|
||||
{
|
||||
return get_value< std::basic_string<Ch> >(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
optional<Type> basic_ptree<K, D, C>::get_value_optional(
|
||||
Translator tr) const
|
||||
{
|
||||
return tr.get_value(data());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
optional<Type> basic_ptree<K, D, C>::get_value_optional() const
|
||||
{
|
||||
return get_value_optional<Type>(
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
typename boost::enable_if<detail::is_translator<Translator>, Type>::type
|
||||
basic_ptree<K, D, C>::get(const path_type &path,
|
||||
Translator tr) const
|
||||
{
|
||||
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>(tr);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
Type basic_ptree<K, D, C>::get(const path_type &path) const
|
||||
{
|
||||
return get_child(path).BOOST_NESTED_TEMPLATE get_value<Type>();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator> inline
|
||||
Type basic_ptree<K, D, C>::get(const path_type &path,
|
||||
const Type &default_value,
|
||||
Translator tr) const
|
||||
{
|
||||
return get_optional<Type>(path, tr).get_value_or(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch, class Translator>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get(
|
||||
const path_type &path, const Ch *default_value, Translator tr) const
|
||||
{
|
||||
return get<std::basic_string<Ch>, Translator>(path, default_value, tr);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
typename boost::disable_if<detail::is_translator<Type>, Type>::type
|
||||
basic_ptree<K, D, C>::get(const path_type &path,
|
||||
const Type &default_value) const
|
||||
{
|
||||
return get_optional<Type>(path).get_value_or(default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template <class Ch>
|
||||
typename boost::enable_if<
|
||||
detail::is_character<Ch>,
|
||||
std::basic_string<Ch>
|
||||
>::type
|
||||
basic_ptree<K, D, C>::get(
|
||||
const path_type &path, const Ch *default_value) const
|
||||
{
|
||||
return get< std::basic_string<Ch> >(path, default_value);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator>
|
||||
optional<Type> basic_ptree<K, D, C>::get_optional(const path_type &path,
|
||||
Translator tr) const
|
||||
{
|
||||
if (optional<const self_type&> child = get_child_optional(path))
|
||||
return child.get().
|
||||
BOOST_NESTED_TEMPLATE get_value_optional<Type>(tr);
|
||||
else
|
||||
return optional<Type>();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type>
|
||||
optional<Type> basic_ptree<K, D, C>::get_optional(
|
||||
const path_type &path) const
|
||||
{
|
||||
if (optional<const self_type&> child = get_child_optional(path))
|
||||
return child.get().BOOST_NESTED_TEMPLATE get_value_optional<Type>();
|
||||
else
|
||||
return optional<Type>();
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, class Translator>
|
||||
void basic_ptree<K, D, C>::put_value(const Type &value, Translator tr)
|
||||
{
|
||||
if(optional<data_type> o = tr.put_value(value)) {
|
||||
data() = *o;
|
||||
} else {
|
||||
BOOST_PROPERTY_TREE_THROW(ptree_bad_data(
|
||||
std::string("conversion of type \"") + typeid(Type).name() +
|
||||
"\" to data failed", boost::any()));
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
void basic_ptree<K, D, C>::put_value(const Type &value)
|
||||
{
|
||||
put_value(value, typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, typename Translator>
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
|
||||
const path_type &path, const Type &value, Translator tr)
|
||||
{
|
||||
if(optional<self_type &> child = get_child_optional(path)) {
|
||||
child.get().put_value(value, tr);
|
||||
return *child;
|
||||
} else {
|
||||
self_type &child2 = put_child(path, self_type());
|
||||
child2.put_value(value, tr);
|
||||
return child2;
|
||||
}
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::put(
|
||||
const path_type &path, const Type &value)
|
||||
{
|
||||
return put(path, value,
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type, typename Translator> inline
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
|
||||
const path_type &path, const Type &value, Translator tr)
|
||||
{
|
||||
self_type &child = add_child(path, self_type());
|
||||
child.put_value(value, tr);
|
||||
return child;
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
template<class Type> inline
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::add(
|
||||
const path_type &path, const Type &value)
|
||||
{
|
||||
return add(path, value,
|
||||
typename translator_between<data_type, Type>::type());
|
||||
}
|
||||
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> *
|
||||
basic_ptree<K, D, C>::walk_path(path_type &p) const
|
||||
{
|
||||
if(p.empty()) {
|
||||
// I'm the child we're looking for.
|
||||
return const_cast<basic_ptree*>(this);
|
||||
}
|
||||
// Recurse down the tree to find the path.
|
||||
key_type fragment = p.reduce();
|
||||
const_assoc_iterator el = find(fragment);
|
||||
if(el == not_found()) {
|
||||
// No such child.
|
||||
return 0;
|
||||
}
|
||||
// Not done yet, recurse.
|
||||
return el->second.walk_path(p);
|
||||
}
|
||||
|
||||
template<class K, class D, class C>
|
||||
basic_ptree<K, D, C> & basic_ptree<K, D, C>::force_path(path_type &p)
|
||||
{
|
||||
BOOST_ASSERT(!p.empty() && "Empty path not allowed for put_child.");
|
||||
if(p.single()) {
|
||||
// I'm the parent we're looking for.
|
||||
return *this;
|
||||
}
|
||||
key_type fragment = p.reduce();
|
||||
assoc_iterator el = find(fragment);
|
||||
// If we've found an existing child, go down that path. Else
|
||||
// create a new one.
|
||||
self_type& child = el == not_found() ?
|
||||
push_back(value_type(fragment, self_type()))->second : el->second;
|
||||
return child.force_path(p);
|
||||
}
|
||||
|
||||
// Free functions
|
||||
|
||||
template<class K, class D, class C>
|
||||
inline void swap(basic_ptree<K, D, C> &pt1, basic_ptree<K, D, C> &pt2)
|
||||
{
|
||||
pt1.swap(pt2);
|
||||
}
|
||||
|
||||
} }
|
||||
|
||||
#if defined(BOOST_PROPERTY_TREE_PAIR_BUG)
|
||||
#undef BOOST_PROPERTY_TREE_PAIR_BUG
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,105 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_PTREE_UTILS_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_PTREE_UTILS_HPP_INCLUDED
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
#include <boost/type_traits/integral_constant.hpp>
|
||||
#include <boost/mpl/has_xxx.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <locale>
|
||||
|
||||
namespace boost { namespace property_tree { namespace detail
|
||||
{
|
||||
|
||||
template<class T>
|
||||
struct less_nocase
|
||||
{
|
||||
typedef typename T::value_type Ch;
|
||||
std::locale m_locale;
|
||||
inline bool operator()(Ch c1, Ch c2) const
|
||||
{
|
||||
return std::toupper(c1, m_locale) < std::toupper(c2, m_locale);
|
||||
}
|
||||
inline bool operator()(const T &t1, const T &t2) const
|
||||
{
|
||||
return std::lexicographical_compare(t1.begin(), t1.end(),
|
||||
t2.begin(), t2.end(), *this);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Ch>
|
||||
struct is_character : public boost::false_type {};
|
||||
template <>
|
||||
struct is_character<char> : public boost::true_type {};
|
||||
template <>
|
||||
struct is_character<wchar_t> : public boost::true_type {};
|
||||
|
||||
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(internal_type)
|
||||
BOOST_MPL_HAS_XXX_TRAIT_DEF(external_type)
|
||||
template <typename T>
|
||||
struct is_translator : public boost::mpl::and_<
|
||||
has_internal_type<T>, has_external_type<T> > {};
|
||||
|
||||
|
||||
|
||||
// Naively convert narrow string to another character type
|
||||
template<typename Str>
|
||||
Str widen(const char *text)
|
||||
{
|
||||
Str result;
|
||||
while (*text)
|
||||
{
|
||||
result += typename Str::value_type(*text);
|
||||
++text;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Naively convert string to narrow character type
|
||||
template<typename Str, typename char_type>
|
||||
Str narrow(const char_type *text)
|
||||
{
|
||||
Str result;
|
||||
while (*text)
|
||||
{
|
||||
if (*text < 0 || *text > (std::numeric_limits<char>::max)())
|
||||
result += '*';
|
||||
else
|
||||
result += typename Str::value_type(*text);
|
||||
++text;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Remove trailing and leading spaces
|
||||
template<class Str>
|
||||
Str trim(const Str &s, const std::locale &loc = std::locale())
|
||||
{
|
||||
typename Str::const_iterator first = s.begin();
|
||||
typename Str::const_iterator end = s.end();
|
||||
while (first != end && std::isspace(*first, loc))
|
||||
++first;
|
||||
if (first == end)
|
||||
return Str();
|
||||
typename Str::const_iterator last = end;
|
||||
do --last; while (std::isspace(*last, loc));
|
||||
if (first != s.begin() || last + 1 != end)
|
||||
return Str(first, last + 1);
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_ERROR_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_ERROR_HPP_INCLUDED
|
||||
|
||||
#include <boost/property_tree/detail/file_parser_error.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost { namespace property_tree { namespace xml_parser
|
||||
{
|
||||
|
||||
//! Xml parser error
|
||||
class xml_parser_error: public file_parser_error
|
||||
{
|
||||
public:
|
||||
xml_parser_error(const std::string &msg,
|
||||
const std::string &file,
|
||||
unsigned long l):
|
||||
file_parser_error(msg, file, l)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,31 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_FLAGS_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_FLAGS_HPP_INCLUDED
|
||||
|
||||
namespace boost { namespace property_tree { namespace xml_parser
|
||||
{
|
||||
|
||||
/// Text elements should be put in separate keys,
|
||||
/// not concatenated in parent data.
|
||||
static const int no_concat_text = 0x1;
|
||||
/// Comments should be omitted.
|
||||
static const int no_comments = 0x2;
|
||||
/// Whitespace should be collapsed and trimmed.
|
||||
static const int trim_whitespace = 0x4;
|
||||
|
||||
inline bool validate_flags(int flags)
|
||||
{
|
||||
return (flags & ~(no_concat_text | no_comments | trim_whitespace)) == 0;
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright (C) 2007 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_RAPIDXML_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_READ_RAPIDXML_HPP_INCLUDED
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/detail/xml_parser_error.hpp>
|
||||
#include <boost/property_tree/detail/xml_parser_flags.hpp>
|
||||
#include <boost/property_tree/detail/xml_parser_utils.hpp>
|
||||
#include <boost/property_tree/detail/rapidxml.hpp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace property_tree { namespace xml_parser
|
||||
{
|
||||
|
||||
template<class Ptree, class Ch>
|
||||
void read_xml_node(detail::rapidxml::xml_node<Ch> *node,
|
||||
Ptree &pt, int flags)
|
||||
{
|
||||
using namespace detail::rapidxml;
|
||||
switch (node->type())
|
||||
{
|
||||
// Element nodes
|
||||
case node_element:
|
||||
{
|
||||
// Create node
|
||||
Ptree &pt_node = pt.push_back(std::make_pair(node->name(),
|
||||
Ptree()))->second;
|
||||
|
||||
// Copy attributes
|
||||
if (node->first_attribute())
|
||||
{
|
||||
Ptree &pt_attr_root = pt_node.push_back(
|
||||
std::make_pair(xmlattr<typename Ptree::key_type>(), Ptree()))->second;
|
||||
for (xml_attribute<Ch> *attr = node->first_attribute();
|
||||
attr; attr = attr->next_attribute())
|
||||
{
|
||||
Ptree &pt_attr = pt_attr_root.push_back(
|
||||
std::make_pair(attr->name(), Ptree()))->second;
|
||||
pt_attr.data() = typename Ptree::key_type(attr->value(), attr->value_size());
|
||||
}
|
||||
}
|
||||
|
||||
// Copy children
|
||||
for (xml_node<Ch> *child = node->first_node();
|
||||
child; child = child->next_sibling())
|
||||
read_xml_node(child, pt_node, flags);
|
||||
}
|
||||
break;
|
||||
|
||||
// Data nodes
|
||||
case node_data:
|
||||
case node_cdata:
|
||||
{
|
||||
if (flags & no_concat_text)
|
||||
pt.push_back(std::make_pair(xmltext<typename Ptree::key_type>(),
|
||||
Ptree(node->value())));
|
||||
else
|
||||
pt.data() += typename Ptree::key_type(node->value(), node->value_size());
|
||||
}
|
||||
break;
|
||||
|
||||
// Comment nodes
|
||||
case node_comment:
|
||||
{
|
||||
if (!(flags & no_comments))
|
||||
pt.push_back(std::make_pair(xmlcomment<typename Ptree::key_type>(),
|
||||
Ptree(typename Ptree::key_type(node->value(), node->value_size()))));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Skip other node types
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<class Ptree>
|
||||
void read_xml_internal(std::basic_istream<
|
||||
typename Ptree::key_type::value_type> &stream,
|
||||
Ptree &pt,
|
||||
int flags,
|
||||
const std::string &filename)
|
||||
{
|
||||
typedef typename Ptree::key_type::value_type Ch;
|
||||
using namespace detail::rapidxml;
|
||||
|
||||
// Load data into vector
|
||||
stream.unsetf(std::ios::skipws);
|
||||
std::vector<Ch> v(std::istreambuf_iterator<Ch>(stream.rdbuf()),
|
||||
std::istreambuf_iterator<Ch>());
|
||||
if (!stream.good())
|
||||
BOOST_PROPERTY_TREE_THROW(
|
||||
xml_parser_error("read error", filename, 0));
|
||||
v.push_back(0); // zero-terminate
|
||||
|
||||
try {
|
||||
// Parse using appropriate flags
|
||||
const int f_tws = parse_normalize_whitespace
|
||||
| parse_trim_whitespace;
|
||||
const int f_c = parse_comment_nodes;
|
||||
// Some compilers don't like the bitwise or in the template arg.
|
||||
const int f_tws_c = parse_normalize_whitespace
|
||||
| parse_trim_whitespace
|
||||
| parse_comment_nodes;
|
||||
xml_document<Ch> doc;
|
||||
if (flags & no_comments) {
|
||||
if (flags & trim_whitespace)
|
||||
doc.BOOST_NESTED_TEMPLATE parse<f_tws>(&v.front());
|
||||
else
|
||||
doc.BOOST_NESTED_TEMPLATE parse<0>(&v.front());
|
||||
} else {
|
||||
if (flags & trim_whitespace)
|
||||
doc.BOOST_NESTED_TEMPLATE parse<f_tws_c>(&v.front());
|
||||
else
|
||||
doc.BOOST_NESTED_TEMPLATE parse<f_c>(&v.front());
|
||||
}
|
||||
|
||||
// Create ptree from nodes
|
||||
Ptree local;
|
||||
for (xml_node<Ch> *child = doc.first_node();
|
||||
child; child = child->next_sibling())
|
||||
read_xml_node(child, local, flags);
|
||||
|
||||
// Swap local and result ptrees
|
||||
pt.swap(local);
|
||||
} catch (parse_error &e) {
|
||||
long line = static_cast<long>(
|
||||
std::count(&v.front(), e.where<Ch>(), Ch('\n')) + 1);
|
||||
BOOST_PROPERTY_TREE_THROW(
|
||||
xml_parser_error(e.what(), filename, line));
|
||||
}
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,139 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_UTILS_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_UTILS_HPP_INCLUDED
|
||||
|
||||
#include <boost/property_tree/detail/ptree_utils.hpp>
|
||||
#include <boost/property_tree/detail/xml_parser_error.hpp>
|
||||
#include <boost/property_tree/detail/xml_parser_writer_settings.hpp>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <locale>
|
||||
|
||||
namespace boost { namespace property_tree { namespace xml_parser
|
||||
{
|
||||
|
||||
template<class Str>
|
||||
Str condense(const Str &s)
|
||||
{
|
||||
typedef typename Str::value_type Ch;
|
||||
Str r;
|
||||
std::locale loc;
|
||||
bool space = false;
|
||||
typename Str::const_iterator end = s.end();
|
||||
for (typename Str::const_iterator it = s.begin();
|
||||
it != end; ++it)
|
||||
{
|
||||
if (isspace(*it, loc) || *it == Ch('\n'))
|
||||
{
|
||||
if (!space)
|
||||
r += Ch(' '), space = true;
|
||||
}
|
||||
else
|
||||
r += *it, space = false;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
template<class Str>
|
||||
Str encode_char_entities(const Str &s)
|
||||
{
|
||||
// Don't do anything for empty strings.
|
||||
if(s.empty()) return s;
|
||||
|
||||
typedef typename Str::value_type Ch;
|
||||
|
||||
Str r;
|
||||
// To properly round-trip spaces and not uglify the XML beyond
|
||||
// recognition, we have to encode them IF the text contains only spaces.
|
||||
Str sp(1, Ch(' '));
|
||||
if(s.find_first_not_of(sp) == Str::npos) {
|
||||
// The first will suffice.
|
||||
r = detail::widen<Str>(" ");
|
||||
r += Str(s.size() - 1, Ch(' '));
|
||||
} else {
|
||||
typename Str::const_iterator end = s.end();
|
||||
for (typename Str::const_iterator it = s.begin(); it != end; ++it)
|
||||
{
|
||||
switch (*it)
|
||||
{
|
||||
case Ch('<'): r += detail::widen<Str>("<"); break;
|
||||
case Ch('>'): r += detail::widen<Str>(">"); break;
|
||||
case Ch('&'): r += detail::widen<Str>("&"); break;
|
||||
case Ch('"'): r += detail::widen<Str>("""); break;
|
||||
case Ch('\''): r += detail::widen<Str>("'"); break;
|
||||
default: r += *it; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<class Str>
|
||||
Str decode_char_entities(const Str &s)
|
||||
{
|
||||
typedef typename Str::value_type Ch;
|
||||
Str r;
|
||||
typename Str::const_iterator end = s.end();
|
||||
for (typename Str::const_iterator it = s.begin(); it != end; ++it)
|
||||
{
|
||||
if (*it == Ch('&'))
|
||||
{
|
||||
typename Str::const_iterator semicolon = std::find(it + 1, end, Ch(';'));
|
||||
if (semicolon == end)
|
||||
BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0));
|
||||
Str ent(it + 1, semicolon);
|
||||
if (ent == detail::widen<Str>("lt")) r += Ch('<');
|
||||
else if (ent == detail::widen<Str>("gt")) r += Ch('>');
|
||||
else if (ent == detail::widen<Str>("amp")) r += Ch('&');
|
||||
else if (ent == detail::widen<Str>("quot")) r += Ch('"');
|
||||
else if (ent == detail::widen<Str>("apos")) r += Ch('\'');
|
||||
else
|
||||
BOOST_PROPERTY_TREE_THROW(xml_parser_error("invalid character entity", "", 0));
|
||||
it = semicolon;
|
||||
}
|
||||
else
|
||||
r += *it;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
template<class Str>
|
||||
const Str &xmldecl()
|
||||
{
|
||||
static Str s = detail::widen<Str>("<?xml>");
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Str>
|
||||
const Str &xmlattr()
|
||||
{
|
||||
static Str s = detail::widen<Str>("<xmlattr>");
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Str>
|
||||
const Str &xmlcomment()
|
||||
{
|
||||
static Str s = detail::widen<Str>("<xmlcomment>");
|
||||
return s;
|
||||
}
|
||||
|
||||
template<class Str>
|
||||
const Str &xmltext()
|
||||
{
|
||||
static Str s = detail::widen<Str>("<xmltext>");
|
||||
return s;
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,195 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright (C) 2002-2006 Marcin Kalicinski
|
||||
// Copyright (C) 2013 Sebastian Redl
|
||||
//
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_WRITE_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_WRITE_HPP_INCLUDED
|
||||
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/detail/xml_parser_utils.hpp>
|
||||
#include <string>
|
||||
#include <ostream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace boost { namespace property_tree { namespace xml_parser
|
||||
{
|
||||
template<class Str>
|
||||
void write_xml_indent(std::basic_ostream<typename Str::value_type> &stream,
|
||||
int indent,
|
||||
const xml_writer_settings<Str> & settings
|
||||
)
|
||||
{
|
||||
stream << std::basic_string<typename Str::value_type>(indent * settings.indent_count, settings.indent_char);
|
||||
}
|
||||
|
||||
template<class Str>
|
||||
void write_xml_comment(std::basic_ostream<typename Str::value_type> &stream,
|
||||
const Str &s,
|
||||
int indent,
|
||||
bool separate_line,
|
||||
const xml_writer_settings<Str> & settings
|
||||
)
|
||||
{
|
||||
typedef typename Str::value_type Ch;
|
||||
if (separate_line)
|
||||
write_xml_indent(stream,indent,settings);
|
||||
stream << Ch('<') << Ch('!') << Ch('-') << Ch('-');
|
||||
stream << s;
|
||||
stream << Ch('-') << Ch('-') << Ch('>');
|
||||
if (separate_line)
|
||||
stream << Ch('\n');
|
||||
}
|
||||
|
||||
template<class Str>
|
||||
void write_xml_text(std::basic_ostream<typename Str::value_type> &stream,
|
||||
const Str &s,
|
||||
int indent,
|
||||
bool separate_line,
|
||||
const xml_writer_settings<Str> & settings
|
||||
)
|
||||
{
|
||||
typedef typename Str::value_type Ch;
|
||||
if (separate_line)
|
||||
write_xml_indent(stream,indent,settings);
|
||||
stream << encode_char_entities(s);
|
||||
if (separate_line)
|
||||
stream << Ch('\n');
|
||||
}
|
||||
|
||||
template<class Ptree>
|
||||
void write_xml_element(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
|
||||
const typename Ptree::key_type &key,
|
||||
const Ptree &pt,
|
||||
int indent,
|
||||
const xml_writer_settings<typename Ptree::key_type> & settings)
|
||||
{
|
||||
typedef typename Ptree::key_type::value_type Ch;
|
||||
typedef typename Ptree::key_type Str;
|
||||
typedef typename Ptree::const_iterator It;
|
||||
|
||||
bool want_pretty = settings.indent_count > 0;
|
||||
// Find if elements present
|
||||
bool has_elements = false;
|
||||
bool has_attrs_only = pt.data().empty();
|
||||
for (It it = pt.begin(), end = pt.end(); it != end; ++it)
|
||||
{
|
||||
if (it->first != xmlattr<Str>() )
|
||||
{
|
||||
has_attrs_only = false;
|
||||
if (it->first != xmltext<Str>())
|
||||
{
|
||||
has_elements = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write element
|
||||
if (pt.data().empty() && pt.empty()) // Empty key
|
||||
{
|
||||
if (indent >= 0)
|
||||
{
|
||||
write_xml_indent(stream,indent,settings);
|
||||
stream << Ch('<') << key <<
|
||||
Ch('/') << Ch('>');
|
||||
if (want_pretty)
|
||||
stream << Ch('\n');
|
||||
}
|
||||
}
|
||||
else // Nonempty key
|
||||
{
|
||||
// Write opening tag, attributes and data
|
||||
if (indent >= 0)
|
||||
{
|
||||
// Write opening brace and key
|
||||
write_xml_indent(stream,indent,settings);
|
||||
stream << Ch('<') << key;
|
||||
|
||||
// Write attributes
|
||||
if (optional<const Ptree &> attribs = pt.get_child_optional(xmlattr<Str>()))
|
||||
for (It it = attribs.get().begin(); it != attribs.get().end(); ++it)
|
||||
stream << Ch(' ') << it->first << Ch('=')
|
||||
<< Ch('"')
|
||||
<< encode_char_entities(
|
||||
it->second.template get_value<Str>())
|
||||
<< Ch('"');
|
||||
|
||||
if ( has_attrs_only )
|
||||
{
|
||||
// Write closing brace
|
||||
stream << Ch('/') << Ch('>');
|
||||
if (want_pretty)
|
||||
stream << Ch('\n');
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write closing brace
|
||||
stream << Ch('>');
|
||||
|
||||
// Break line if needed and if we want pretty-printing
|
||||
if (has_elements && want_pretty)
|
||||
stream << Ch('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// Write data text, if present
|
||||
if (!pt.data().empty())
|
||||
write_xml_text(stream,
|
||||
pt.template get_value<Str>(),
|
||||
indent + 1, has_elements && want_pretty, settings);
|
||||
|
||||
// Write elements, comments and texts
|
||||
for (It it = pt.begin(); it != pt.end(); ++it)
|
||||
{
|
||||
if (it->first == xmlattr<Str>())
|
||||
continue;
|
||||
else if (it->first == xmlcomment<Str>())
|
||||
write_xml_comment(stream,
|
||||
it->second.template get_value<Str>(),
|
||||
indent + 1, want_pretty, settings);
|
||||
else if (it->first == xmltext<Str>())
|
||||
write_xml_text(stream,
|
||||
it->second.template get_value<Str>(),
|
||||
indent + 1, has_elements && want_pretty, settings);
|
||||
else
|
||||
write_xml_element(stream, it->first, it->second,
|
||||
indent + 1, settings);
|
||||
}
|
||||
|
||||
// Write closing tag
|
||||
if (indent >= 0 && !has_attrs_only)
|
||||
{
|
||||
if (has_elements)
|
||||
write_xml_indent(stream,indent,settings);
|
||||
stream << Ch('<') << Ch('/') << key << Ch('>');
|
||||
if (want_pretty)
|
||||
stream << Ch('\n');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template<class Ptree>
|
||||
void write_xml_internal(std::basic_ostream<typename Ptree::key_type::value_type> &stream,
|
||||
const Ptree &pt,
|
||||
const std::string &filename,
|
||||
const xml_writer_settings<typename Ptree::key_type> & settings)
|
||||
{
|
||||
typedef typename Ptree::key_type Str;
|
||||
stream << detail::widen<Str>("<?xml version=\"1.0\" encoding=\"")
|
||||
<< settings.encoding
|
||||
<< detail::widen<Str>("\"?>\n");
|
||||
write_xml_element(stream, Str(), pt, -1, settings);
|
||||
if (!stream)
|
||||
BOOST_PROPERTY_TREE_THROW(xml_parser_error("write error", filename, 0));
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Copyright (C) 2002-2007 Marcin Kalicinski
|
||||
// Copyright (C) 2007 Alexey Baskakov
|
||||
//
|
||||
// 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
|
||||
// ----------------------------------------------------------------------------
|
||||
#ifndef BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_WRITER_SETTINGS_HPP_INCLUDED
|
||||
#define BOOST_PROPERTY_TREE_DETAIL_XML_PARSER_WRITER_SETTINGS_HPP_INCLUDED
|
||||
|
||||
#include <string>
|
||||
#include <boost/property_tree/detail/ptree_utils.hpp>
|
||||
|
||||
namespace boost { namespace property_tree { namespace xml_parser
|
||||
{
|
||||
|
||||
// Naively convert narrow string to another character type
|
||||
template<class Str>
|
||||
Str widen(const char *text)
|
||||
{
|
||||
typedef typename Str::value_type Ch;
|
||||
Str result;
|
||||
while (*text)
|
||||
{
|
||||
result += Ch(*text);
|
||||
++text;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Xml writer settings. The default settings lead to no pretty printing.
|
||||
template<class Str>
|
||||
class xml_writer_settings
|
||||
{
|
||||
typedef typename Str::value_type Ch;
|
||||
public:
|
||||
xml_writer_settings(Ch inchar = Ch(' '),
|
||||
typename Str::size_type incount = 0,
|
||||
const Str &enc = widen<Str>("utf-8"))
|
||||
: indent_char(inchar)
|
||||
, indent_count(incount)
|
||||
, encoding(enc)
|
||||
{
|
||||
}
|
||||
|
||||
Ch indent_char;
|
||||
typename Str::size_type indent_count;
|
||||
Str encoding;
|
||||
};
|
||||
|
||||
template <class Str>
|
||||
xml_writer_settings<Str> xml_writer_make_settings(typename Str::value_type indent_char = (typename Str::value_type)(' '),
|
||||
typename Str::size_type indent_count = 0,
|
||||
const Str &encoding = widen<Str>("utf-8"))
|
||||
{
|
||||
return xml_writer_settings<Str>(indent_char, indent_count, encoding);
|
||||
}
|
||||
|
||||
} } }
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user