refactor xml parser, uses faster string to double conversion

This commit is contained in:
Dennis Luxen 2014-04-29 15:33:13 +02:00
parent b7704f0c7f
commit a1ecab2f95
3 changed files with 318 additions and 229 deletions

View File

@ -42,249 +42,307 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <boost/ref.hpp> #include <boost/ref.hpp>
XMLParser::XMLParser(const char * filename, ExtractorCallbacks* ec, ScriptingEnvironment& se) : BaseParser(ec, se) { XMLParser::XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se)
inputReader = inputReaderFactory(filename); : BaseParser(ec, se)
{
inputReader = inputReaderFactory(filename);
} }
bool XMLParser::ReadHeader() { bool XMLParser::ReadHeader() { return (xmlTextReaderRead(inputReader) == 1); }
return (xmlTextReaderRead( inputReader ) == 1); bool XMLParser::Parse()
} {
bool XMLParser::Parse() { while (xmlTextReaderRead(inputReader) == 1)
while ( xmlTextReaderRead( inputReader ) == 1 ) { {
const int type = xmlTextReaderNodeType( inputReader ); const int type = xmlTextReaderNodeType(inputReader);
//1 is Element // 1 is Element
if ( type != 1 ) { if (type != 1)
continue; {
} continue;
}
xmlChar* currentName = xmlTextReaderName( inputReader ); xmlChar *currentName = xmlTextReaderName(inputReader);
if ( currentName == NULL ) { if (currentName == NULL)
continue; {
} continue;
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "node" ) == 1 ) { if (xmlStrEqual(currentName, (const xmlChar *)"node") == 1)
ImportNode n = _ReadXMLNode(); {
ParseNodeInLua( n, lua_state ); ImportNode n = ReadXMLNode();
extractor_callbacks->nodeFunction(n); ParseNodeInLua(n, lua_state);
// if(!extractor_callbacks->nodeFunction(n)) extractor_callbacks->nodeFunction(n);
// std::cerr << "[XMLParser] dense node not parsed" << std::endl; }
}
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { if (xmlStrEqual(currentName, (const xmlChar *)"way") == 1)
ExtractionWay way = _ReadXMLWay( ); {
ParseWayInLua( way, lua_state ); ExtractionWay way = ReadXMLWay();
extractor_callbacks->wayFunction(way); ParseWayInLua(way, lua_state);
// if(!extractor_callbacks->wayFunction(way)) extractor_callbacks->wayFunction(way);
// std::cerr << "[PBFParser] way not parsed" << std::endl; }
} if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
if( use_turn_restrictions ) { {
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { InputRestrictionContainer r = ReadXMLRestriction();
InputRestrictionContainer r = _ReadXMLRestriction(); if ((UINT_MAX != r.fromWay) && !extractor_callbacks->restrictionFunction(r))
if(r.fromWay != UINT_MAX) { {
if(!extractor_callbacks->restrictionFunction(r)) { std::cerr << "[XMLParser] restriction not parsed" << std::endl;
std::cerr << "[XMLParser] restriction not parsed" << std::endl; }
} }
} xmlFree(currentName);
} }
} return true;
xmlFree( currentName );
}
return true;
} }
InputRestrictionContainer XMLParser::_ReadXMLRestriction() { InputRestrictionContainer XMLParser::ReadXMLRestriction()
{
InputRestrictionContainer restriction; InputRestrictionContainer restriction;
std::string except_tag_string; std::string except_tag_string;
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { if (xmlTextReaderIsEmptyElement(inputReader) != 1)
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { {
const int childType = xmlTextReaderNodeType( inputReader ); const int depth = xmlTextReaderDepth(inputReader);
if ( childType != 1 && childType != 15 ) { while (xmlTextReaderRead(inputReader) == 1)
continue; {
} const int childType = xmlTextReaderNodeType(inputReader);
const int childDepth = xmlTextReaderDepth( inputReader ); if (childType != 1 && childType != 15)
xmlChar* childName = xmlTextReaderName( inputReader ); {
if ( childName == NULL ) { continue;
continue; }
} const int childDepth = xmlTextReaderDepth(inputReader);
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) { xmlChar *childName = xmlTextReaderName(inputReader);
xmlFree( childName ); if (childName == NULL)
break; {
} continue;
if ( childType != 1 ) { }
xmlFree( childName ); if (depth == childDepth && childType == 15 &&
continue; xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
} {
xmlFree(childName);
break;
}
if (childType != 1)
{
xmlFree(childName);
continue;
}
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); {
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
if ( k != NULL && value != NULL ) { xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){ if (k != NULL && value != NULL)
if(0 == std::string((const char *) value).find("only_")) { {
restriction.restriction.flags.isOnly = true; if (xmlStrEqual(k, (const xmlChar *)"restriction") &&
} (0 == std::string((const char *)value).find("only_")))
} {
if ( xmlStrEqual(k, (const xmlChar *) "except") ) { restriction.restriction.flags.isOnly = true;
except_tag_string = (const char*) value; }
} if (xmlStrEqual(k, (const xmlChar *)"except"))
} {
except_tag_string = (const char *)value;
}
}
if ( k != NULL ) { if (k != NULL)
xmlFree( k ); {
} xmlFree(k);
if ( value != NULL ) { }
xmlFree( value ); if (value != NULL)
} {
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) { xmlFree(value);
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); }
if ( ref != NULL ) { }
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" ); else if (xmlStrEqual(childName, (const xmlChar *)"member") == 1)
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" ); {
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
if (ref != NULL)
{
xmlChar *role = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"role");
xmlChar *type = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"type");
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) { if (xmlStrEqual(role, (const xmlChar *)"to") &&
restriction.toWay = stringToUint((const char*) ref); xmlStrEqual(type, (const xmlChar *)"way"))
} {
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) { restriction.toWay = stringToUint((const char *)ref);
restriction.fromWay = stringToUint((const char*) ref); }
} if (xmlStrEqual(role, (const xmlChar *)"from") &&
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) { xmlStrEqual(type, (const xmlChar *)"way"))
restriction.restriction.viaNode = stringToUint((const char*) ref); {
} restriction.fromWay = stringToUint((const char *)ref);
}
if (xmlStrEqual(role, (const xmlChar *)"via") &&
xmlStrEqual(type, (const xmlChar *)"node"))
{
restriction.restriction.viaNode = stringToUint((const char *)ref);
}
if(NULL != type) { if (NULL != type)
xmlFree( type ); {
} xmlFree(type);
if(NULL != role) { }
xmlFree( role ); if (NULL != role)
} {
if(NULL != ref) { xmlFree(role);
xmlFree( ref ); }
} if (NULL != ref)
} {
} xmlFree(ref);
xmlFree( childName ); }
} }
} }
xmlFree(childName);
}
}
if( ShouldIgnoreRestriction(except_tag_string) ) { if (ShouldIgnoreRestriction(except_tag_string))
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction {
} restriction.fromWay = UINT_MAX; // workaround to ignore the restriction
return restriction; }
return restriction;
} }
ExtractionWay XMLParser::_ReadXMLWay() { ExtractionWay XMLParser::ReadXMLWay()
ExtractionWay way; {
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { ExtractionWay way;
const int depth = xmlTextReaderDepth( inputReader ); if (xmlTextReaderIsEmptyElement(inputReader) != 1)
while ( xmlTextReaderRead( inputReader ) == 1 ) { {
const int childType = xmlTextReaderNodeType( inputReader ); const int depth = xmlTextReaderDepth(inputReader);
if ( childType != 1 && childType != 15 ) { while (xmlTextReaderRead(inputReader) == 1)
continue; {
} const int childType = xmlTextReaderNodeType(inputReader);
const int childDepth = xmlTextReaderDepth( inputReader ); if (childType != 1 && childType != 15)
xmlChar* childName = xmlTextReaderName( inputReader ); {
if ( childName == NULL ) { continue;
continue; }
} const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) { if (depth == childDepth && childType == 15 &&
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); xmlStrEqual(childName, (const xmlChar *)"way") == 1)
way.id = stringToUint((char*)id); {
xmlFree(id); xmlChar *id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
xmlFree( childName ); way.id = stringToUint((char *)id);
break; xmlFree(id);
} xmlFree(childName);
if ( childType != 1 ) { break;
xmlFree( childName ); }
continue; if (childType != 1)
} {
xmlFree(childName);
continue;
}
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); {
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
// cout << "->k=" << k << ", v=" << value << endl; xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
if ( k != NULL && value != NULL ) {
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value)); if (k != NULL && value != NULL)
} {
if ( k != NULL ) { way.keyVals.Add(std::string((char *)k), std::string((char *)value));
xmlFree( k ); }
} if (k != NULL)
if ( value != NULL ) { {
xmlFree( value ); xmlFree(k);
} }
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) { if (value != NULL)
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); {
if ( ref != NULL ) { xmlFree(value);
way.path.push_back( stringToUint(( const char* ) ref ) ); }
xmlFree( ref ); }
} else if (xmlStrEqual(childName, (const xmlChar *)"nd") == 1)
} {
xmlFree( childName ); xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
} if (ref != NULL)
} {
return way; way.path.push_back(stringToUint((const char *)ref));
xmlFree(ref);
}
}
xmlFree(childName);
}
}
return way;
} }
ImportNode XMLParser::_ReadXMLNode() { ImportNode XMLParser::ReadXMLNode()
ImportNode node; {
ImportNode node;
xmlChar* attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lat" ); xmlChar *attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lat");
if ( attribute != NULL ) { if (attribute != NULL)
node.lat = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute ) ); {
xmlFree( attribute ); node.lat = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
} xmlFree(attribute);
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "lon" ); }
if ( attribute != NULL ) { attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute )); if (attribute != NULL)
xmlFree( attribute ); {
} node.lon = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); xmlFree(attribute);
if ( attribute != NULL ) { }
node.id = stringToUint(( const char* ) attribute ); attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
xmlFree( attribute ); if (attribute != NULL)
} {
node.id = stringToUint((const char *)attribute);
xmlFree(attribute);
}
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { if (xmlTextReaderIsEmptyElement(inputReader) != 1)
const int depth = xmlTextReaderDepth( inputReader ); {
while ( xmlTextReaderRead( inputReader ) == 1 ) { const int depth = xmlTextReaderDepth(inputReader);
const int childType = xmlTextReaderNodeType( inputReader ); while (xmlTextReaderRead(inputReader) == 1)
// 1 = Element, 15 = EndElement {
if ( childType != 1 && childType != 15 ) { const int childType = xmlTextReaderNodeType(inputReader);
continue; // 1 = Element, 15 = EndElement
} if (childType != 1 && childType != 15)
const int childDepth = xmlTextReaderDepth( inputReader ); {
xmlChar* childName = xmlTextReaderName( inputReader ); continue;
if ( childName == NULL ) { }
continue; const int childDepth = xmlTextReaderDepth(inputReader);
} xmlChar *childName = xmlTextReaderName(inputReader);
if (childName == NULL)
{
continue;
}
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) { if (depth == childDepth && childType == 15 &&
xmlFree( childName ); xmlStrEqual(childName, (const xmlChar *)"node") == 1)
break; {
} xmlFree(childName);
if ( childType != 1 ) { break;
xmlFree( childName ); }
continue; if (childType != 1)
} {
xmlFree(childName);
continue;
}
if ( xmlStrEqual( childName, ( const xmlChar* ) "tag" ) == 1 ) { if (xmlStrEqual(childName, (const xmlChar *)"tag") == 1)
xmlChar* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" ); {
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); xmlChar *k = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"k");
if ( k != NULL && value != NULL ) { xmlChar *value = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"v");
node.keyVals.emplace(std::string(reinterpret_cast<char*>(k)), std::string(reinterpret_cast<char*>(value))); if (k != NULL && value != NULL)
} {
if ( k != NULL ) { node.keyVals.emplace(std::string((char *)(k)),
xmlFree( k ); std::string((char *)(value)));
} }
if ( value != NULL ) { if (k != NULL)
xmlFree( value ); {
} xmlFree(k);
} }
if (value != NULL)
{
xmlFree(value);
}
}
xmlFree( childName ); xmlFree(childName);
} }
} }
return node; return node;
} }

