void TagComparator::_addNonConflictingTags(Tags& t1, const Tags& t2, Tags& result) { OsmSchema& schema = OsmSchema::getInstance(); // we're deleting as we iterate so be careful making changes. for (Tags::iterator it1 = t1.begin(); it1 != t1.end(); ) { QString kvp1 = it1.key() + "=" + it1.value(); bool conflict = false; for (Tags::const_iterator it2 = t2.begin(); it2 != t2.end(); ++it2) { QString kvp2 = it2.key() + "=" + it2.value(); if (schema.score(kvp1, kvp2) > 0.0) { conflict = true; break; } } if (conflict) { ++it1; } else { result[it1.key()] = it1.value(); t1.erase(it1++); } } }
void TagComparator::_promoteToCommonAncestor(Tags& t1, Tags& t2, Tags& result) { OsmSchema& schema = OsmSchema::getInstance(); // we're deleting as we iterate so be careful making changes. for (Tags::iterator it1 = t1.begin(); it1 != t1.end(); ) { for (Tags::iterator it2 = t2.begin(); it2 != t2.end(); ) { const SchemaVertex& ancestor = schema.getFirstCommonAncestor(it1.key() + "=" + it1.value(), it2.key() + "=" + it2.value()); if (ancestor.isEmpty() == false) { // erase from the iterators in a safe way t1.erase(it1++); t2.erase(it2++); if (ancestor.value.isEmpty() == false) { result[ancestor.key] = ancestor.value; } } else { // if we didn't erase anything then increment the iterators. ++it2; } } if (it1 != t1.end()) { ++it1; } } }
void TagComparator::_overwriteUnrecognizedTags(Tags& t1, Tags& t2, Tags& result) { OsmSchema& schema = OsmSchema::getInstance(); const Tags t1Copy = t1; for (Tags::ConstIterator it1 = t1Copy.begin(); it1 != t1Copy.end(); ++it1) { // if this is an unknown type if (schema.getTagVertex(it1.key() + "=" + it1.value()).isEmpty() && schema.getTagVertex(it1.key()).isEmpty()) { // if this is also in t2. if (t2.contains(it1.key())) { result[it1.key()] = it1.value(); t1.remove(it1.key()); t2.remove(it1.key()); } } } // go through any remaining tags in t2 const Tags t2Copy = t2; for (Tags::ConstIterator it2 = t2Copy.begin(); it2 != t2Copy.end(); ++it2) { // if this is an unknown type if (schema.getTagVertex(it2.key() + "=" + it2.value()).isEmpty()) { // we know it isn't in t1, or it would have been handled in the above loop so just deal with // t2 t2.remove(it2.key()); result[it2.key()] = it2.value(); } } }
void TagComparator::_mergeText(Tags& t1, Tags& t2, Tags& result) { OsmSchema& schema = OsmSchema::getInstance(); const Tags t1Copy = t1; for (Tags::ConstIterator it1 = t1Copy.begin(); it1 != t1Copy.end(); ++it1) { const SchemaVertex& tv = schema.getTagVertex(it1.key()); // if this is a text field and it exists in both tag sets. if (tv.valueType == Text && t2.contains(it1.key())) { // only keep the unique text fields QStringList values = t1.getList(it1.key()); values.append(t2.getList(it1.key())); // append all unique values in the existing order. for (int i = 0; i < values.size(); i++) { if (values[i].isEmpty() == false) { result.appendValueIfUnique(it1.key(), values[i]); } } t1.remove(it1.key()); t2.remove(it1.key()); } } }
//------------------------------------------------------------------------------------------------------------------------------------ // Helper for ErrorMessenger. //------------------------------------------------------------------------------------------------------------------------------------ LogMgr::ErrorDialogResult LogMgr::Error(const std::string& errorMessage, bool isFatal, const char* funcName, const char* sourceFile, unsigned int lineNum) { string tag = ((isFatal) ? ("FATAL") : ("ERROR")); // buffer for our final output string string buffer; GetOutputBuffer(buffer, tag, errorMessage, funcName, sourceFile, lineNum); // write the final buffer to all the various logs m_tagCriticalSection.Lock(); Tags::iterator findIt = m_tags.find(tag); if (findIt != m_tags.end()) OutputFinalBufferToLogs(buffer, findIt->second); m_tagCriticalSection.Unlock(); // show the dialog box int result = ::MessageBoxA(NULL, buffer.c_str(), tag.c_str(), MB_ABORTRETRYIGNORE|MB_ICONERROR|MB_DEFBUTTON3); // act upon the choice switch (result) { case IDIGNORE : return LogMgr::LOGMGR_ERROR_IGNORE; case IDABORT : __debugbreak(); return LogMgr::LOGMGR_ERROR_RETRY; // assembly language instruction to break into the debugger case IDRETRY : return LogMgr::LOGMGR_ERROR_RETRY; default : return LogMgr::LOGMGR_ERROR_RETRY; } }
void TagComparator::_mergeUnrecognizedTags(Tags& t1, Tags& t2, Tags& result) { OsmSchema& schema = OsmSchema::getInstance(); const Tags t1Copy = t1; for (Tags::ConstIterator it1 = t1Copy.begin(); it1 != t1Copy.end(); ++it1) { // if this is an unknown type if (schema.getTagVertex(it1.key() + "=" + it1.value()).isEmpty() && schema.getTagVertex(it1.key()).isEmpty()) { // if this is also in t2. if (t2.contains(it1.key())) { // get the set of all values. QSet<QString> values = _toSet(t1, it1.key()); values.unite(_toSet(t2, it1.key())); QList<QString> sortEm = values.toList(); qSort(sortEm); // remove it from the inputs t1.remove(it1.key()); t2.remove(it1.key()); // set the united set in the output result.set(it1.key(), sortEm.begin(), sortEm.end()); } else { result[it1.key()] = it1.value(); } } } // go through any remaining tags in t2 const Tags t2Copy = t2; for (Tags::ConstIterator it2 = t2Copy.begin(); it2 != t2Copy.end(); ++it2) { // if this is an unknown type if (schema.getTagVertex(it2.key() + "=" + it2.value()).isEmpty()) { // we know it isn't in t1, or it would have been handled in the above loop so just deal with // t2 t2.remove(it2.key()); result[it2.key()] = it2.value(); } } }
bool TagComparator::nonNameTagsExactlyMatch(const Tags& t1, const Tags& t2) { const Qt::CaseSensitivity caseSensitivity = _caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; Tags t1Filtered; for (Tags::const_iterator it1 = t1.begin(); it1 != t1.end(); it1++) { QString key = it1.key(); QString value = it1.value(); if (!Tags::getNameKeys().contains(key, caseSensitivity) && //Metadata keys are controlled by hoot and, therefore, should always be lower case, so no //case check needed. !OsmSchema::getInstance().isMetaData(key, value)) { if (!_caseSensitive) { key = key.toUpper(); value = value.toUpper(); } t1Filtered.insert(key, value); } } Tags t2Filtered; for (Tags::const_iterator it2 = t2.begin(); it2 != t2.end(); it2++) { QString key = it2.key(); QString value = it2.value(); if (!Tags::getNameKeys().contains(key, caseSensitivity) && !OsmSchema::getInstance().isMetaData(key, value)) { if (!_caseSensitive) { key = key.toUpper(); value = value.toUpper(); } t2Filtered.insert(key, value); } } return t1Filtered == t2Filtered; }
void LogManager::Log(const std::string& tag, const std::string& msg, const char* funcName, const char* fileName, unsigned int lineNum) { m_CritSection.Lock(); Tags::iterator findIt = m_Tags.find(tag); if (findIt != m_Tags.end()) { std::string buffer; GetOutputBuffer(buffer, tag, msg, funcName, fileName, lineNum); OutputBufferToLogs(buffer, findIt->second); } m_CritSection.Unlock(); }
/* topological (depth-first) sorting of operations */ static void sort_operations_recursive(NodeOperationBuilder::Operations &sorted, Tags &visited, NodeOperation *op) { if (visited.find(op) != visited.end()) return; visited.insert(op); for (int i = 0; i < op->getNumberOfInputSockets(); ++i) { NodeOperationInput *input = op->getInputSocket(i); if (input->isConnected()) sort_operations_recursive(sorted, visited, &input->getLink()->getOperation()); } sorted.push_back(op); }
void LogManager::SetDisplayFlags(const std::string& tag, unsigned char flag) { m_CritSection.Lock(); if (flag != 0) { Tags::iterator findIt = m_Tags.find(tag); if (findIt == m_Tags.end()) m_Tags.insert(std::make_pair(tag, flag)); else findIt->second = flag; } else m_Tags.erase(tag); m_CritSection.Unlock(); }
static void add_group_operations_recursive(Tags &visited, NodeOperation *op, ExecutionGroup *group) { if (visited.find(op) != visited.end()) return; visited.insert(op); if (!group->addOperation(op)) return; /* add all eligible input ops to the group */ for (int i = 0; i < op->getNumberOfInputSockets(); ++i) { NodeOperationInput *input = op->getInputSocket(i); if (input->isConnected()) add_group_operations_recursive(visited, &input->getLink()->getOperation(), group); } }
/////////////////////////////////////////////////////////////////////////////////////// // sets one or more display flags /////////////////////////////////////////////////////////////////////////////////////// void LogMgr::SetDisplayFlags(const std::string& tag, unsigned char flags) { _tag_critical_section.Lock(); if(flags != 0) { Tags::iterator it = _tags.find(tag); if(it == _tags.end()) _tags.insert(std::make_pair(tag, flags)); else it->second = flags; } else { _tags.erase(tag); } _tag_critical_section.Unlock(); }
/////////////////////////////////////////////////////////////////////////////////////////////////////// // this function builds up the log string and outputs it to various places based on display flags /////////////////////////////////////////////////////////////////////////////////////////////////////// void LogMgr::Log(const string& tag, const string& message, const char* func, const char* source, unsigned int line) { _tag_critical_section.Lock(); Tags::iterator it = _tags.find(tag); if(it != _tags.end()) { _tag_critical_section.Unlock(); string buffer; GetOutputBuffer(buffer, tag, message, func, source, line); OutputFinalBufferToLogs(buffer, it->second); } else { //critical section is exited in the if above, so need to do it here if above wasnt executed _tag_critical_section.Unlock(); } }
void LogMgr::setDisplayFLags(const std::string& tag, unsigned char flags) { m_TagCriticalSection.lock(); if (flags != 0) { Tags::iterator findIt = m_Tags.find(tag); if (findIt == m_Tags.end()) m_Tags.insert(std::make_pair(tag, flags)); else findIt->second = flags; } else { m_Tags.erase(tag); } m_TagCriticalSection.unlock(); }
void LogMgr::log(const std::string& tag, const std::string& message, const char* funcName, const char* sourceFile, unsigned int lineNum) { m_TagCriticalSection.lock(); Tags::iterator findIt = m_Tags.find(tag); if (findIt != m_Tags.end()) { m_TagCriticalSection.unlock(); std::string buffer; getOutputBuffer(buffer, tag, message, funcName, sourceFile, lineNum); outputFinalBufferToLogs(buffer, tag, findIt->second); } else { m_TagCriticalSection.unlock(); } }
void OsmApiDbSqlChangesetFileWriter::_createTags(ConstElementPtr element) { LOG_TRACE("Creating tags for: " << element->getElementId()); QStringList tableNames = _tagTableNamesForElement(element->getElementId()); Tags tags = element->getTags(); if (_includeDebugTags) { tags.set(MetadataTags::HootStatus(), QString::number(element->getStatus().getEnum())); } LOG_VART(tags); if (element->getElementType().getEnum() == ElementType::Relation && !tags.contains("type")) { ConstRelationPtr tmp = boost::dynamic_pointer_cast<const Relation>(element); tags.appendValue("type", tmp->getType()); } for (Tags::const_iterator it = tags.begin(); it != tags.end(); ++it) { QString k = it.key(); QString v = it.value(); if (k != MetadataTags::HootHash()) { const QString currentTagValues = QString("(%1_id, k, v) VALUES (%2, '%3', '%4');\n") .arg(element->getElementId().getType().toString().toLower()) .arg(element->getElementId().getId()) .arg(k.replace('\'', "''")) .arg(v.replace('\'', "''")); const QString tagValues = QString("(%1_id, k, v, version) VALUES (%2, '%3', '%4', %5);\n") .arg(element->getElementId().getType().toString().toLower()) .arg(element->getElementId().getId()) .arg(k.replace('\'', "''")) .arg(v.replace('\'', "''")) .arg(element->getVersion()); _outputSql.write( (QString("INSERT INTO %1 ").arg(tableNames.at(0)) + currentTagValues).toUtf8()); _outputSql.write((QString("INSERT INTO %1 ").arg(tableNames.at(1)) + tagValues).toUtf8()); } } }
QString ServicesDb::_escapeTags(const Tags& tags) const { QStringList l; static QChar f1('\\'), f2('"'), f3('\''); static QChar to('_'); for (Tags::const_iterator it = tags.begin(); it != tags.end(); ++it) { // this doesn't appear to be working, but I think it is implementing the spec as described here: // http://www.postgresql.org/docs/9.0/static/hstore.html // The spec described above does seem to work on the psql command line. Curious. QString k = QString(it.key()).replace(f1, "\\\\").replace(f2, "\\\""); QString v = QString(it.value()).replace(f1, "\\\\").replace(f2, "\\\""); l << QString("\"%1\"=>\"%2\"").arg(k).arg(v); } return l.join(","); }
//------------------------------------------------------------------------------------------------------------------------------------ // This function builds up the log string and outputs it to various places based on the display flags (m_displayFlags). //------------------------------------------------------------------------------------------------------------------------------------ void LogMgr::Log(const string& tag, const string& message, const char* funcName, const char* sourceFile, unsigned int lineNum) { m_tagCriticalSection.Lock(); Tags::iterator findIt = m_tags.find(tag); if (findIt != m_tags.end()) { m_tagCriticalSection.Unlock(); string buffer; GetOutputBuffer(buffer, tag, message, funcName, sourceFile, lineNum); OutputFinalBufferToLogs(buffer, findIt->second); } else { // Critical section is exited in the if statement above, so we need to exit it here if that didn't // get executed. m_tagCriticalSection.Unlock(); } } // end LogMgr::Log()
void compareTags(const Tags& t1, const Tags& t2) { if (t1.size() != t2.size()) { LOG_WARN("t1: " << t1.toString()); LOG_WARN("t2: " << t2.toString()); CPPUNIT_ASSERT_EQUAL(t1.size(), t2.size()); } for (Tags::const_iterator it = t1.begin(); it != t1.end(); it++) { if (t1[it.key()] != t2[it.key()]) { LOG_WARN("t1: " << t1.toString()); LOG_WARN("t2: " << t2.toString()); CPPUNIT_ASSERT_EQUAL(t1[it.key()].toStdString(), t2[it.key()].toStdString()); } } }
static void find_reachable_operations_recursive(Tags &reachable, NodeOperation *op) { if (reachable.find(op) != reachable.end()) return; reachable.insert(op); for (int i = 0; i < op->getNumberOfInputSockets(); ++i) { NodeOperationInput *input = op->getInputSocket(i); if (input->isConnected()) find_reachable_operations_recursive(reachable, &input->getLink()->getOperation()); } /* associated write-buffer operations are executed as well */ if (op->isReadBufferOperation()) { ReadBufferOperation *read_op = (ReadBufferOperation *)op; MemoryProxy *memproxy = read_op->getMemoryProxy(); find_reachable_operations_recursive(reachable, memproxy->getWriteBufferOperation()); } }
void SplitNameVisitor::visit(const shared_ptr<Element>& e) { Tags& t = e->getTags(); QStringList extraNames; Tags copy = t; for (Tags::const_iterator it = copy.begin(); it != copy.end(); ++it) { const QString& k = it.key(); const QString& v = it.value(); if (v.size() > _maxSize && OsmSchema::getInstance().getCategories(it.key()).intersects(OsmSchemaCategory::name())) { QStringList l = _splitNames(v, extraNames); t.setList(k, l); } } _addExtraNames(t, extraNames); }
LogMgr::ErrorDialogResult LogMgr::error(const std::string & errorMessage, bool isFatal, const char* funcName, const char* sourceFile, unsigned int lineNum) { std::string tag = ((isFatal) ? ("FATAL") : ("ERROR")); std::string buffer; getOutputBuffer(buffer, tag, errorMessage, funcName, sourceFile, lineNum); m_TagCriticalSection.lock(); Tags::iterator findIt = m_Tags.find(tag); if (findIt != m_Tags.end()) outputFinalBufferToLogs(buffer, tag, findIt->second); m_TagCriticalSection.unlock(); int result = ::MessageBoxA(NULL, buffer.c_str(), tag.c_str(), MB_ABORTRETRYIGNORE | MB_ICONERROR | MB_DEFBUTTON3); switch (result) { case IDIGNORE: return LogMgr::LOGMGR_ERROR_IGNORE; case IDABORT: __debugbreak(); return LogMgr::LOGMGR_ERROR_RETRY; case IDRETRY: return LogMgr::LOGMGR_ERROR_RETRY; default: return LogMgr::LOGMGR_ERROR_RETRY; } }
void TagComparator::compareTextTags(const Tags& t1, const Tags& t2, double& score, double& weight) { OsmSchema& schema = OsmSchema::getInstance(); score = 1.0; weight = 0.0; for (Tags::const_iterator it = t1.begin(); it != t1.end(); it++) { const SchemaVertex& tv = schema.getTagVertex(it.key()); if (schema.isAncestor(it.key(), "abstract_name") == false && tv.valueType == Text && t2.contains(it.key())) { score *= LevenshteinDistance::score(it.value(), t2[it.key()]); weight += tv.influence; } } // if the weight is zero don't confuse things with a low score. if (weight == 0.0) { score = 1; } }
////////////////////////////////////////////////////////////////////////////////////////////// //helper for ErrorMessenger ///////////////////////////////////////////////////////////////////////////////////////////// LogMgr::ErrorDialogResult LogMgr::Error(const std::string& error_message, bool is_fatal, const char* func, const char* source, unsigned int line) { string tag = ((is_fatal) ? ("FATAL") : ("ERROR")); //buffer for final output string string buffer; GetOutputBuffer(buffer, tag, error_message, func, source, line); //write final buffer to various logs _tag_critical_section.Lock(); Tags::iterator it = _tags.find(tag); if(it != _tags.end()) OutputFinalBufferToLogs(buffer, it->second); _tag_critical_section.Unlock(); //show the dialog box int result = ::MessageBoxA(NULL, buffer.c_str(), tag.c_str(), MB_ABORTRETRYIGNORE|MB_ICONERROR|MB_DEFBUTTON3); switch(result) { case IDIGNORE: return LogMgr::LOGMGR_ERROR_IGNORE; case IDABORT: __debugbreak(); return LogMgr::LOGMGR_ERROR_ABORT; case IDRETRY: return LogMgr::LOGMGR_ERROR_RETRY; default: return LogMgr::LOGMGR_ERROR_RETRY; } }
LogManager::ErrorDialogResult LogManager::Error(const std::string& msg, bool isFatal, const char* funcName, const char* fileName, unsigned int lineNum) { std::string tag = ((isFatal) ? "FATAL" : "ERROR"); std::string buffer; GetOutputBuffer(buffer, tag, msg, funcName, fileName, lineNum); m_CritSection.Lock(); Tags::iterator findIt = m_Tags.find(tag); if (findIt != m_Tags.end()) OutputBufferToLogs(buffer, findIt->second); m_CritSection.Unlock(); int result; // show dialog box if (isFatal) result = MessageBox(nullptr, buffer.c_str(), tag.c_str(), MB_OK | MB_ICONERROR | MB_DEFBUTTON1); else result = MessageBox(nullptr, buffer.c_str(), tag.c_str(), MB_ABORTRETRYIGNORE | MB_ICONERROR | MB_DEFBUTTON3); switch (result) { case IDOK: exit(EXIT_FAILURE); case IDIGNORE: return LogManager::ERROR_DIALOG_IGNORE; case IDABORT: __debugbreak(); // Assembly instruction to open VS debugger. return LogManager::ERROR_DIALOG_ABORT; case IDRETRY: return LogManager::ERROR_DIALOG_RETRY; default: return LogManager::ERROR_DIALOG_RETRY; } }
void NodeOperationBuilder::prune_operations() { Tags reachable; for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) { NodeOperation *op = *it; /* output operations are primary executed operations */ if (op->isOutputOperation(m_context->isRendering())) find_reachable_operations_recursive(reachable, op); } /* delete unreachable operations */ Operations reachable_ops; for (Operations::const_iterator it = m_operations.begin(); it != m_operations.end(); ++it) { NodeOperation *op = *it; if (reachable.find(op) != reachable.end()) reachable_ops.push_back(op); else delete op; } /* finally replace the operations list with the pruned list */ m_operations = reachable_ops; }
void TagComparator::_mergeExactMatches(Tags& t1, Tags& t2, Tags& result) { OsmSchema& schema = OsmSchema::getInstance(); Tags t1Copy = t1; for (Tags::ConstIterator it1 = t1Copy.begin(); it1 != t1Copy.end(); ++it1) { bool keepIt = false; Tags::const_iterator it2 = t2.find(it1.key()); if (it2 != t2.end()) { if (schema.isList(it1.key(), it1.value())) { // treat the inputs as unordered lists QSet<QString> values1 = QSet<QString>::fromList(t1.getList(it1.key())); QSet<QString> values2 = QSet<QString>::fromList(t2.getList(it2.key())); values1.intersect(values2); if (values1.size() == values2.size()) { keepIt = true; } } else if (it2.value() == it1.value()) { keepIt = true; } if (keepIt) { result[it1.key()] = it1.value(); t1.remove(it1.key()); t2.remove(it1.key()); } } } }
shared_ptr<Relation> BuildingPartMergeOp::combineParts(const OsmMapPtr& map, const vector< shared_ptr<Element> >& parts) { assert(parts.size() > 0); shared_ptr<Relation> building(new Relation(parts[0]->getStatus(), map->createNextRelationId(), -1, "building")); OsmSchema& schema = OsmSchema::getInstance(); Tags& t = building->getTags(); for (size_t i = 0; i < parts.size(); i++) { building->addElement("part", parts[i]); Tags pt = parts[i]->getTags(); Tags tCopy = t; Tags names; TagComparator::getInstance().mergeNames(tCopy, pt, names); t.set(names); // go through all the tags. for (Tags::const_iterator it = pt.begin(); it != pt.end(); it++) { // ignore all keys that are building:part specific. if (_buildingPartTagNames.find(it.key()) == _buildingPartTagNames.end()) { // if the tag isn't already in the relation if (t.contains(it.key()) == false) { t[it.key()] = it.value(); } // if this is an arbitrary text value, then concatenate the values. else if (schema.isTextTag(it.key())) { t.appendValueIfUnique(it.key(), it.value()); } // if the tag is in the relation and the tags differ. else if (t[it.key()] != it.value()) { t[it.key()] = ""; } } } } // go through all the keys that were consistent for each of the parts and move them into the // relation. Tags tCopy = t; for (Tags::const_iterator it = tCopy.begin(); it != tCopy.end(); it++) { // if the value is empty, then the tag isn't needed, or it wasn't consistent between multiple // parts. if (it.value() == "") { t.remove(it.key()); } // if the tag isn't empty, remove it from each of the parts. else { for (size_t i = 0; i < parts.size(); i++) { parts[i]->getTags().remove(it.key()); } } } if (t.contains("building") == false) { t["building"] = "yes"; } // replace the building tag with building:part tags. for (size_t i = 0; i < parts.size(); i++) { parts[i]->getTags().remove("building"); parts[i]->getTags()["building:part"] = "yes"; } map->addRelation(building); return building; }
void TagComparator::mergeNames(Tags& t1, Tags& t2, Tags& result) { set<QString> altNames, nonAltNames; set<QString> toRemove; toRemove.insert("alt_name"); for (Tags::const_iterator it1 = t1.begin(); it1 != t1.end(); it1++) { if (it1.key() == "alt_name") { QStringList sl = Tags::split(it1.value()); altNames.insert(sl.begin(), sl.end()); } else { if (OsmSchema::getInstance().isAncestor(it1.key(), "abstract_name")) { result[it1.key()] = it1.value(); QStringList sl = Tags::split(it1.value()); // keep track of all the names we've used nonAltNames.insert(sl.begin(), sl.end()); toRemove.insert(it1.key()); } } } for (Tags::const_iterator it2 = t2.begin(); it2 != t2.end(); it2++) { if (it2.key() == "alt_name") { QStringList sl = Tags::split(it2.value()); altNames.insert(sl.begin(), sl.end()); } else if (result.contains(it2.key())) { const Qt::CaseSensitivity caseSensitivity = _caseSensitive ? Qt::CaseSensitive : Qt::CaseInsensitive; if (result[it2.key()].compare(it2.value(), caseSensitivity) != 0) { QStringList sl = Tags::split(it2.value()); altNames.insert(sl.begin(), sl.end()); } } else { if (OsmSchema::getInstance().isAncestor(it2.key(), "abstract_name")) { result[it2.key()] = it2.value(); QStringList sl = Tags::split(it2.value()); nonAltNames.insert(sl.begin(), sl.end()); toRemove.insert(it2.key()); } } } for (set<QString>::const_iterator it = toRemove.begin(); it != toRemove.end(); it++) { t1.remove(*it); t2.remove(*it); } // add all the altNames that don't exist in nonAltNames QStringList l; for (set<QString>::const_iterator it = altNames.begin(); it != altNames.end(); it++) { if (nonAltNames.find(*it) == nonAltNames.end()) { l.append(*it); } } if (l.size() > 0) { result.setList("alt_name", l); } }