Libosmium  2.15.3
Fast and flexible C++ library for working with OpenStreetMap data
string_matcher.hpp
Go to the documentation of this file.
1 #ifndef OSMIUM_UTIL_STRING_MATCHER_HPP
2 #define OSMIUM_UTIL_STRING_MATCHER_HPP
3 
4 /*
5 
6 This file is part of Osmium (https://osmcode.org/libosmium).
7 
8 Copyright 2013-2019 Jochen Topf <jochen@topf.org> and others (see README).
9 
10 Boost Software License - Version 1.0 - August 17th, 2003
11 
12 Permission is hereby granted, free of charge, to any person or organization
13 obtaining a copy of the software and accompanying documentation covered by
14 this license (the "Software") to use, reproduce, display, distribute,
15 execute, and transmit the Software, and to prepare derivative works of the
16 Software, and to permit third-parties to whom the Software is furnished to
17 do so, all subject to the following:
18 
19 The copyright notices in the Software and this entire statement, including
20 the above license grant, this restriction and the following disclaimer,
21 must be included in all copies of the Software, in whole or in part, and
22 all derivative works of the Software, unless such copies or derivative
23 works are solely in the form of machine-executable object code generated by
24 a source language processor.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32 DEALINGS IN THE SOFTWARE.
33 
34 */
35 
36 #include <boost/variant.hpp>
37 
38 #include <cstring>
39 #include <iosfwd>
40 #include <regex>
41 #include <string>
42 #include <utility>
43 #include <vector>
44 
45 // std::regex isn't implemented properly in glibc++ (before the version
46 // delivered with GCC 4.9) and libc++ before the version 3.6, so the use is
47 // disabled by these checks. Checks for GLIBC were based on
48 // https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
49 // Checks for libc++ are simply based on compiler defines. This is probably
50 // not optimal but seems to work for now.
51 #if defined(__GLIBCXX__)
52 # if ((__cplusplus >= 201402L) || \
53  defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
54  defined(_GLIBCXX_REGEX_STATE_LIMIT))
55 # define OSMIUM_WITH_REGEX
56 # else
57 # pragma message("Disabling regex functionality. See source code for info.")
58 # endif
59 #elif defined(__clang__)
60 # if ((__clang_major__ > 3) || \
61  (__clang_minor__ == 3 && __clang_minor__ > 5))
62 # define OSMIUM_WITH_REGEX
63 # else
64 # pragma message("Disabling regex functionality")
65 # endif
66 #endif
67 
68 namespace osmium {
69 
73  class StringMatcher {
74 
75  public:
76 
77  // Parent class for all matcher classes. Used for enable_if check.
78  class matcher {
79  };
80 
84  class always_false : public matcher {
85 
86  public:
87 
88  bool match(const char* /*test_string*/) const noexcept {
89  return false;
90  }
91 
92  template <typename TChar, typename TTraits>
93  void print(std::basic_ostream<TChar, TTraits>& out) const {
94  out << "always_false";
95  }
96 
97  }; // class always_false
98 
102  class always_true : public matcher {
103 
104  public:
105 
106  bool match(const char* /*test_string*/) const noexcept {
107  return true;
108  }
109 
110  template <typename TChar, typename TTraits>
111  void print(std::basic_ostream<TChar, TTraits>& out) const {
112  out << "always_true";
113  }
114 
115  }; // class always_true
116 
120  class equal : public matcher {
121 
122  std::string m_str;
123 
124  public:
125 
126  explicit equal(std::string str) :
127  m_str(std::move(str)) {
128  }
129 
130  explicit equal(const char* str) :
131  m_str(str) {
132  }
133 
134  bool match(const char* test_string) const noexcept {
135  return !std::strcmp(m_str.c_str(), test_string);
136  }
137 
138  template <typename TChar, typename TTraits>
139  void print(std::basic_ostream<TChar, TTraits>& out) const {
140  out << "equal[" << m_str << ']';
141  }
142 
143  }; // class equal
144 
148  class prefix : public matcher {
149 
150  std::string m_str;
151 
152  public:
153 
154  explicit prefix(std::string str) :
155  m_str(std::move(str)) {
156  }
157 
158  explicit prefix(const char* str) :
159  m_str(str) {
160  }
161 
162  bool match(const char* test_string) const noexcept {
163  return m_str.compare(0, std::string::npos, test_string, 0, m_str.size()) == 0;
164  }
165 
166  template <typename TChar, typename TTraits>
167  void print(std::basic_ostream<TChar, TTraits>& out) const {
168  out << "prefix[" << m_str << ']';
169  }
170 
171  }; // class prefix
172 
176  class substring : public matcher {
177 
178  std::string m_str;
179 
180  public:
181 
182  explicit substring(std::string str) :
183  m_str(std::move(str)) {
184  }
185 
186  explicit substring(const char* str) :
187  m_str(str) {
188  }
189 
190  bool match(const char* test_string) const noexcept {
191  return std::strstr(test_string, m_str.c_str()) != nullptr;
192  }
193 
194  template <typename TChar, typename TTraits>
195  void print(std::basic_ostream<TChar, TTraits>& out) const {
196  out << "substring[" << m_str << ']';
197  }
198 
199  }; // class substring
200 
201 #ifdef OSMIUM_WITH_REGEX
202 
205  class regex : public matcher {
206 
207  std::regex m_regex;
208 
209  public:
210 
211  explicit regex(std::regex regex) :
212  m_regex(std::move(regex)) {
213  }
214 
215  bool match(const char* test_string) const noexcept {
216  return std::regex_search(test_string, m_regex);
217  }
218 
219  template <typename TChar, typename TTraits>
220  void print(std::basic_ostream<TChar, TTraits>& out) const {
221  out << "regex";
222  }
223 
224  }; // class regex
225 #endif
226 
230  class list : public matcher {
231 
232  std::vector<std::string> m_strings;
233 
234  public:
235 
236  explicit list() = default;
237 
238  explicit list(std::vector<std::string> strings) :
239  m_strings(std::move(strings)) {
240  }
241 
242  list& add_string(const char* str) {
243  m_strings.emplace_back(str);
244  return *this;
245  }
246 
247  list& add_string(const std::string& str) {
248  m_strings.push_back(str);
249  return *this;
250  }
251 
252  bool match(const char* test_string) const noexcept {
253  for (const auto& s : m_strings) {
254  if (!std::strcmp(s.c_str(), test_string)) {
255  return true;
256  }
257  }
258  return false;
259 
260  }
261 
262  template <typename TChar, typename TTraits>
263  void print(std::basic_ostream<TChar, TTraits>& out) const {
264  out << "list[";
265  for (const auto& s : m_strings) {
266  out << '[' << s << ']';
267  }
268  out << ']';
269  }
270 
271  }; // class list
272 
273  private:
274 
275  using matcher_type = boost::variant<always_false,
276  always_true,
277  equal,
278  prefix,
279  substring,
280 #ifdef OSMIUM_WITH_REGEX
281  regex,
282 #endif
284 
286 
287  class match_visitor : public boost::static_visitor<bool> {
288 
289  const char* m_str;
290 
291  public:
292 
293  explicit match_visitor(const char* str) noexcept :
294  m_str(str) {
295  }
296 
297  template <typename TMatcher>
298  bool operator()(const TMatcher& t) const noexcept {
299  return t.match(m_str);
300  }
301 
302  }; // class match_visitor
303 
304  template <typename TChar, typename TTraits>
305  class print_visitor : public boost::static_visitor<void> {
306 
307  std::basic_ostream<TChar, TTraits>* m_out;
308 
309  public:
310 
311  explicit print_visitor(std::basic_ostream<TChar, TTraits>& out) :
312  m_out(&out) {
313  }
314 
315  template <typename TMatcher>
316  void operator()(const TMatcher& t) const noexcept {
317  t.print(*m_out);
318  }
319 
320  }; // class print_visitor
321 
322  public:
323 
328  m_matcher(always_false{}) {
329  }
330 
339  StringMatcher(bool result) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
340  m_matcher(always_false{}) {
341  if (result) {
342  m_matcher = always_true{};
343  }
344  }
345 
351  StringMatcher(const char* str) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
352  m_matcher(equal{str}) {
353  }
354 
360  StringMatcher(const std::string& str) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
361  m_matcher(equal{str}) {
362  }
363 
364 #ifdef OSMIUM_WITH_REGEX
365 
370  StringMatcher(const std::regex& aregex) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
371  m_matcher(regex{aregex}) {
372  }
373 #endif
374 
381  StringMatcher(const std::vector<std::string>& strings) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
382  m_matcher(list{strings}) {
383  }
384 
392  template <typename TMatcher, typename X = typename std::enable_if<
393  std::is_base_of<matcher, TMatcher>::value, void>::type>
394  StringMatcher(TMatcher&& matcher) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
395  m_matcher(std::forward<TMatcher>(matcher)) {
396  }
397 
401  bool operator()(const char* str) const noexcept {
402  return boost::apply_visitor(match_visitor{str}, m_matcher);
403  }
404 
408  bool operator()(const std::string& str) const noexcept {
409  return operator()(str.c_str());
410  }
411 
412  template <typename TChar, typename TTraits>
413  void print(std::basic_ostream<TChar, TTraits>& out) const {
414  boost::apply_visitor(print_visitor<TChar, TTraits>{out}, m_matcher);
415  }
416 
417  }; // class StringMatcher
418 
419  template <typename TChar, typename TTraits>
420  inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const StringMatcher& matcher) {
421  matcher.print(out);
422  return out;
423  }
424 
425 } // namespace osmium
426 
427 #endif // OSMIUM_UTIL_STRING_MATCHER_HPP
equal(const char *str)
Definition: string_matcher.hpp:130
Definition: string_matcher.hpp:230
StringMatcher(TMatcher &&matcher)
Definition: string_matcher.hpp:394
bool operator()(const char *str) const noexcept
Definition: string_matcher.hpp:401
type
Definition: entity_bits.hpp:63
Definition: string_matcher.hpp:102
StringMatcher(const std::string &str)
Definition: string_matcher.hpp:360
boost::variant< always_false, always_true, equal, prefix, substring, list > matcher_type
Definition: string_matcher.hpp:283
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:111
list & add_string(const char *str)
Definition: string_matcher.hpp:242
Definition: string_matcher.hpp:305
print_visitor(std::basic_ostream< TChar, TTraits > &out)
Definition: string_matcher.hpp:311
Definition: location.hpp:550
StringMatcher(const std::vector< std::string > &strings)
Definition: string_matcher.hpp:381
equal(std::string str)
Definition: string_matcher.hpp:126
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:252
Definition: string_matcher.hpp:120
bool match(const char *) const noexcept
Definition: string_matcher.hpp:88
StringMatcher()
Definition: string_matcher.hpp:327
Definition: string_matcher.hpp:78
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:413
Definition: string_matcher.hpp:176
match_visitor(const char *str) noexcept
Definition: string_matcher.hpp:293
std::vector< std::string > m_strings
Definition: string_matcher.hpp:232
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:263
Definition: string_matcher.hpp:73
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:93
bool operator()(const TMatcher &t) const noexcept
Definition: string_matcher.hpp:298
std::string m_str
Definition: string_matcher.hpp:150
Definition: string_matcher.hpp:148
Definition: string_matcher.hpp:84
StringMatcher(const char *str)
Definition: string_matcher.hpp:351
substring(std::string str)
Definition: string_matcher.hpp:182
StringMatcher(bool result)
Definition: string_matcher.hpp:339
list & add_string(const std::string &str)
Definition: string_matcher.hpp:247
prefix(const char *str)
Definition: string_matcher.hpp:158
substring(const char *str)
Definition: string_matcher.hpp:186
matcher_type m_matcher
Definition: string_matcher.hpp:285
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:139
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:190
std::basic_ostream< TChar, TTraits > * m_out
Definition: string_matcher.hpp:307
const char * m_str
Definition: string_matcher.hpp:289
Definition: string_matcher.hpp:287
bool match(const char *) const noexcept
Definition: string_matcher.hpp:106
std::string m_str
Definition: string_matcher.hpp:178
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:167
prefix(std::string str)
Definition: string_matcher.hpp:154
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:195
bool operator()(const std::string &str) const noexcept
Definition: string_matcher.hpp:408
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:162
list(std::vector< std::string > strings)
Definition: string_matcher.hpp:238
std::string m_str
Definition: string_matcher.hpp:122
void operator()(const TMatcher &t) const noexcept
Definition: string_matcher.hpp:316
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:134