View File

@ -33,20 +33,17 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <libxml/xmlreader.h> #include <libxml/xmlreader.h>
class XMLParser : public BaseParser { class XMLParser : public BaseParser
public: {
XMLParser( public:
const char* filename, XMLParser(const char *filename, ExtractorCallbacks *ec, ScriptingEnvironment &se);
ExtractorCallbacks * ec,
ScriptingEnvironment & se
);
bool ReadHeader(); bool ReadHeader();
bool Parse(); bool Parse();
private: private:
InputRestrictionContainer _ReadXMLRestriction(); InputRestrictionContainer ReadXMLRestriction();
ExtractionWay _ReadXMLWay(); ExtractionWay ReadXMLWay();
ImportNode _ReadXMLNode(); ImportNode ReadXMLNode();
xmlTextReaderPtr inputReader; xmlTextReaderPtr inputReader;
}; };

View File

@ -126,6 +126,40 @@ static inline uint64_t stringToInt64(const std::string& input) {
return value; return value;
} }
// source: http://tinodidriksen.com/2011/05/28/cpp-convert-string-to-double-speed/
static inline double StringToDouble(const char *p)
{
double r = 0.0;
bool neg = false;
if (*p == '-')
{
neg = true;
++p;
}
while (*p >= '0' && *p <= '9')
{
r = (r*10.0) + (*p - '0');
++p;
}
if (*p == '.')
{
double f = 0.0;
int n = 0;
++p;
while (*p >= '0' && *p <= '9')
{
f = (f*10.0) + (*p - '0');
++p;
++n;
}
r += f / std::pow(10.0, n);
}
if (neg)
{
r = -r;
}
return r;
}
static inline void doubleToString(const double value, std::string & output){ static inline void doubleToString(const double value, std::string & output){
output.clear(); output.clear();