Convert first function to new XML structure.

This commit is contained in:
Hermann Kraus 2012-03-06 15:18:11 +01:00
parent 481271cb76
commit 191d0f907a
4 changed files with 203 additions and 57 deletions

View file

@ -23,16 +23,14 @@
#ifndef MAPNIK_LIBXML2_LOADER_HPP
#define MAPNIK_LIBXML2_LOADER_HPP
// boost
#include <boost/property_tree/ptree.hpp>
// stl
#include <string>
namespace mapnik
{
void read_xml2( std::string const & filename, boost::property_tree::ptree & pt);
void read_xml2_string( std::string const & str, boost::property_tree::ptree & pt, std::string const & base_path="");
class xml_node;
void read_xml2( std::string const & filename, xml_node &node);
void read_xml2_string( std::string const & str, xml_node &node, std::string const & base_path="");
}
#endif // MAPNIK_LIBXML2_LOADER_HPP

View file

@ -23,13 +23,19 @@
#ifndef MAPNIK_XML_TREE_H
#define MAPNIK_XML_TREE_H
//boost
#include <boost/optional.hpp>
//stl
#include <list>
#include <string>
#include <map>
#include <exception>
namespace mapnik
{
class xml_tree;
class color;
class xml_attribute
{
@ -38,6 +44,19 @@ public:
bool processed;
};
class node_not_found: public std::exception
{
public:
node_not_found(std::string node_name) : node_name_(node_name) {}
virtual const char* what() const throw()
{
return ("Node "+node_name_+ "not found").c_str();
}
~node_not_found() throw ();
private:
std::string node_name_;
};
class xml_node
{
public:
@ -49,6 +68,15 @@ public:
xml_node &add_child(std::string name, unsigned line=0, bool text_node = false);
void add_attribute(std::string name, std::string value);
void set_processed(bool processed);
xml_node & get_child(std::string name);
xml_node const& get_child(std::string name) const;
template <typename T>
boost::optional<T> get_opt_attr(std::string const& name) const;
template <typename T>
T get_attr(std::string const& name, T const& default_value) const;
private:
xml_tree &tree_;
std::string name_;
@ -66,7 +94,7 @@ public:
xml_tree();
void set_filename(std::string fn);
std::string filename() const;
xml_node &node();
xml_node &root();
private:
xml_node node_;
std::string file_;

View file

@ -22,6 +22,7 @@
// mapnik
#include <mapnik/load_map.hpp>
#include <mapnik/xml_tree.hpp>
#include <mapnik/version.hpp>
#include <mapnik/image_reader.hpp>
#include <mapnik/color.hpp>
@ -94,7 +95,7 @@ public:
expr_grammar_(tr_)
{}
void parse_map(Map & map, ptree const & sty, std::string const& base_path="");
void parse_map(Map & map, xml_node const& sty, std::string const& base_path="");
private:
void parse_map_include( Map & map, ptree const & include);
void parse_style(Map & map, ptree const & sty);
@ -166,9 +167,10 @@ void remove_empty_text_nodes(ptree &pt)
//#include <mapnik/internal/dump_xml.hpp>
void load_map(Map & map, std::string const& filename, bool strict)
{
ptree pt;
xml_tree tree;
tree.set_filename(filename);
#ifdef HAVE_LIBXML2
read_xml2(filename, pt);
read_xml2(filename, tree.root());
#else
try
{
@ -180,18 +182,18 @@ void load_map(Map & map, std::string const& filename, bool strict)
throw config_error( ex.what() );
}
#endif
map_parser parser( strict, filename);
parser.parse_map(map, pt);
map_parser parser(strict, filename);
// parser.parse_map(map, pt);
}
void load_map_string(Map & map, std::string const& str, bool strict, std::string const& base_path)
{
ptree pt;
xml_tree tree;
#ifdef HAVE_LIBXML2
if (!base_path.empty())
read_xml2_string(str, pt, base_path); // accept base_path passed into function
read_xml2_string(str, tree.root(), base_path); // accept base_path passed into function
else
read_xml2_string(str, pt, map.base_path()); // default to map base_path
read_xml2_string(str, tree.root(), map.base_path()); // default to map base_path
#else
try
{
@ -206,8 +208,8 @@ void load_map_string(Map & map, std::string const& str, bool strict, std::string
}
#endif
map_parser parser( strict, base_path);
parser.parse_map(map, pt, base_path);
map_parser parser(strict, base_path);
// parser.parse_map(map, tree.root(), base_path);
}
expression_ptr map_parser::parse_expr(std::string const& str)
@ -244,44 +246,31 @@ boost::optional<color> map_parser::get_opt_color_attr(boost::property_tree::ptre
return result;
}
void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base_path )
void map_parser::parse_map(Map & map, xml_node const& pt, std::string const& base_path)
{
try
{
ptree const & map_node = pt.get_child("Map");
std::ostringstream s("");
s << "background-color,"
<< "background-image,"
<< "srs,"
<< "buffer-size,"
<< "paths-from-xml,"
<< "minimum-version,"
<< "font-directory,"
<< "maximum-extent,"
<< "base";
ensure_attrs(map_node, "Map", s.str());
xml_node const& map_node = pt.get_child("Map");
try
{
parameters extra_attr;
// Check if relative paths should be interpreted as relative to/from XML location
// Default is true, and map_parser::ensure_relative_to_xml will be called to modify path
optional<boolean> paths_from_xml = get_opt_attr<boolean>(map_node, "paths-from-xml");
optional<boolean> paths_from_xml = map_node.get_opt_attr<boolean>("paths-from-xml");
if (paths_from_xml)
{
relative_to_xml_ = *paths_from_xml;
}
optional<std::string> base_path_from_xml = get_opt_attr<std::string>(map_node, "base");
optional<std::string> base_path_from_xml = map_node.get_opt_attr<std::string>("base");
if (!base_path.empty())
{
map.set_base_path( base_path );
map.set_base_path(base_path);
}
else if (base_path_from_xml)
{
map.set_base_path( *base_path_from_xml );
map.set_base_path(*base_path_from_xml);
}
else
{
@ -293,30 +282,30 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base
std::string base = xml_path.branch_path().string();
#endif
map.set_base_path( base );
map.set_base_path(base);
}
optional<color> bgcolor = get_opt_color_attr(map_node, "background-color");
optional<color> bgcolor = map_node.get_opt_attr<color>("background-color");
if (bgcolor)
{
map.set_background( * bgcolor );
map.set_background(*bgcolor);
}
optional<std::string> image_filename = get_opt_attr<std::string>(map_node, "background-image");
optional<std::string> image_filename = map_node.get_opt_attr<std::string>("background-image");
if (image_filename)
{
map.set_background_image(ensure_relative_to_xml(image_filename));
}
map.set_srs( get_attr(map_node, "srs", map.srs() ));
map.set_srs(map_node.get_attr("srs", map.srs()));
optional<unsigned> buffer_size = get_opt_attr<unsigned>(map_node,"buffer-size");
optional<unsigned> buffer_size = map_node.get_opt_attr<unsigned>("buffer-size");
if (buffer_size)
{
map.set_buffer_size(*buffer_size);
}
optional<std::string> maximum_extent = get_opt_attr<std::string>(map_node,"maximum-extent");
optional<std::string> maximum_extent = map_node.get_opt_attr<std::string>("maximum-extent");
if (maximum_extent)
{
box2d<double> box;
@ -327,33 +316,33 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base
else
{
std::ostringstream s_err;
s << "failed to parse 'maximum-extent'";
if ( strict_ )
s_err << "failed to parse 'maximum-extent'";
if (strict_)
throw config_error(s_err.str());
else
std::clog << "### WARNING: " << s.str() << std::endl;
std::clog << "### WARNING: " << s_err.str() << std::endl;
}
}
optional<std::string> font_directory = get_opt_attr<std::string>(map_node,"font-directory");
optional<std::string> font_directory = map_node.get_opt_attr<std::string>("font-directory");
if (font_directory)
{
extra_attr["font-directory"] = *font_directory;
freetype_engine::register_fonts( ensure_relative_to_xml(font_directory), false);
freetype_engine::register_fonts(ensure_relative_to_xml(font_directory), false);
}
optional<std::string> min_version_string = get_opt_attr<std::string>(map_node, "minimum-version");
optional<std::string> min_version_string = map_node.get_opt_attr<std::string>("minimum-version");
if (min_version_string)
{
extra_attr["minimum-version"] = *min_version_string;
boost::char_separator<char> sep(".");
boost::tokenizer<boost::char_separator<char> > tokens(*min_version_string,sep);
boost::tokenizer<boost::char_separator<char> > tokens(*min_version_string, sep);
unsigned i = 0;
bool success = false;
int n[3];
for (boost::tokenizer<boost::char_separator<char> >::iterator beg=tokens.begin();
beg!=tokens.end();++beg)
for (boost::tokenizer<boost::char_separator<char> >::iterator beg = tokens.begin();
beg != tokens.end(); ++beg)
{
try
{
@ -391,15 +380,15 @@ void map_parser::parse_map( Map & map, ptree const & pt, std::string const& base
throw;
}
parse_map_include( map, map_node );
// parse_map_include( map, map_node );
}
catch (const boost::property_tree::ptree_bad_path &)
catch (node_not_found const&)
{
throw config_error("Not a map file. Node 'Map' not found.");
}
}
void map_parser::parse_map_include( Map & map, ptree const & include )
void map_parser::parse_map_include(Map & map, xml_node const& include )
{
ptree::const_iterator itr = include.begin();
ptree::const_iterator end = include.end();

View file

@ -19,11 +19,112 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
*****************************************************************************/
//mapnik
#include <mapnik/xml_tree.hpp>
#include <mapnik/util/conversions.hpp>
#include <mapnik/enumeration.hpp>
//boost
#include <boost/lexical_cast.hpp>
namespace mapnik
{
template <typename T>
inline boost::optional<T> fast_cast(xml_tree const& tree, std::string const& value)
{
return boost::lexical_cast<T>(value);
}
template <>
inline boost::optional<int> fast_cast(xml_tree const& tree, std::string const& value)
{
int result;
if (mapnik::conversions::string2int(value, result))
return boost::optional<int>(result);
return boost::optional<int>();
}
template <>
inline boost::optional<double> fast_cast(xml_tree const& tree, std::string const& value)
{
double result;
if (mapnik::conversions::string2double(value, result))
return boost::optional<double>(result);
return boost::optional<double>();
}
template <>
inline boost::optional<float> fast_cast(xml_tree const& tree, std::string const& value)
{
float result;
if (mapnik::conversions::string2float(value, result))
return boost::optional<float>(result);
return boost::optional<float>();
}
template <>
inline boost::optional<std::string> fast_cast(xml_tree const& tree, std::string const& value)
{
return value;
}
/****************************************************************************/
class boolean;
template <typename T>
struct name_trait
{
static std::string name()
{
return "<unknown>";
}
// missing name_trait for type ...
// if you get here you are probably using a new type
// in the XML file. Just add a name trait for the new
// type below.
BOOST_STATIC_ASSERT( sizeof(T) == 0 );
};
#define DEFINE_NAME_TRAIT( type, type_name ) \
template <> \
struct name_trait<type> \
{ \
static std::string name() { return std::string("type ") + type_name; } \
};
DEFINE_NAME_TRAIT( double, "double")
DEFINE_NAME_TRAIT( float, "float")
DEFINE_NAME_TRAIT( unsigned, "unsigned")
DEFINE_NAME_TRAIT( boolean, "boolean")
DEFINE_NAME_TRAIT( int, "integer" )
DEFINE_NAME_TRAIT( std::string, "string" )
DEFINE_NAME_TRAIT( color, "color" )
template <typename ENUM, int MAX>
struct name_trait< mapnik::enumeration<ENUM, MAX> >
{
typedef enumeration<ENUM, MAX> Enum;
static std::string name()
{
std::string value_list("one of [");
for (unsigned i = 0; i < Enum::MAX; ++i)
{
value_list += Enum::get_string( i );
if ( i + 1 < Enum::MAX ) value_list += ", ";
}
value_list += "]";
return value_list;
}
};
/****************************************************************************/
xml_tree::xml_tree()
: node_(*this, "<root>")
{
@ -39,7 +140,7 @@ std::string xml_tree::filename() const
return file_;
}
xml_node &xml_tree::node()
xml_node &xml_tree::root()
{
return node_;
}
@ -61,7 +162,7 @@ std::string xml_node::name() const
if (!text_node_)
return name_;
else
return "<xmltext>";
return "<xmltext>"; //TODO: throw
}
std::string xml_node::text() const
@ -69,7 +170,7 @@ std::string xml_node::text() const
if (text_node_)
return name_;
else
return "NOT A TEXT NODE";
return "NOT A TEXT NODE"; //TODO: throw
}
void xml_node::set_processed(bool processed)
@ -83,5 +184,35 @@ xml_node &xml_node::add_child(std::string name, unsigned line, bool text_node)
return children_.back();
}
xml_node & xml_node::get_child(std::string name)
{
std::list<xml_node>::iterator itr = children_.begin();
std::list<xml_node>::iterator end = children_.end();
for (; itr != end; itr++)
{
if (!(itr->text_node_) && itr->name_ == name)
{
itr->set_processed(true);
return *itr;
}
}
throw node_not_found(name);
}
template <typename T>
boost::optional<T> xml_node::get_opt_attr(std::string const& name) const
{
std::map<std::string, xml_attribute>::const_iterator itr = attributes_.find(name);
if (itr == attributes_.end()) return boost::optional<T>();
boost::optional<T> result = fast_cast<T>(itr->second);
if (!result)
{
throw config_error(std::string("Failed to parse attribute '") +
name + "'. Expected " + name_trait<T>::name() +
" but got '" + itr->second + "'");
}
return result;
}
} //ns mapnik