Implementation of turn restriction exceptions

This commit is contained in:
DennisOSRM 2013-01-05 19:20:25 +01:00
parent 5de2aa1cbf
commit ffdaa71086
6 changed files with 761 additions and 692 deletions

View File

@ -21,489 +21,524 @@
#include "PBFParser.h" #include "PBFParser.h"
PBFParser::PBFParser(const char * fileName) : externalMemory(NULL){ PBFParser::PBFParser(const char * fileName) : externalMemory(NULL){
GOOGLE_PROTOBUF_VERIFY_VERSION; GOOGLE_PROTOBUF_VERIFY_VERSION;
//TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk? //TODO: What is the bottleneck here? Filling the queue or reading the stuff from disk?
//NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free. //NOTE: With Lua scripting, it is parsing the stuff. I/O is virtually for free.
threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */ threadDataQueue = boost::make_shared<ConcurrentQueue<_ThreadData*> >( 2500 ); /* Max 2500 items in queue, hardcoded. */
input.open(fileName, std::ios::in | std::ios::binary); input.open(fileName, std::ios::in | std::ios::binary);
if (!input) { if (!input) {
std::cerr << fileName << ": File not found." << std::endl; std::cerr << fileName << ": File not found." << std::endl;
} }
#ifndef NDEBUG #ifndef NDEBUG
blockCount = 0; blockCount = 0;
groupCount = 0; groupCount = 0;
#endif #endif
} }
void PBFParser::RegisterCallbacks(ExtractorCallbacks * em) { void PBFParser::RegisterCallbacks(ExtractorCallbacks * em) {
externalMemory = em; externalMemory = em;
} }
void PBFParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { void PBFParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
scriptingEnvironment = _se; scriptingEnvironment = _se;
if(lua_function_exists(scriptingEnvironment.getLuaStateForThreadID(0), "get_exceptions" )) {
//get list of turn restriction exceptions
try {
luabind::call_function<void>(
scriptingEnvironment.getLuaStateForThreadID(0),
"get_exceptions",
boost::ref(restriction_exceptions_vector)
);
INFO("Found " << restriction_exceptions_vector.size() << " exceptions to turn restriction");
BOOST_FOREACH(std::string & str, restriction_exceptions_vector) {
INFO("ignoring: " << str);
}
} catch (const luabind::error &er) {
lua_State* Ler=er.state();
report_errors(Ler, -1);
ERR(er.what());
}
} else {
INFO("Found no exceptions to turn restrictions");
}
} }
PBFParser::~PBFParser() { PBFParser::~PBFParser() {
if(input.is_open()) if(input.is_open())
input.close(); input.close();
// Clean up any leftover ThreadData objects in the queue // Clean up any leftover ThreadData objects in the queue
_ThreadData* td; _ThreadData* td;
while (threadDataQueue->try_pop(td)) { while (threadDataQueue->try_pop(td)) {
delete td; delete td;
} }
google::protobuf::ShutdownProtobufLibrary(); google::protobuf::ShutdownProtobufLibrary();
#ifndef NDEBUG #ifndef NDEBUG
DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups"); DEBUG("parsed " << blockCount << " blocks from pbf with " << groupCount << " groups");
#endif #endif
} }
inline bool PBFParser::Init() { inline bool PBFParser::Init() {
_ThreadData initData; _ThreadData initData;
/** read Header */ /** read Header */
if(!readPBFBlobHeader(input, &initData)) { if(!readPBFBlobHeader(input, &initData)) {
return false; return false;
} }
if(readBlob(input, &initData)) { if(readBlob(input, &initData)) {
if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) { if(!initData.PBFHeaderBlock.ParseFromArray(&(initData.charBuffer[0]), initData.charBuffer.size() ) ) {
std::cerr << "[error] Header not parseable!" << std::endl; std::cerr << "[error] Header not parseable!" << std::endl;
return false; return false;
} }
for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) { for(int i = 0, featureSize = initData.PBFHeaderBlock.required_features_size(); i < featureSize; ++i) {
const std::string& feature = initData.PBFHeaderBlock.required_features( i ); const std::string& feature = initData.PBFHeaderBlock.required_features( i );
bool supported = false; bool supported = false;
if ( "OsmSchema-V0.6" == feature ) if ( "OsmSchema-V0.6" == feature )
supported = true; supported = true;
else if ( "DenseNodes" == feature ) else if ( "DenseNodes" == feature )
supported = true; supported = true;
if ( !supported ) { if ( !supported ) {
std::cerr << "[error] required feature not supported: " << feature.data() << std::endl; std::cerr << "[error] required feature not supported: " << feature.data() << std::endl;
return false; return false;
} }
} }
} else { } else {
std::cerr << "[error] blob not loaded!" << std::endl; std::cerr << "[error] blob not loaded!" << std::endl;
} }
return true; return true;
} }
inline void PBFParser::ReadData() { inline void PBFParser::ReadData() {
bool keepRunning = true; bool keepRunning = true;
do { do {
_ThreadData *threadData = new _ThreadData(); _ThreadData *threadData = new _ThreadData();
keepRunning = readNextBlock(input, threadData); keepRunning = readNextBlock(input, threadData);
if (keepRunning) if (keepRunning)
threadDataQueue->push(threadData); threadDataQueue->push(threadData);
else { else {
threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered threadDataQueue->push(NULL); // No more data to read, parse stops when NULL encountered
delete threadData; delete threadData;
} }
} while(keepRunning); } while(keepRunning);
} }
inline void PBFParser::ParseData() { inline void PBFParser::ParseData() {
while (true) { while (true) {
_ThreadData *threadData; _ThreadData *threadData;
threadDataQueue->wait_and_pop(threadData); threadDataQueue->wait_and_pop(threadData);
if (threadData == NULL) { if (threadData == NULL) {
INFO("Parse Data Thread Finished"); INFO("Parse Data Thread Finished");
threadDataQueue->push(NULL); // Signal end of data for other threads threadDataQueue->push(NULL); // Signal end of data for other threads
break; break;
} }
loadBlock(threadData); loadBlock(threadData);
for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) { for(int i = 0, groupSize = threadData->PBFprimitiveBlock.primitivegroup_size(); i < groupSize; ++i) {
threadData->currentGroupID = i; threadData->currentGroupID = i;
loadGroup(threadData); loadGroup(threadData);
if(threadData->entityTypeIndicator == TypeNode) if(threadData->entityTypeIndicator == TypeNode)
parseNode(threadData); parseNode(threadData);
if(threadData->entityTypeIndicator == TypeWay) if(threadData->entityTypeIndicator == TypeWay)
parseWay(threadData); parseWay(threadData);
if(threadData->entityTypeIndicator == TypeRelation) if(threadData->entityTypeIndicator == TypeRelation)
parseRelation(threadData); parseRelation(threadData);
if(threadData->entityTypeIndicator == TypeDenseNode) if(threadData->entityTypeIndicator == TypeDenseNode)
parseDenseNode(threadData); parseDenseNode(threadData);
} }
delete threadData; delete threadData;
threadData = NULL; threadData = NULL;
} }
} }
inline bool PBFParser::Parse() { inline bool PBFParser::Parse() {
// Start the read and parse threads // Start the read and parse threads
boost::thread readThread(boost::bind(&PBFParser::ReadData, this)); boost::thread readThread(boost::bind(&PBFParser::ReadData, this));
//Open several parse threads that are synchronized before call to //Open several parse threads that are synchronized before call to
boost::thread parseThread(boost::bind(&PBFParser::ParseData, this)); boost::thread parseThread(boost::bind(&PBFParser::ParseData, this));
// Wait for the threads to finish // Wait for the threads to finish
readThread.join(); readThread.join();
parseThread.join(); parseThread.join();
return true; return true;
} }
inline void PBFParser::parseDenseNode(_ThreadData * threadData) { inline void PBFParser::parseDenseNode(_ThreadData * threadData) {
const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense(); const OSMPBF::DenseNodes& dense = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).dense();
int denseTagIndex = 0; int denseTagIndex = 0;
int m_lastDenseID = 0; int m_lastDenseID = 0;
int m_lastDenseLatitude = 0; int m_lastDenseLatitude = 0;
int m_lastDenseLongitude = 0; int m_lastDenseLongitude = 0;
ImportNode n; ImportNode n;
std::vector<ImportNode> nodesToParse; std::vector<ImportNode> nodesToParse;
for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) { for(int i = 0, idSize = dense.id_size(); i < idSize; ++i) {
n.Clear(); n.Clear();
m_lastDenseID += dense.id( i ); m_lastDenseID += dense.id( i );
m_lastDenseLatitude += dense.lat( i ); m_lastDenseLatitude += dense.lat( i );
m_lastDenseLongitude += dense.lon( i ); m_lastDenseLongitude += dense.lon( i );
n.id = m_lastDenseID; n.id = m_lastDenseID;
n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO; n.lat = 100000*( ( double ) m_lastDenseLatitude * threadData->PBFprimitiveBlock.granularity() +threadData-> PBFprimitiveBlock.lat_offset() ) / NANO;
n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO; n.lon = 100000*( ( double ) m_lastDenseLongitude * threadData->PBFprimitiveBlock.granularity() + threadData->PBFprimitiveBlock.lon_offset() ) / NANO;
while (denseTagIndex < dense.keys_vals_size()) { while (denseTagIndex < dense.keys_vals_size()) {
const int tagValue = dense.keys_vals( denseTagIndex ); const int tagValue = dense.keys_vals( denseTagIndex );
if(tagValue == 0) { if(tagValue == 0) {
++denseTagIndex; ++denseTagIndex;
break; break;
} }
const int keyValue = dense.keys_vals ( denseTagIndex+1 ); const int keyValue = dense.keys_vals ( denseTagIndex+1 );
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data(); const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(tagValue).data();
const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data(); const std::string & value = threadData->PBFprimitiveBlock.stringtable().s(keyValue).data();
n.keyVals.Add(key, value); n.keyVals.Add(key, value);
denseTagIndex += 2; denseTagIndex += 2;
} }
nodesToParse.push_back(n); nodesToParse.push_back(n);
} }
unsigned endi_nodes = nodesToParse.size(); unsigned endi_nodes = nodesToParse.size();
#pragma omp parallel for schedule ( guided ) #pragma omp parallel for schedule ( guided )
for(unsigned i = 0; i < endi_nodes; ++i) { for(unsigned i = 0; i < endi_nodes; ++i) {
ImportNode &n = nodesToParse[i]; ImportNode &n = nodesToParse[i];
/** Pass the unpacked node to the LUA call back **/ /** Pass the unpacked node to the LUA call back **/
try { try {
luabind::call_function<int>( luabind::call_function<int>(
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
"node_function", "node_function",
boost::ref(n) boost::ref(n)
); );
} catch (const luabind::error &er) { } catch (const luabind::error &er) {
lua_State* Ler=er.state(); lua_State* Ler=er.state();
report_errors(Ler, -1); report_errors(Ler, -1);
ERR(er.what()); ERR(er.what());
} }
// catch (...) { // catch (...) {
// ERR("Unknown error occurred during PBF dense node parsing!"); // ERR("Unknown error occurred during PBF dense node parsing!");
// } // }
} }
BOOST_FOREACH(ImportNode &n, nodesToParse) { BOOST_FOREACH(ImportNode &n, nodesToParse) {
if(!externalMemory->nodeFunction(n)) if(!externalMemory->nodeFunction(n))
std::cerr << "[PBFParser] dense node not parsed" << std::endl; std::cerr << "[PBFParser] dense node not parsed" << std::endl;
} }
} }
inline void PBFParser::parseNode(_ThreadData * ) { inline void PBFParser::parseNode(_ThreadData * ) {
ERR("Parsing of simple nodes not supported. PBF should use dense nodes"); ERR("Parsing of simple nodes not supported. PBF should use dense nodes");
} }
inline void PBFParser::parseRelation(_ThreadData * threadData) { inline void PBFParser::parseRelation(_ThreadData * threadData) {
//TODO: leave early, if relatio is not a restriction //TODO: leave early, if relation is not a restriction
//TODO: reuse rawRestriction container //TODO: reuse rawRestriction container
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
for(int i = 0; i < group.relations_size(); ++i ) { for(int i = 0; i < group.relations_size(); ++i ) {
const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i); std::string exception_of_restriction_tag;
bool isRestriction = false; const OSMPBF::Relation& inputRelation = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).relations(i);
bool isOnlyRestriction = false; bool isRestriction = false;
for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) { bool isOnlyRestriction = false;
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k)); for(int k = 0, endOfKeys = inputRelation.keys_size(); k < endOfKeys; ++k) {
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k)); const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.keys(k));
if ("type" == key) { const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputRelation.vals(k));
if( "restriction" == val) if ("type" == key) {
isRestriction = true; if( "restriction" == val)
else isRestriction = true;
break; else
} break;
if ("restriction" == key) { }
if(val.find("only_") == 0) if ("restriction" == key) {
isOnlyRestriction = true; if(val.find("only_") == 0)
} isOnlyRestriction = true;
}
if ("except" == key) {
exception_of_restriction_tag = val;
}
}
} //Check if restriction shall be ignored
if(isRestriction) { if(isRestriction && ("" != exception_of_restriction_tag) ) {
long long lastRef = 0; //Be warned, this is quadratic work here, but we assume that
_RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction); //only a few exceptions are actually defined.
for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) { std::vector<std::string> tokenized_exception_tags_of_restriction;
std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data()); boost::algorithm::split_regex(tokenized_exception_tags_of_restriction, exception_of_restriction_tag, boost::regex("[;][ ]*"));
lastRef += inputRelation.memids(rolesIndex); BOOST_FOREACH(std::string & str, tokenized_exception_tags_of_restriction) {
if(restriction_exceptions_vector.end() != std::find(restriction_exceptions_vector.begin(), restriction_exceptions_vector.end(), str)) {
isRestriction = false;
break; //BOOST_FOREACH
}
}
}
if(false == ("from" == role || "to" == role || "via" == role)) {
continue;
}
switch(inputRelation.types(rolesIndex)) { if(isRestriction) {
case 0: //node long long lastRef = 0;
if("from" == role || "to" == role) //Only via should be a node _RawRestrictionContainer currentRestrictionContainer(isOnlyRestriction);
continue; for(int rolesIndex = 0; rolesIndex < inputRelation.roles_sid_size(); ++rolesIndex) {
assert("via" == role); std::string role(threadData->PBFprimitiveBlock.stringtable().s( inputRelation.roles_sid( rolesIndex ) ).data());
if(UINT_MAX != currentRestrictionContainer.viaNode) lastRef += inputRelation.memids(rolesIndex);
currentRestrictionContainer.viaNode = UINT_MAX;
assert(UINT_MAX == currentRestrictionContainer.viaNode);
currentRestrictionContainer.restriction.viaNode = lastRef;
break;
case 1: //way
assert("from" == role || "to" == role || "via" == role);
if("from" == role) {
currentRestrictionContainer.fromWay = lastRef;
}
if ("to" == role) {
currentRestrictionContainer.toWay = lastRef;
}
if ("via" == role) {
assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
currentRestrictionContainer.viaNode = lastRef;
}
break;
case 2: //relation, not used. relations relating to relations are evil.
continue;
assert(false);
break;
default: //should not happen if(!("from" == role || "to" == role || "via" == role)) {
//cout << "unknown"; continue;
assert(false); }
break;
} switch(inputRelation.types(rolesIndex)) {
} case 0: //node
// if(UINT_MAX != currentRestriction.viaNode) { if("from" == role || "to" == role) //Only via should be a node
// cout << "restr from " << currentRestriction.from << " via "; continue;
// cout << "node " << currentRestriction.viaNode; assert("via" == role);
// cout << " to " << currentRestriction.to << endl; if(UINT_MAX != currentRestrictionContainer.viaNode)
// } currentRestrictionContainer.viaNode = UINT_MAX;
if(!externalMemory->restrictionFunction(currentRestrictionContainer)) assert(UINT_MAX == currentRestrictionContainer.viaNode);
std::cerr << "[PBFParser] relation not parsed" << std::endl; currentRestrictionContainer.restriction.viaNode = lastRef;
} break;
} case 1: //way
assert("from" == role || "to" == role || "via" == role);
if("from" == role) {
currentRestrictionContainer.fromWay = lastRef;
}
if ("to" == role) {
currentRestrictionContainer.toWay = lastRef;
}
if ("via" == role) {
assert(currentRestrictionContainer.restriction.toNode == UINT_MAX);
currentRestrictionContainer.viaNode = lastRef;
}
break;
case 2: //relation, not used. relations relating to relations are evil.
continue;
assert(false);
break;
default: //should not happen
//cout << "unknown";
assert(false);
break;
}
}
if(!externalMemory->restrictionFunction(currentRestrictionContainer))
std::cerr << "[PBFParser] relation not parsed" << std::endl;
}
}
} }
inline void PBFParser::parseWay(_ThreadData * threadData) { inline void PBFParser::parseWay(_ThreadData * threadData) {
_Way w; _Way w;
std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size()); std::vector<_Way> waysToParse(threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size());
for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) { for(int i = 0, ways_size = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways_size(); i < ways_size; ++i) {
w.Clear(); w.Clear();
const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i ); const OSMPBF::Way& inputWay = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ).ways( i );
w.id = inputWay.id(); w.id = inputWay.id();
unsigned pathNode(0); unsigned pathNode(0);
for(int i = 0; i < inputWay.refs_size(); ++i) { for(int i = 0; i < inputWay.refs_size(); ++i) {
pathNode += inputWay.refs(i); pathNode += inputWay.refs(i);
w.path.push_back(pathNode); w.path.push_back(pathNode);
} }
assert(inputWay.keys_size() == inputWay.vals_size()); assert(inputWay.keys_size() == inputWay.vals_size());
for(int i = 0; i < inputWay.keys_size(); ++i) { for(int i = 0; i < inputWay.keys_size(); ++i) {
const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i)); const std::string & key = threadData->PBFprimitiveBlock.stringtable().s(inputWay.keys(i));
const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i)); const std::string & val = threadData->PBFprimitiveBlock.stringtable().s(inputWay.vals(i));
w.keyVals.Add(key, val); w.keyVals.Add(key, val);
} }
waysToParse.push_back(w); waysToParse.push_back(w);
} }
unsigned endi_ways = waysToParse.size(); unsigned endi_ways = waysToParse.size();
#pragma omp parallel for schedule ( guided ) #pragma omp parallel for schedule ( guided )
for(unsigned i = 0; i < endi_ways; ++i) { for(unsigned i = 0; i < endi_ways; ++i) {
_Way & w = waysToParse[i]; _Way & w = waysToParse[i];
/** Pass the unpacked way to the LUA call back **/ /** Pass the unpacked way to the LUA call back **/
try { try {
luabind::call_function<int>( luabind::call_function<int>(
scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()), scriptingEnvironment.getLuaStateForThreadID(omp_get_thread_num()),
"way_function", "way_function",
boost::ref(w), boost::ref(w),
w.path.size() w.path.size()
); );
} catch (const luabind::error &er) { } catch (const luabind::error &er) {
lua_State* Ler=er.state(); lua_State* Ler=er.state();
report_errors(Ler, -1); report_errors(Ler, -1);
ERR(er.what()); ERR(er.what());
} }
// catch (...) { // catch (...) {
// ERR("Unknown error!"); // ERR("Unknown error!");
// } // }
} }
BOOST_FOREACH(_Way & w, waysToParse) { BOOST_FOREACH(_Way & w, waysToParse) {
if(!externalMemory->wayFunction(w)) { if(!externalMemory->wayFunction(w)) {
std::cerr << "[PBFParser] way not parsed" << std::endl; std::cerr << "[PBFParser] way not parsed" << std::endl;
} }
} }
} }
inline void PBFParser::loadGroup(_ThreadData * threadData) { inline void PBFParser::loadGroup(_ThreadData * threadData) {
#ifndef NDEBUG #ifndef NDEBUG
++groupCount; ++groupCount;
#endif #endif
const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID ); const OSMPBF::PrimitiveGroup& group = threadData->PBFprimitiveBlock.primitivegroup( threadData->currentGroupID );
threadData->entityTypeIndicator = 0; threadData->entityTypeIndicator = 0;
if ( group.nodes_size() != 0 ) { if ( group.nodes_size() != 0 ) {
threadData->entityTypeIndicator = TypeNode; threadData->entityTypeIndicator = TypeNode;
} }
if ( group.ways_size() != 0 ) { if ( group.ways_size() != 0 ) {
threadData->entityTypeIndicator = TypeWay; threadData->entityTypeIndicator = TypeWay;
} }
if ( group.relations_size() != 0 ) { if ( group.relations_size() != 0 ) {
threadData->entityTypeIndicator = TypeRelation; threadData->entityTypeIndicator = TypeRelation;
} }
if ( group.has_dense() ) { if ( group.has_dense() ) {
threadData->entityTypeIndicator = TypeDenseNode; threadData->entityTypeIndicator = TypeDenseNode;
assert( group.dense().id_size() != 0 ); assert( group.dense().id_size() != 0 );
} }
assert( threadData->entityTypeIndicator != 0 ); assert( threadData->entityTypeIndicator != 0 );
} }
inline void PBFParser::loadBlock(_ThreadData * threadData) { inline void PBFParser::loadBlock(_ThreadData * threadData) {
#ifndef NDEBUG #ifndef NDEBUG
++blockCount; ++blockCount;
#endif #endif
threadData->currentGroupID = 0; threadData->currentGroupID = 0;
threadData->currentEntityID = 0; threadData->currentEntityID = 0;
} }
inline bool PBFParser::readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) { inline bool PBFParser::readPBFBlobHeader(std::fstream& stream, _ThreadData * threadData) {
int size(0); int size(0);
stream.read((char *)&size, sizeof(int)); stream.read((char *)&size, sizeof(int));
size = swapEndian(size); size = swapEndian(size);
if(stream.eof()) { if(stream.eof()) {
return false; return false;
} }
if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) { if ( size > MAX_BLOB_HEADER_SIZE || size < 0 ) {
return false; return false;
} }
char *data = new char[size]; char *data = new char[size];
stream.read(data, size*sizeof(data[0])); stream.read(data, size*sizeof(data[0]));
bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size); bool dataSuccessfullyParsed = (threadData->PBFBlobHeader).ParseFromArray( data, size);
delete[] data; delete[] data;
return dataSuccessfullyParsed; return dataSuccessfullyParsed;
} }
inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) { inline bool PBFParser::unpackZLIB(std::fstream &, _ThreadData * threadData) {
unsigned rawSize = threadData->PBFBlob.raw_size(); unsigned rawSize = threadData->PBFBlob.raw_size();
char* unpackedDataArray = new char[rawSize]; char* unpackedDataArray = new char[rawSize];
z_stream compressedDataStream; z_stream compressedDataStream;
compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data(); compressedDataStream.next_in = ( unsigned char* ) threadData->PBFBlob.zlib_data().data();
compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size(); compressedDataStream.avail_in = threadData->PBFBlob.zlib_data().size();
compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray; compressedDataStream.next_out = ( unsigned char* ) unpackedDataArray;
compressedDataStream.avail_out = rawSize; compressedDataStream.avail_out = rawSize;
compressedDataStream.zalloc = Z_NULL; compressedDataStream.zalloc = Z_NULL;
compressedDataStream.zfree = Z_NULL; compressedDataStream.zfree = Z_NULL;
compressedDataStream.opaque = Z_NULL; compressedDataStream.opaque = Z_NULL;
int ret = inflateInit( &compressedDataStream ); int ret = inflateInit( &compressedDataStream );
if ( ret != Z_OK ) { if ( ret != Z_OK ) {
std::cerr << "[error] failed to init zlib stream" << std::endl; std::cerr << "[error] failed to init zlib stream" << std::endl;
delete[] unpackedDataArray; delete[] unpackedDataArray;
return false; return false;
} }
ret = inflate( &compressedDataStream, Z_FINISH ); ret = inflate( &compressedDataStream, Z_FINISH );
if ( ret != Z_STREAM_END ) { if ( ret != Z_STREAM_END ) {
std::cerr << "[error] failed to inflate zlib stream" << std::endl; std::cerr << "[error] failed to inflate zlib stream" << std::endl;
std::cerr << "[error] Error type: " << ret << std::endl; std::cerr << "[error] Error type: " << ret << std::endl;
delete[] unpackedDataArray; delete[] unpackedDataArray;
return false; return false;
} }
ret = inflateEnd( &compressedDataStream ); ret = inflateEnd( &compressedDataStream );
if ( ret != Z_OK ) { if ( ret != Z_OK ) {
std::cerr << "[error] failed to deinit zlib stream" << std::endl; std::cerr << "[error] failed to deinit zlib stream" << std::endl;
delete[] unpackedDataArray; delete[] unpackedDataArray;
return false; return false;
} }
threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize); threadData->charBuffer.clear(); threadData->charBuffer.resize(rawSize);
std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin()); std::copy(unpackedDataArray, unpackedDataArray + rawSize, threadData->charBuffer.begin());
delete[] unpackedDataArray; delete[] unpackedDataArray;
return true; return true;
} }
inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) { inline bool PBFParser::unpackLZMA(std::fstream &, _ThreadData * ) {
return false; return false;
} }
inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) { inline bool PBFParser::readBlob(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) if(stream.eof())
return false; return false;
const int size = threadData->PBFBlobHeader.datasize(); const int size = threadData->PBFBlobHeader.datasize();
if ( size < 0 || size > MAX_BLOB_SIZE ) { if ( size < 0 || size > MAX_BLOB_SIZE ) {
std::cerr << "[error] invalid Blob size:" << size << std::endl; std::cerr << "[error] invalid Blob size:" << size << std::endl;
return false; return false;
} }
char* data = new char[size]; char* data = new char[size];
stream.read(data, sizeof(data[0])*size); stream.read(data, sizeof(data[0])*size);
if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) { if ( !threadData->PBFBlob.ParseFromArray( data, size ) ) {
std::cerr << "[error] failed to parse blob" << std::endl; std::cerr << "[error] failed to parse blob" << std::endl;
delete[] data; delete[] data;
return false; return false;
} }
if ( threadData->PBFBlob.has_raw() ) { if ( threadData->PBFBlob.has_raw() ) {
const std::string& data = threadData->PBFBlob.raw(); const std::string& data = threadData->PBFBlob.raw();
threadData->charBuffer.clear(); threadData->charBuffer.clear();
threadData->charBuffer.resize( data.size() ); threadData->charBuffer.resize( data.size() );
std::copy(data.begin(), data.end(), threadData->charBuffer.begin()); std::copy(data.begin(), data.end(), threadData->charBuffer.begin());
} else if ( threadData->PBFBlob.has_zlib_data() ) { } else if ( threadData->PBFBlob.has_zlib_data() ) {
if ( !unpackZLIB(stream, threadData) ) { if ( !unpackZLIB(stream, threadData) ) {
std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl; std::cerr << "[error] zlib data encountered that could not be unpacked" << std::endl;
delete[] data; delete[] data;
return false; return false;
} }
} else if ( threadData->PBFBlob.has_lzma_data() ) { } else if ( threadData->PBFBlob.has_lzma_data() ) {
if ( !unpackLZMA(stream, threadData) ) if ( !unpackLZMA(stream, threadData) )
std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl; std::cerr << "[error] lzma data encountered that could not be unpacked" << std::endl;
delete[] data; delete[] data;
return false; return false;
} else { } else {
std::cerr << "[error] Blob contains no data" << std::endl; std::cerr << "[error] Blob contains no data" << std::endl;
delete[] data; delete[] data;
return false; return false;
} }
delete[] data; delete[] data;
return true; return true;
} }
bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) { bool PBFParser::readNextBlock(std::fstream& stream, _ThreadData * threadData) {
if(stream.eof()) { if(stream.eof()) {
return false; return false;
} }
if ( !readPBFBlobHeader(stream, threadData) ){ if ( !readPBFBlobHeader(stream, threadData) ){
return false; return false;
} }
if ( threadData->PBFBlobHeader.type() != "OSMData" ) { if ( threadData->PBFBlobHeader.type() != "OSMData" ) {
return false; return false;
} }
if ( !readBlob(stream, threadData) ) { if ( !readBlob(stream, threadData) ) {
return false; return false;
} }
if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) { if ( !threadData->PBFprimitiveBlock.ParseFromArray( &(threadData->charBuffer[0]), threadData-> charBuffer.size() ) ) {
ERR("failed to parse PrimitiveBlock"); ERR("failed to parse PrimitiveBlock");
return false; return false;
} }
return true; return true;
} }

