Commit f2e6fc68 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

* fix expat error reporting, and reorder element start check for better average performace.


git-svn-id: https://svn.forked.de/graph-tool/trunk@76 d4600afd-f417-0410-95de-beed9576f240
parent dd8d12ea
...@@ -62,26 +62,28 @@ public: ...@@ -62,26 +62,28 @@ public:
void run(std::istream& in) void run(std::istream& in)
{ {
const int buffer_size = 4096; const int buffer_size = 4096;
XML_Parser parser = XML_ParserCreateNS(0,'|'); m_parser = XML_ParserCreateNS(0,'|');
XML_SetElementHandler(parser, &on_start_element, &on_end_element); XML_SetElementHandler(m_parser, &on_start_element, &on_end_element);
XML_SetCharacterDataHandler(parser, &on_character_data); XML_SetCharacterDataHandler(m_parser, &on_character_data);
XML_SetUserData(parser, this); XML_SetUserData(m_parser, this);
char buffer[buffer_size]; char buffer[buffer_size];
int retval;
do do
{ {
in.read(buffer, buffer_size); in.read(buffer, buffer_size);
retval = XML_Parse(m_parser, buffer, in.gcount(), in.gcount() == 0);
} }
while (XML_Parse(parser, buffer, in.gcount(), in.gcount() == 0) && in.good()); while (retval && in.good());
if (in.good()) if (retval == 0)
{ {
std::stringstream s; std::stringstream s;
s << "Parse error: " << XML_ErrorString(XML_GetErrorCode(parser)) s << "on line " << XML_GetCurrentLineNumber(m_parser)
<< " on line " << XML_GetCurrentLineNumber(parser) <<", column " << XML_GetCurrentColumnNumber(m_parser)
<<", column " << XML_GetCurrentColumnNumber(parser); << ": " << XML_ErrorString(XML_GetErrorCode(m_parser));
throw parse_error(s.str()); throw parse_error(s.str());
} }
XML_ParserFree(parser); XML_ParserFree(m_parser);
} }
private: private:
...@@ -104,43 +106,35 @@ private: ...@@ -104,43 +106,35 @@ private:
std::string name(c_name); std::string name(c_name);
replace_first(name, "http://graphml.graphdrawing.org/xmlns|", ""); replace_first(name, "http://graphml.graphdrawing.org/xmlns|", "");
if (name == "key") if (name == "edge")
{ {
std::string id; std::string id;
std::string key_name; std::string source, target;
std::string key_type;
key_kind kind = all_key;
while (*atts) while (*atts)
{ {
std::string name = *atts++; std::string name = *atts++;
std::string value = *atts++; std::string value = *atts++;
if (name == "id") id = value; if (name == "id") id = value;
else if (name == "attr.name") key_name = value; else if (name == "source") source = value;
else if (name == "attr.type") key_type = value; else if (name == "target") target = value;
else if (name == "for") else if (name == "directed")
{ {
if (value == "graph") kind = graph_key; bool edge_is_directed = (value == "directed");
else if (value == "node") kind = node_key; if (edge_is_directed != self->m_g.is_directed())
else if (value == "edge") kind = edge_key;
else if (value == "hyperedge") kind = hyperedge_key;
else if (value == "port") kind = port_key;
else if (value == "endpoint") kind = endpoint_key;
else if (value == "all") kind = all_key;
else
{ {
throw parse_error("unrecognized key kind '" + value + "'"); if (edge_is_directed)
throw directed_graph_error();
else
throw undirected_graph_error();
} }
} }
} }
self->m_keys[id] = kind; self->m_active_descriptor = self->m_edge.size();
self->m_key_name[id] = key_name; self->handle_edge(source, target);
self->m_key_type[id] = key_type; }
self->m_active_key = id;
}
else if (name == "node") else if (name == "node")
{ {
std::string id; std::string id;
...@@ -156,33 +150,55 @@ private: ...@@ -156,33 +150,55 @@ private:
self->handle_vertex(id); self->handle_vertex(id);
self->m_active_descriptor = id; self->m_active_descriptor = id;
} }
else if (name == "edge") else if (name == "data")
{
while (*atts)
{
std::string name = *atts++;
std::string value = *atts++;
if (name == "key") self->m_active_key = value;
}
}
else if (name == "key")
{ {
std::string id; std::string id;
std::string source, target; std::string key_name;
std::string key_type;
key_kind kind = all_key;
while (*atts) while (*atts)
{ {
std::string name = *atts++; std::string name = *atts++;
std::string value = *atts++; std::string value = *atts++;
if (name == "id") id = value; if (name == "id") id = value;
else if (name == "source") source = value; else if (name == "attr.name") key_name = value;
else if (name == "target") target = value; else if (name == "attr.type") key_type = value;
else if (name == "directed") else if (name == "for")
{ {
bool edge_is_directed = (value == "directed"); if (value == "graph") kind = graph_key;
if (edge_is_directed != self->m_g.is_directed()) else if (value == "node") kind = node_key;
else if (value == "edge") kind = edge_key;
else if (value == "hyperedge") kind = hyperedge_key;
else if (value == "port") kind = port_key;
else if (value == "endpoint") kind = endpoint_key;
else if (value == "all") kind = all_key;
else
{ {
if (edge_is_directed) std::stringstream s;
throw directed_graph_error(); s << "on line " << XML_GetCurrentLineNumber(self->m_parser)
else << ", column " << XML_GetCurrentColumnNumber(self->m_parser)
throw undirected_graph_error(); << ": unrecognized key kind '" << value << "'";
throw parse_error(s.str());
} }
} }
} }
self->m_active_descriptor = self->m_edge.size(); self->m_keys[id] = kind;
self->handle_edge(source, target); self->m_key_name[id] = key_name;
self->m_key_type[id] = key_type;
self->m_active_key = id;
} }
else if (name == "graph") else if (name == "graph")
{ {
...@@ -209,16 +225,6 @@ private: ...@@ -209,16 +225,6 @@ private:
} }
self->m_active_descriptor = ""; self->m_active_descriptor = "";
} }
else if (name == "data")
{
while (*atts)
{
std::string name = *atts++;
std::string value = *atts++;
if (name == "key") self->m_active_key = value;
}
}
self->m_character_data.clear(); self->m_character_data.clear();
} }
...@@ -265,7 +271,11 @@ private: ...@@ -265,7 +271,11 @@ private:
} }
catch (bad_lexical_cast) catch (bad_lexical_cast)
{ {
throw parse_error("invalid vertex: " + v); std::stringstream s;
s << "on line " << XML_GetCurrentLineNumber(m_parser)
<< ", column " << XML_GetCurrentColumnNumber(m_parser)
<< ": invalid vertex: " << v;
throw parse_error(s.str());
} }
while(id >= m_canonical_vertex.size()) while(id >= m_canonical_vertex.size())
...@@ -338,16 +348,27 @@ private: ...@@ -338,16 +348,27 @@ private:
void handle_property(const std::string& key_id, const variant<std::string,size_t>& descriptor, const std::string& value) void handle_property(const std::string& key_id, const variant<std::string,size_t>& descriptor, const std::string& value)
{ {
if (get<std::string>(&descriptor)) try
{ {
if (get<std::string>(descriptor) == "") if (get<std::string>(&descriptor))
m_g.set_graph_property(m_key_name[key_id], value, m_key_type[key_id]); {
if (get<std::string>(descriptor) == "")
m_g.set_graph_property(m_key_name[key_id], value, m_key_type[key_id]);
else
m_g.set_vertex_property(m_key_name[key_id], get_vertex_descriptor(get<std::string>(descriptor)), value, m_key_type[key_id]);
}
else else
m_g.set_vertex_property(m_key_name[key_id], get_vertex_descriptor(get<std::string>(descriptor)), value, m_key_type[key_id]); {
m_g.set_edge_property(m_key_name[key_id], get_edge_descriptor(get<size_t>(descriptor)), value, m_key_type[key_id]);
}
} }
else catch (parse_error &e)
{ {
m_g.set_edge_property(m_key_name[key_id], get_edge_descriptor(get<size_t>(descriptor)), value, m_key_type[key_id]); std::stringstream s;
s << "on line " << XML_GetCurrentLineNumber(m_parser)
<< ", column " << XML_GetCurrentColumnNumber(m_parser)
<< ": " << e.error;
throw parse_error(s.str());
} }
} }
...@@ -370,6 +391,7 @@ private: ...@@ -370,6 +391,7 @@ private:
std::string m_character_data; std::string m_character_data;
bool m_canonical_vertices; bool m_canonical_vertices;
bool m_canonical_edges; bool m_canonical_edges;
XML_Parser m_parser;
}; };
namespace boost namespace boost
......
...@@ -70,10 +70,11 @@ namespace boost ...@@ -70,10 +70,11 @@ namespace boost
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
struct parse_error: public graph_exception struct parse_error: public graph_exception
{ {
parse_error(const std::string& error) {statement = "parse error: " + error;} parse_error(const std::string& err) {error = err; statement = "parse error: " + error;}
virtual ~parse_error() throw() {} virtual ~parse_error() throw() {}
virtual const char* what() const throw() {return statement.c_str();} virtual const char* what() const throw() {return statement.c_str();}
std::string statement; std::string statement;
std::string error;
}; };
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment