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,248 +42,306 @@ 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)
: BaseParser(ec, se)
{
inputReader = inputReaderFactory(filename); 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();
ParseNodeInLua(n, lua_state);
extractor_callbacks->nodeFunction(n); extractor_callbacks->nodeFunction(n);
// if(!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();
ParseWayInLua(way, lua_state);
extractor_callbacks->wayFunction(way); extractor_callbacks->wayFunction(way);
// if(!extractor_callbacks->wayFunction(way))
// std::cerr << "[PBFParser] way not parsed" << std::endl;
} }
if( use_turn_restrictions ) { if (use_turn_restrictions && xmlStrEqual(currentName, (const xmlChar *)"relation") == 1)
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { {
InputRestrictionContainer r = _ReadXMLRestriction(); InputRestrictionContainer r = ReadXMLRestriction();
if(r.fromWay != UINT_MAX) { if ((UINT_MAX != r.fromWay) && !extractor_callbacks->restrictionFunction(r))
if(!extractor_callbacks->restrictionFunction(r)) { {
std::cerr << "[XMLParser] restriction not parsed" << std::endl; std::cerr << "[XMLParser] restriction not parsed" << std::endl;
} }
} }
} xmlFree(currentName);
}
xmlFree( currentName );
} }
return true; 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)
{
const int childType = xmlTextReaderNodeType(inputReader);
if (childType != 1 && childType != 15)
{
continue; continue;
} }
const int childDepth = xmlTextReaderDepth( inputReader ); const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar* childName = xmlTextReaderName( inputReader ); xmlChar *childName = xmlTextReaderName(inputReader);
if ( childName == NULL ) { if (childName == NULL)
{
continue; continue;
} }
if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) { if (depth == childDepth && childType == 15 &&
xmlFree( childName ); xmlStrEqual(childName, (const xmlChar *)"relation") == 1)
{
xmlFree(childName);
break; break;
} }
if ( childType != 1 ) { if (childType != 1)
xmlFree( childName ); {
xmlFree(childName);
continue; 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_")) { {
if (xmlStrEqual(k, (const xmlChar *)"restriction") &&
(0 == std::string((const char *)value).find("only_")))
{
restriction.restriction.flags.isOnly = true; restriction.restriction.flags.isOnly = true;
} }
} if (xmlStrEqual(k, (const xmlChar *)"except"))
if ( xmlStrEqual(k, (const xmlChar *) "except") ) { {
except_tag_string = (const char*) value; except_tag_string = (const char *)value;
} }
} }
if ( k != NULL ) { if (k != NULL)
xmlFree( k ); {
xmlFree(k);
} }
if ( value != NULL ) { if (value != NULL)
xmlFree( value ); {
xmlFree(value);
} }
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) { }
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); else if (xmlStrEqual(childName, (const xmlChar *)"member") == 1)
if ( ref != NULL ) { {
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" ); xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" ); 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"))
{
restriction.toWay = stringToUint((const char *)ref);
} }
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) { if (xmlStrEqual(role, (const xmlChar *)"from") &&
restriction.fromWay = stringToUint((const char*) ref); xmlStrEqual(type, (const xmlChar *)"way"))
{
restriction.fromWay = stringToUint((const char *)ref);
} }
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) { if (xmlStrEqual(role, (const xmlChar *)"via") &&
restriction.restriction.viaNode = stringToUint((const char*) ref); 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) { if (NULL != role)
xmlFree( role ); {
xmlFree(role);
} }
if(NULL != ref) { if (NULL != ref)
xmlFree( 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; ExtractionWay way;
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)
if ( childType != 1 && childType != 15 ) { {
const int childType = xmlTextReaderNodeType(inputReader);
if (childType != 1 && childType != 15)
{
continue; continue;
} }
const int childDepth = xmlTextReaderDepth( inputReader ); const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar* childName = xmlTextReaderName( inputReader ); xmlChar *childName = xmlTextReaderName(inputReader);
if ( childName == NULL ) { if (childName == NULL)
{
continue; 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); {
xmlChar *id = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
way.id = stringToUint((char *)id);
xmlFree(id); xmlFree(id);
xmlFree( childName ); xmlFree(childName);
break; break;
} }
if ( childType != 1 ) { if (childType != 1)
xmlFree( childName ); {
xmlFree(childName);
continue; 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)
{
way.keyVals.Add(std::string((char *)k), std::string((char *)value));
} }
if ( k != NULL ) { if (k != NULL)
xmlFree( k ); {
xmlFree(k);
} }
if ( value != NULL ) { if (value != NULL)
xmlFree( value ); {
} xmlFree(value);
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
if ( ref != NULL ) {
way.path.push_back( stringToUint(( const char* ) ref ) );
xmlFree( ref );
} }
} }
xmlFree( childName ); else if (xmlStrEqual(childName, (const xmlChar *)"nd") == 1)
{
xmlChar *ref = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"ref");
if (ref != NULL)
{
way.path.push_back(stringToUint((const char *)ref));
xmlFree(ref);
}
}
xmlFree(childName);
} }
} }
return way; 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" ); attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"lon");
if ( attribute != NULL ) { if (attribute != NULL)
node.lon = static_cast<NodeID>(COORDINATE_PRECISION*atof(( const char* ) attribute )); {
xmlFree( attribute ); node.lon = COORDINATE_PRECISION * StringToDouble((const char *)attribute);
xmlFree(attribute);
} }
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); attribute = xmlTextReaderGetAttribute(inputReader, (const xmlChar *)"id");
if ( attribute != NULL ) { if (attribute != NULL)
node.id = stringToUint(( const char* ) attribute ); {
xmlFree( attribute ); 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)
{
const int childType = xmlTextReaderNodeType(inputReader);
// 1 = Element, 15 = EndElement // 1 = Element, 15 = EndElement
if ( childType != 1 && childType != 15 ) { if (childType != 1 && childType != 15)
{
continue; continue;
} }
const int childDepth = xmlTextReaderDepth( inputReader ); const int childDepth = xmlTextReaderDepth(inputReader);
xmlChar* childName = xmlTextReaderName( inputReader ); xmlChar *childName = xmlTextReaderName(inputReader);
if ( childName == NULL ) { if (childName == NULL)
{
continue; 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)
{
xmlFree(childName);
break; break;
} }
if ( childType != 1 ) { if (childType != 1)
xmlFree( childName ); {
xmlFree(childName);
continue; 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)
{
node.keyVals.emplace(std::string((char *)(k)),
std::string((char *)(value)));
} }
if ( k != NULL ) { if (k != NULL)
xmlFree( k ); {
xmlFree(k);
} }
if ( value != NULL ) { if (value != NULL)
xmlFree( value ); {
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();