11#include <QXmlStreamReader>
18OscParser::OscParser(
DataSet* dataSet)
23void OscParser::readFromIODevice(
QIODevice *io)
26 while (!reader.atEnd() && !reader.hasError()) {
31 if (reader.name() ==
"create"_L1) {
33 }
else if (reader.name() ==
"modify"_L1) {
35 }
else if (reader.name() ==
"delete"_L1){
40 if (reader.hasError()) {
41 m_error = reader.errorString();
46void OscParser::assignNewId(T &elem, std::unordered_map<OSM::Id, OSM::Id> &idMap)
49 idMap[elem.id] = newId;
53OSM::Id OscParser::mapId(
OSM::Id id,
const std::unordered_map<OSM::Id, OSM::Id> &idMap)
55 auto it = idMap.find(
id);
56 return it == idMap.end() ? id : (*it).second;
59void OscParser::mapNodeIds(
OSM::Way &way)
const
61 for (
auto &
id : way.nodes) {
62 id = mapId(
id, m_nodeIdMap);
68 for (
auto &member : rel.members) {
69 switch (member.type()) {
73 member.id = mapId(member.id, m_nodeIdMap);
76 member.id = mapId(member.id, m_wayIdMap);
78 case OSM::Type::Relation:
79 member.id = mapId(member.id, m_relIdMap);
95 if (reader.
name() ==
"node"_L1) {
96 auto node = parseNode(reader);
97 assignNewId(node, m_nodeIdMap);
99 }
else if (reader.
name() ==
"way"_L1) {
100 auto way = parseWay(reader);
101 assignNewId(way, m_wayIdMap);
103 addWay(std::move(way));
104 }
else if (reader.
name() ==
"releation"_L1) {
105 auto rel = parseRelation(reader);
106 assignNewId(rel, m_relIdMap);
108 addRelation(std::move(rel));
125 if (reader.
name() ==
"node"_L1) {
126 auto modifiedNode = parseNode(reader);
127 if (
const auto it = std::lower_bound(m_dataSet->nodes.begin(), m_dataSet->nodes.end(), modifiedNode.id); it != m_dataSet->nodes.end() && (*it).id == modifiedNode.id) {
128 if (modifiedNode.coordinate.isValid()) {
129 (*it).coordinate = modifiedNode.coordinate;
131 if (!modifiedNode.tags.empty()) {
132 (*it).tags = std::move(modifiedNode.tags);
135 qDebug() <<
"modified node not in data set:" << modifiedNode.url();
137 }
else if (reader.
name() ==
"way"_L1) {
138 auto modifiedWay = parseWay(reader);
139 if (
const auto it = std::lower_bound(m_dataSet->ways.begin(), m_dataSet->ways.end(), modifiedWay.id); it != m_dataSet->ways.end() && (*it).id == modifiedWay.id) {
140 if (!modifiedWay.tags.empty()) {
141 (*it).tags = std::move(modifiedWay.tags);
143 if (!modifiedWay.nodes.empty()) {
144 mapNodeIds(modifiedWay);
145 (*it).nodes = std::move(modifiedWay.nodes);
148 qDebug() <<
"modified way not in data set:" << modifiedWay.url();
150 }
else if (reader.
name() ==
"releation"_L1) {
151 auto modifiedRel = parseRelation(reader);
152 if (
const auto it = std::lower_bound(m_dataSet->relations.begin(), m_dataSet->relations.end(), modifiedRel.id); it != m_dataSet->relations.end() && (*it).id == modifiedRel.id) {
153 if (!modifiedRel.tags.empty()) {
154 (*it).tags = std::move(modifiedRel.tags);
156 if (!modifiedRel.members.empty()) {
157 mapMemberIds(modifiedRel);
158 (*it).members = std::move(modifiedRel.members);
161 qDebug() <<
"modified relation not in data set:" << modifiedRel.url();
182 if (reader.
name() ==
"node"_L1) {
183 const auto node = parseNode(reader);
184 if (
const auto it = std::lower_bound(m_dataSet->nodes.begin(), m_dataSet->nodes.end(), node.id); it != m_dataSet->nodes.end() && (*it).id == node.id) {
187 qDebug() <<
"deleted node not in data set:" << node.url();
189 }
else if (reader.
name() ==
"way"_L1) {
190 const auto way = parseWay(reader);
191 if (
const auto it = std::lower_bound(m_dataSet->ways.begin(), m_dataSet->ways.end(), way.id); it != m_dataSet->ways.end() && (*it).id == way.id) {
194 qDebug() <<
"modified way not in data set:" << way.url();
196 }
else if (reader.
name() ==
"releation"_L1) {
197 const auto rel = parseRelation(reader);
198 if (
const auto it = std::lower_bound(m_dataSet->relations.begin(), m_dataSet->relations.end(), rel.id); it != m_dataSet->relations.end() && (*it).id == rel.id) {
201 qDebug() <<
"modified relation not in data set:" << rel.url();
void addNode(OSM::Node &&node)
Add read elements to the merge buffer if set, or the dataset otherwise.
A set of nodes, ways and relations.
Id nextInternalId() const
Create a unique id for internal use (ie.
Low-level types and functions to work with raw OSM data as efficiently as possible.
int64_t Id
OSM element identifier.
bool hasError() const const
QStringView name() const const
void skipCurrentElement()
TokenType tokenType() const const