2
2
#include " extractor/profile_properties.hpp"
3
3
4
4
#include " util/conditional_restrictions.hpp"
5
+ #include " util/integer_range.hpp"
5
6
#include " util/log.hpp"
6
7
7
8
#include < boost/algorithm/string/predicate.hpp>
8
9
#include < boost/optional/optional.hpp>
9
10
#include < boost/ref.hpp>
10
11
11
12
#include < osmium/osm.hpp>
12
- #include < osmium/tags/regex_filter.hpp>
13
13
14
14
#include < algorithm>
15
15
@@ -20,9 +20,9 @@ namespace extractor
20
20
21
21
RestrictionParser::RestrictionParser (bool use_turn_restrictions_,
22
22
bool parse_conditionals_,
23
- std::vector<std::string> &restrictions_)
23
+ const std::vector<std::string> &restrictions_)
24
24
: use_turn_restrictions(use_turn_restrictions_), parse_conditionals(parse_conditionals_),
25
- restrictions (restrictions_)
25
+ restrictions (restrictions_.begin(), restrictions_.end()), filter( false )
26
26
{
27
27
if (use_turn_restrictions)
28
28
{
@@ -40,11 +40,28 @@ RestrictionParser::RestrictionParser(bool use_turn_restrictions_,
40
40
util::Log () << " Found no turn restriction tags" ;
41
41
}
42
42
}
43
+
44
+ filter.add (true , " restriction" );
45
+ if (parse_conditionals)
46
+ {
47
+ filter.add (true , " restriction:conditional" );
48
+ for (const auto &namespaced : restrictions_)
49
+ {
50
+ filter.add (true , " restriction:" + namespaced + " :conditional" );
51
+ }
52
+ }
53
+
54
+ // Not only use restriction= but also e.g. restriction:motorcar=
55
+ // Include restriction:{mode}:conditional if flagged
56
+ for (const auto &namespaced : restrictions_)
57
+ {
58
+ filter.add (true , " restriction:" + namespaced);
59
+ }
43
60
}
44
61
45
62
/* *
46
63
* Tries to parse a relation as a turn restriction. This can fail for a number of
47
- * reasons. The return type is a boost::optional <T>.
64
+ * reasons. The return type is a std::vector <T>.
48
65
*
49
66
* Some restrictions can also be ignored: See the ```get_restrictions``` function
50
67
* in the corresponding profile. We use it for both namespacing restrictions, as in
@@ -59,31 +76,13 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
59
76
return {};
60
77
}
61
78
62
- osmium::tags::KeyFilter filter (false );
63
- filter.add (true , " restriction" );
64
- if (parse_conditionals)
65
- {
66
- filter.add (true , " restriction:conditional" );
67
- for (const auto &namespaced : restrictions)
68
- {
69
- filter.add (true , " restriction:" + namespaced + " :conditional" );
70
- }
71
- }
72
-
73
- // Not only use restriction= but also e.g. restriction:motorcar=
74
- // Include restriction:{mode}:conditional if flagged
75
- for (const auto &namespaced : restrictions)
76
- {
77
- filter.add (true , " restriction:" + namespaced);
78
- }
79
-
80
79
const osmium::TagList &tag_list = relation.tags ();
81
80
82
81
osmium::tags::KeyFilter::iterator fi_begin (filter, tag_list.begin (), tag_list.end ());
83
82
osmium::tags::KeyFilter::iterator fi_end (filter, tag_list.end (), tag_list.end ());
84
83
85
84
// if it's not a restriction, continue;
86
- if (std::distance ( fi_begin, fi_end) == 0 )
85
+ if (fi_begin == fi_end )
87
86
{
88
87
return {};
89
88
}
@@ -99,18 +98,20 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
99
98
bool is_multi_from = false ;
100
99
bool is_multi_to = false ;
101
100
101
+ std::vector<util::OpeningHours> condition;
102
+
102
103
for (; fi_begin != fi_end; ++fi_begin)
103
104
{
104
- const std::string key (fi_begin->key ());
105
- const std::string value (fi_begin->value ());
105
+ auto value = fi_begin->value ();
106
106
107
107
// documented OSM restriction tags start either with only_* or no_*;
108
108
// check and return on these values, and ignore no_*_on_red or unrecognized values
109
- if (value. find ( " only_" ) == 0 )
109
+ if (boost::algorithm::starts_with (value, " only_" ))
110
110
{
111
111
is_only_restriction = true ;
112
112
}
113
- else if (value.find (" no_" ) == 0 && !boost::algorithm::ends_with (value, " _on_red" ))
113
+ else if (boost::algorithm::starts_with (value, " no_" ) &&
114
+ !boost::algorithm::ends_with (value, " _on_red" ))
114
115
{
115
116
is_only_restriction = false ;
116
117
if (boost::algorithm::starts_with (value, " no_exit" ))
@@ -126,6 +127,25 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
126
127
{
127
128
return {};
128
129
}
130
+
131
+ if (parse_conditionals)
132
+ {
133
+ // Parse condition and add independent value/condition pairs
134
+ const auto &parsed = osrm::util::ParseConditionalRestrictions (value);
135
+
136
+ if (parsed.empty ())
137
+ continue ;
138
+
139
+ for (const auto &p : parsed)
140
+ {
141
+ std::vector<util::OpeningHours> hours = util::ParseOpeningHours (p.condition );
142
+ // found unrecognized condition, continue
143
+ if (hours.empty ())
144
+ return {};
145
+
146
+ condition = std::move (hours);
147
+ }
148
+ }
129
149
}
130
150
131
151
constexpr auto INVALID_OSM_ID = std::numeric_limits<std::uint64_t >::max ();
@@ -138,7 +158,11 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
138
158
for (const auto &member : relation.members ())
139
159
{
140
160
const char *role = member.role ();
141
- if (strcmp (" from" , role) != 0 && strcmp (" to" , role) != 0 && strcmp (" via" , role) != 0 )
161
+ const bool is_from_role = strcmp (" from" , role) == 0 ;
162
+ const bool is_to_role = strcmp (" to" , role) == 0 ;
163
+ const bool is_via_role = strcmp (" via" , role) == 0 ;
164
+
165
+ if (!is_from_role && !is_to_role && !is_via_role)
142
166
{
143
167
continue ;
144
168
}
@@ -149,28 +173,27 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
149
173
{
150
174
151
175
// Make sure nodes appear only in the role if a via node
152
- if (0 == strcmp ( " from " , role) || 0 == strcmp ( " to " , role) )
176
+ if (is_from_role || is_to_role )
153
177
{
154
178
continue ;
155
179
}
156
- BOOST_ASSERT (0 == strcmp ( " via " , role) );
180
+ BOOST_ASSERT (is_via_role );
157
181
via_node = static_cast <std::uint64_t >(member.ref ());
158
182
is_node_restriction = true ;
159
183
// set via node id
160
184
break ;
161
185
}
162
186
case osmium::item_type::way:
163
- BOOST_ASSERT (0 == strcmp (" from" , role) || 0 == strcmp (" to" , role) ||
164
- 0 == strcmp (" via" , role));
165
- if (0 == strcmp (" from" , role))
187
+ BOOST_ASSERT (is_from_role || is_to_role || is_via_role);
188
+ if (is_from_role)
166
189
{
167
190
from_ways.push_back ({static_cast <std::uint64_t >(member.ref ())});
168
191
}
169
- else if (0 == strcmp ( " to " , role) )
192
+ else if (is_to_role )
170
193
{
171
194
to_ways.push_back ({static_cast <std::uint64_t >(member.ref ())});
172
195
}
173
- else if (0 == strcmp ( " via " , role) )
196
+ else if (is_via_role )
174
197
{
175
198
via_ways.push_back ({static_cast <std::uint64_t >(member.ref ())});
176
199
is_node_restriction = false ;
@@ -185,35 +208,6 @@ RestrictionParser::TryParse(const osmium::Relation &relation) const
185
208
}
186
209
}
187
210
188
- std::vector<util::OpeningHours> condition;
189
- // parse conditional tags
190
- if (parse_conditionals)
191
- {
192
- osmium::tags::KeyFilter::iterator fi_begin (filter, tag_list.begin (), tag_list.end ());
193
- osmium::tags::KeyFilter::iterator fi_end (filter, tag_list.end (), tag_list.end ());
194
- for (; fi_begin != fi_end; ++fi_begin)
195
- {
196
- const std::string key (fi_begin->key ());
197
- const std::string value (fi_begin->value ());
198
-
199
- // Parse condition and add independent value/condition pairs
200
- const auto &parsed = osrm::util::ParseConditionalRestrictions (value);
201
-
202
- if (parsed.empty ())
203
- continue ;
204
-
205
- for (const auto &p : parsed)
206
- {
207
- std::vector<util::OpeningHours> hours = util::ParseOpeningHours (p.condition );
208
- // found unrecognized condition, continue
209
- if (hours.empty ())
210
- return {};
211
-
212
- condition = std::move (hours);
213
- }
214
- }
215
- }
216
-
217
211
std::vector<InputTurnRestriction> restriction_containers;
218
212
if (!from_ways.empty () && (via_node != INVALID_OSM_ID || !via_ways.empty ()) && !to_ways.empty ())
219
213
{
@@ -270,17 +264,25 @@ bool RestrictionParser::ShouldIgnoreRestriction(const std::string &except_tag_st
270
264
return false ;
271
265
}
272
266
273
- // Be warned, this is quadratic work here, but we assume that
274
- // only a few exceptions are actually defined.
275
- const std::regex delimiter_re (" [;][ ]*" );
276
- std::sregex_token_iterator except_tags_begin (
277
- except_tag_string.begin (), except_tag_string.end (), delimiter_re, -1 );
278
- std::sregex_token_iterator except_tags_end;
279
-
280
- return std::any_of (except_tags_begin, except_tags_end, [&](const std::string ¤t_string) {
281
- return std::end (restrictions) !=
282
- std::find (std::begin (restrictions), std::end (restrictions), current_string);
283
- });
267
+ // split `except_tag_string` by semicolon and check if any of items is in `restrictions`
268
+ std::string current_string;
269
+ for (auto index : util::irange<size_t >(0 , except_tag_string.size ()))
270
+ {
271
+ const auto ch = except_tag_string[index];
272
+ if (ch != ' ;' )
273
+ {
274
+ current_string += ch;
275
+ }
276
+ else
277
+ {
278
+ if (restrictions.find (current_string) != restrictions.end ())
279
+ {
280
+ return true ;
281
+ }
282
+ current_string.clear ();
283
+ }
284
+ }
285
+ return restrictions.find (current_string) != restrictions.end ();
284
286
}
285
287
} // namespace extractor
286
288
} // namespace osrm
0 commit comments