1 #ifndef OSRM_GUIDANCE_PARSING_TOOLKIT_HPP_
2 #define OSRM_GUIDANCE_PARSING_TOOLKIT_HPP_
3
4 #include <cstdint>
5 #include <string>
6
7 #include <boost/algorithm/string.hpp>
8 #include <boost/tokenizer.hpp>
9
10 #include "util/attributes.hpp"
11
12 namespace osrm
13 {
14 namespace extractor
15 {
16 namespace guidance
17 {
18
19 // Public service vehicle lanes and similar can introduce additional lanes into the lane string that
20 // are not specifically marked for left/right turns. This function can be used from the profile to
21 // trim the lane string appropriately
22 //
23 // left|throught|
24 // in combination with lanes:psv:forward=1
25 // will be corrected to left|throught, since the final lane is not drivable.
26 // This is in contrast to a situation with lanes:psv:forward=0 (or not set) where left|through|
27 // represents left|through|through
28 OSRM_ATTR_WARN_UNUSED
29 inline std::string
trimLaneString(std::string lane_string,std::int32_t count_left,std::int32_t count_right)30 trimLaneString(std::string lane_string, std::int32_t count_left, std::int32_t count_right)
31 {
32 if (count_left)
33 {
34 bool sane = count_left < static_cast<std::int32_t>(lane_string.size());
35 for (std::int32_t i = 0; i < count_left; ++i)
36 // this is adjusted for our fake pipe. The moment cucumber can handle multiple escaped
37 // pipes, the '&' part can be removed
38 if (lane_string[i] != '|')
39 {
40 sane = false;
41 break;
42 }
43
44 if (sane)
45 {
46 lane_string.erase(lane_string.begin(), lane_string.begin() + count_left);
47 }
48 }
49 if (count_right)
50 {
51 bool sane = count_right < static_cast<std::int32_t>(lane_string.size());
52 for (auto itr = lane_string.rbegin();
53 itr != lane_string.rend() && itr != lane_string.rbegin() + count_right;
54 ++itr)
55 {
56 if (*itr != '|')
57 {
58 sane = false;
59 break;
60 }
61 }
62 if (sane)
63 lane_string.resize(lane_string.size() - count_right);
64 }
65 return lane_string;
66 }
67
68 // https://github.com/Project-OSRM/osrm-backend/issues/2638
69 // It can happen that some lanes are not drivable by car. Here we handle this tagging scheme
70 // (vehicle:lanes) to filter out not-allowed roads
71 // lanes=3
72 // turn:lanes=left|through|through|right
73 // vehicle:lanes=yes|yes|no|yes
74 // bicycle:lanes=yes|no|designated|yes
75 OSRM_ATTR_WARN_UNUSED
applyAccessTokens(std::string lane_string,const std::string & access_tokens)76 inline std::string applyAccessTokens(std::string lane_string, const std::string &access_tokens)
77 {
78 typedef boost::tokenizer<boost::char_separator<char>> tokenizer;
79 boost::char_separator<char> sep("|", "", boost::keep_empty_tokens);
80 tokenizer tokens(lane_string, sep);
81 tokenizer access(access_tokens, sep);
82
83 // strings don't match, don't do anything
84 if (std::distance(std::begin(tokens), std::end(tokens)) !=
85 std::distance(std::begin(access), std::end(access)))
86 return lane_string;
87
88 std::string result_string = "";
89 const static std::string yes = "yes";
90
91 for (auto token_itr = std::begin(tokens), access_itr = std::begin(access);
92 token_itr != std::end(tokens);
93 ++token_itr, ++access_itr)
94 {
95 if (*access_itr == yes)
96 {
97 // we have to add this in front, because the next token could be invalid. Doing this on
98 // non-empty strings makes sure that the token string will be valid in the end
99 if (!result_string.empty())
100 result_string += '|';
101
102 result_string += *token_itr;
103 }
104 }
105 return result_string;
106 }
107
108 } // namespace guidance
109 } // namespace extractor
110 } // namespace osrm
111
112 #endif // OSRM_GUIDANCE_PARSING_TOOLKIT_HPP_
113