Convert first function to new XML structure.
This commit is contained in:
parent
481271cb76
commit
191d0f907a
4 changed files with 203 additions and 57 deletions
|
@ -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
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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();
|
||||
|
|
137
src/xml_tree.cpp
137
src/xml_tree.cpp
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue