#include "rapidxml.hpp" #include #include namespace rx = rapidxml; inline bool is_highway_crossing(rx::xml_node<>* tag_node) { rx::xml_attribute<>* k = tag_node->first_attribute(); if (!k) return false; rx::xml_attribute<>* v = k->next_attribute(); if (!v) return false; return std::strcmp(k->value(), "highway") == 0 && std::strcmp(v->value(), "crossing") == 0; } size_t count_highway_crossings(char* buffer, size_t len) { rx::xml_document<> doc; try { doc.parse(buffer); } catch (const rx::parse_error&) { return 0; } size_t count = 0; rx::xml_node<>* osm = doc.first_node("osm"); if (!osm) return count; for (rx::xml_node<>* node = osm->first_node("node"); node; node = node->next_sibling("node")) { for (rx::xml_node<>* tag = node->first_node("tag"); tag; tag = tag->next_sibling("tag")) { if (is_highway_crossing(tag)) ++count; } } return count; } size_t count_highway_crossings_cheat_and_early_out(char* buffer, size_t len) { rx::xml_document<> doc; try { doc.parse(buffer); } catch (const rx::parse_error&) { return 0; } size_t count = 0; rx::xml_node<>* osm = doc.first_node("osm"); if (!osm) return count; // Equivalent to iterating over all children and stopping at "way". // next_sibling() avoids inspecting unrelated nodes between elements. for (rx::xml_node<>* top = osm->first_node(); top; top = top->next_sibling()) { if (std::strcmp(top->name(), "way") == 0) break; for (rx::xml_node<>* tag = top->first_node("tag"); tag; tag = tag->next_sibling("tag")) { if (is_highway_crossing(tag)) ++count; } } return count; }