View File

@ -106,6 +106,8 @@ private:
/* ThreadData Queue */ /* ThreadData Queue */
boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue; boost::shared_ptr<ConcurrentQueue < _ThreadData* > > threadDataQueue;
ScriptingEnvironment scriptingEnvironment; ScriptingEnvironment scriptingEnvironment;
std::vector<std::string> restriction_exceptions_vector;
}; };
#endif /* PBFPARSER_H_ */ #endif /* PBFPARSER_H_ */

View File

@ -18,16 +18,7 @@
or see http://www.gnu.org/licenses/agpl.txt. or see http://www.gnu.org/licenses/agpl.txt.
*/ */
extern "C" {
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
}
#include "ScriptingEnvironment.h" #include "ScriptingEnvironment.h"
#include "../typedefs.h"
#include "../Util/LuaUtil.h"
#include "../Util/OpenMPWrapper.h"
ScriptingEnvironment::ScriptingEnvironment() {} ScriptingEnvironment::ScriptingEnvironment() {}
ScriptingEnvironment::ScriptingEnvironment(const char * fileName) { ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
@ -45,6 +36,8 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
//open utility libraries string library; //open utility libraries string library;
luaL_openlibs(myLuaState); luaL_openlibs(myLuaState);
luaAddScriptFolderToLoadPath( myLuaState, fileName );
// Add our function to the state's global scope // Add our function to the state's global scope
luabind::module(myLuaState) [ luabind::module(myLuaState) [
luabind::def("print", LUA_print<std::string>), luabind::def("print", LUA_print<std::string>),
@ -53,17 +46,6 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
luabind::def("parseDuration", parseDuration) luabind::def("parseDuration", parseDuration)
]; ];
luaAddScriptFolderToLoadPath( myLuaState, fileName );
//#pragma omp critical
// {
// if(0 != luaL_dostring(
// myLuaState,
// "print('Initializing LUA engine')\n"
// )) {
// ERR(lua_tostring(myLuaState,-1)<< " occured in scripting block");
// }
// }
luabind::module(myLuaState) [ luabind::module(myLuaState) [
luabind::class_<HashTable<std::string, std::string> >("keyVals") luabind::class_<HashTable<std::string, std::string> >("keyVals")
.def("Add", &HashTable<std::string, std::string>::Add) .def("Add", &HashTable<std::string, std::string>::Add)
@ -96,13 +78,17 @@ ScriptingEnvironment::ScriptingEnvironment(const char * fileName) {
.def_readwrite("tags", &_Way::keyVals) .def_readwrite("tags", &_Way::keyVals)
.def_readwrite("direction", &_Way::direction) .def_readwrite("direction", &_Way::direction)
.enum_("constants") .enum_("constants")
[ [
luabind::value("notSure", 0), luabind::value("notSure", 0),
luabind::value("oneway", 1), luabind::value("oneway", 1),
luabind::value("bidirectional", 2), luabind::value("bidirectional", 2),
luabind::value("opposite", 3) luabind::value("opposite", 3)
] ]
]; ];
luabind::module(myLuaState) [
luabind::class_<std::vector<std::string> >("vector")
.def("Add", &std::vector<std::string>::push_back)
];
// Now call our function in a lua script // Now call our function in a lua script
//#pragma omp critical //#pragma omp critical

View File

@ -31,7 +31,10 @@ extern "C" {
#include "ExtractionHelperFunctions.h" #include "ExtractionHelperFunctions.h"
#include "ExtractorStructs.h" #include "ExtractorStructs.h"
#include "../typedefs.h"
#include "../DataStructures/ImportNode.h" #include "../DataStructures/ImportNode.h"
#include "../Util/LuaUtil.h"
#include "../Util/OpenMPWrapper.h"
class ScriptingEnvironment { class ScriptingEnvironment {
public: public:

View File

@ -28,263 +28,304 @@
XMLParser::XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){ XMLParser::XMLParser(const char * filename) : externalMemory(NULL), myLuaState(NULL){
WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf"); WARN("Parsing plain .osm/.osm.bz2 is deprecated. Switch to .pbf");
inputReader = inputReaderFactory(filename); inputReader = inputReaderFactory(filename);
} }
XMLParser::~XMLParser() {} XMLParser::~XMLParser() {}
void XMLParser::RegisterCallbacks(ExtractorCallbacks * em) { void XMLParser::RegisterCallbacks(ExtractorCallbacks * em) {
externalMemory = em; externalMemory = em;
} }
void XMLParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) { void XMLParser::RegisterScriptingEnvironment(ScriptingEnvironment & _se) {
myLuaState = _se.getLuaStateForThreadID(0); myLuaState = _se.getLuaStateForThreadID(0);
if(lua_function_exists(myLuaState, "get_exceptions" )) {
//get list of turn restriction exceptions
try {
luabind::call_function<void>(
myLuaState,
"get_exceptions",
boost::ref(restriction_exceptions_vector)
);
INFO("Found " << restriction_exceptions_vector.size() << " exceptions to turn restriction");
BOOST_FOREACH(std::string & str, restriction_exceptions_vector) {
INFO(" " << str);
}
} catch (const luabind::error &er) {
lua_State* Ler=er.state();
report_errors(Ler, -1);
ERR(er.what());
}
} else {
INFO("Found no exceptions to turn restrictions");
}
} }
bool XMLParser::Init() { bool XMLParser::Init() {
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( ); ImportNode n = _ReadXMLNode( );
/** Pass the unpacked node to the LUA call back **/ /** Pass the unpacked node to the LUA call back **/
try { try {
luabind::call_function<int>( luabind::call_function<int>(
myLuaState, myLuaState,
"node_function", "node_function",
boost::ref(n) boost::ref(n)
); );
if(!externalMemory->nodeFunction(n)) if(!externalMemory->nodeFunction(n))
std::cerr << "[XMLParser] dense node not parsed" << std::endl; std::cerr << "[XMLParser] dense node not parsed" << std::endl;
} catch (const luabind::error &er) { } catch (const luabind::error &er) {
std::cerr << er.what() << std::endl; std::cerr << er.what() << std::endl;
lua_State* Ler=er.state(); lua_State* Ler=er.state();
report_errors(Ler, -1); report_errors(Ler, -1);
} catch (std::exception & e) { } catch (std::exception & e) {
ERR(e.what()); ERR(e.what());
} catch (...) { } catch (...) {
ERR("Unknown error occurred during XML node parsing!"); ERR("Unknown error occurred during XML node parsing!");
} }
} }
if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) { if ( xmlStrEqual( currentName, ( const xmlChar* ) "way" ) == 1 ) {
_Way way = _ReadXMLWay( ); _Way way = _ReadXMLWay( );
/** Pass the unpacked way to the LUA call back **/ /** Pass the unpacked way to the LUA call back **/
try { try {
luabind::call_function<int>( luabind::call_function<int>(
myLuaState, myLuaState,
"way_function", "way_function",
boost::ref(way), boost::ref(way),
way.path.size() way.path.size()
); );
if(!externalMemory->wayFunction(way)) { if(!externalMemory->wayFunction(way)) {
std::cerr << "[PBFParser] way not parsed" << std::endl; std::cerr << "[PBFParser] way not parsed" << std::endl;
} }
} catch (const luabind::error &er) { } catch (const luabind::error &er) {
std::cerr << er.what() << std::endl; std::cerr << er.what() << std::endl;
lua_State* Ler=er.state(); lua_State* Ler=er.state();
report_errors(Ler, -1); report_errors(Ler, -1);
} catch (std::exception & e) { } catch (std::exception & e) {
ERR(e.what()); ERR(e.what());
} catch (...) { } catch (...) {
ERR("Unknown error occurred during XML way parsing!"); ERR("Unknown error occurred during XML way parsing!");
} }
} }
if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) { if ( xmlStrEqual( currentName, ( const xmlChar* ) "relation" ) == 1 ) {
_RawRestrictionContainer r = _ReadXMLRestriction(); _RawRestrictionContainer r = _ReadXMLRestriction();
if(r.fromWay != UINT_MAX) { if(r.fromWay != UINT_MAX) {
if(!externalMemory->restrictionFunction(r)) { if(!externalMemory->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;
} }
_RawRestrictionContainer XMLParser::_ReadXMLRestriction() { _RawRestrictionContainer XMLParser::_ReadXMLRestriction() {
_RawRestrictionContainer restriction; _RawRestrictionContainer restriction;
std::string exception_of_restriction_tag;
bool restriction_is_excepted = false;
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) { const int depth = xmlTextReaderDepth( inputReader );while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int childType = xmlTextReaderNodeType( inputReader ); const int childType = xmlTextReaderNodeType( inputReader );
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* ) "relation" ) == 1 ) { if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "relation" ) == 1 ) {
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* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
if ( k != NULL && value != NULL ) { if ( k != NULL && value != NULL ) {
if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){ if(xmlStrEqual(k, ( const xmlChar* ) "restriction" )){
if(0 == std::string((const char *) value).find("only_")) if(0 == std::string((const char *) value).find("only_"))
restriction.restriction.flags.isOnly = true; restriction.restriction.flags.isOnly = true;
} }
}
if ( xmlStrEqual(k, (const xmlChar *) "except") ) {
exception_of_restriction_tag = (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 ) {
} else if ( xmlStrEqual( childName, ( const xmlChar* ) "member" ) == 1 ) { xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); if ( ref != NULL ) {
if ( ref != NULL ) { xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" );
xmlChar * role = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "role" ); xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
xmlChar * type = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "type" );
if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
restriction.toWay = atoi((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
restriction.fromWay = atoi((const char*) ref);
}
if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
restriction.restriction.viaNode = atoi((const char*) ref);
}
if(NULL != type) if(xmlStrEqual(role, (const xmlChar *) "to") && xmlStrEqual(type, (const xmlChar *) "way")) {
xmlFree( type ); restriction.toWay = atoi((const char*) ref);
if(NULL != role) }
xmlFree( role ); if(xmlStrEqual(role, (const xmlChar *) "from") && xmlStrEqual(type, (const xmlChar *) "way")) {
if(NULL != ref) restriction.fromWay = atoi((const char*) ref);
xmlFree( ref ); }
} if(xmlStrEqual(role, (const xmlChar *) "via") && xmlStrEqual(type, (const xmlChar *) "node")) {
} restriction.restriction.viaNode = atoi((const char*) ref);
xmlFree( childName ); }
}
} if(NULL != type)
return restriction; xmlFree( type );
if(NULL != role)
xmlFree( role );
if(NULL != ref)
xmlFree( ref );
}
}
xmlFree( childName );
}
}
//Check if restriction shall be ignored
if( "" != exception_of_restriction_tag ) {
//Be warned, this is quadratic work here, but we assume that
//only a few exceptions are actually defined.
std::vector<std::string> tokenized_exception_tags_of_restriction;
boost::algorithm::split_regex(tokenized_exception_tags_of_restriction, exception_of_restriction_tag, boost::regex("[;][ ]*"));
BOOST_FOREACH(std::string & str, tokenized_exception_tags_of_restriction) {
if(restriction_exceptions_vector.end() != std::find(restriction_exceptions_vector.begin(), restriction_exceptions_vector.end(), str)) {
restriction.fromWay = UINT_MAX; //workaround to ignore the restriction
break; //BOOST_FOREACH
}
}
}
return restriction;
} }
_Way XMLParser::_ReadXMLWay() { _Way XMLParser::_ReadXMLWay() {
_Way way; _Way way;
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
const int depth = xmlTextReaderDepth( inputReader ); const int depth = xmlTextReaderDepth( inputReader );
while ( xmlTextReaderRead( inputReader ) == 1 ) { while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int childType = xmlTextReaderNodeType( inputReader ); const int childType = xmlTextReaderNodeType( inputReader );
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* ) "way" ) == 1 ) { if ( depth == childDepth && childType == 15 && xmlStrEqual( childName, ( const xmlChar* ) "way" ) == 1 ) {
xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); xmlChar* id = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
way.id = atoi((char*)id); way.id = atoi((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* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
// cout << "->k=" << k << ", v=" << value << endl; // cout << "->k=" << k << ", v=" << value << endl;
if ( k != NULL && value != NULL ) { if ( k != NULL && value != NULL ) {
way.keyVals.Add(std::string( (char *) k ), std::string( (char *) value)); 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 ) { } else if ( xmlStrEqual( childName, ( const xmlChar* ) "nd" ) == 1 ) {
xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" ); xmlChar* ref = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "ref" );
if ( ref != NULL ) { if ( ref != NULL ) {
way.path.push_back( atoi(( const char* ) ref ) ); way.path.push_back( atoi(( const char* ) ref ) );
xmlFree( ref ); xmlFree( ref );
} }
} }
xmlFree( childName ); 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>(100000.*atof(( const char* ) attribute ) ); node.lat = static_cast<NodeID>(100000.*atof(( const char* ) attribute ) );
xmlFree( 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>(100000.*atof(( const char* ) attribute )); node.lon = static_cast<NodeID>(100000.*atof(( const char* ) attribute ));
xmlFree( attribute ); xmlFree( attribute );
} }
attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" ); attribute = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "id" );
if ( attribute != NULL ) { if ( attribute != NULL ) {
node.id = atoi(( const char* ) attribute ); node.id = atoi(( const char* ) attribute );
xmlFree( attribute ); xmlFree( attribute );
} }
if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) { if ( xmlTextReaderIsEmptyElement( inputReader ) != 1 ) {
const int depth = xmlTextReaderDepth( inputReader ); const int depth = xmlTextReaderDepth( inputReader );
while ( xmlTextReaderRead( inputReader ) == 1 ) { while ( xmlTextReaderRead( inputReader ) == 1 ) {
const int childType = xmlTextReaderNodeType( inputReader ); 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 && xmlStrEqual( childName, ( const xmlChar* ) "node" ) == 1 ) {
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* k = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "k" );
xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" ); xmlChar* value = xmlTextReaderGetAttribute( inputReader, ( const xmlChar* ) "v" );
if ( k != NULL && value != NULL ) { if ( k != NULL && value != NULL ) {
node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<char*>(value))); node.keyVals.Add(std::string( reinterpret_cast<char*>(k) ), std::string( reinterpret_cast<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

@ -45,6 +45,8 @@ private:
xmlTextReaderPtr inputReader; xmlTextReaderPtr inputReader;
ExtractorCallbacks * externalMemory; ExtractorCallbacks * externalMemory;
lua_State *myLuaState; lua_State *myLuaState;
std::vector<std::string> restriction_exceptions_vector;
}; };
#endif /* XMLPARSER_H_ */ #endif /* XMLPARSER_H_ */