summaryrefslogtreecommitdiff
path: root/benchmarks/RapidXML/count_highway_crossings.cpp
blob: 6d0ecf607457440b492c3c8315932b0a29790e39 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "rapidxml.hpp"
#include <cstddef>
#include <cstring>

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<rx::parse_no_data_nodes | rx::parse_no_element_values>(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<rx::parse_no_data_nodes | rx::parse_no_element_values>(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;
}