Libosmium  2.20.0
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-2023 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 <algorithm>
37 #include <cstring>
38 #include <iosfwd>
39 #include <regex>
40 #include <string>
41 #include <utility>
42 #include <vector>
43 
44 #ifdef __has_include
45 # if __has_include(<variant>)
46 # include <variant>
47 # ifdef __cpp_lib_variant
48 # define OSMIUM_USE_STD_VARIANT
49 # endif
50 # endif
51 #endif
52 
53 #ifndef OSMIUM_USE_STD_VARIANT
54 # include <boost/variant.hpp>
55 #endif
56 
57 
58 // std::regex isn't implemented properly in glibc++ (before the version
59 // delivered with GCC 4.9) and libc++ before the version 3.6, so the use is
60 // disabled by these checks. Checks for GLIBC were based on
61 // https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
62 // Checks for libc++ are simply based on compiler defines. This is probably
63 // not optimal but seems to work for now.
64 #if defined(__GLIBCXX__)
65 # if ((__cplusplus >= 201402L) || \
66  defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
67  defined(_GLIBCXX_REGEX_STATE_LIMIT))
68 # define OSMIUM_WITH_REGEX
69 # else
70 # pragma message("Disabling regex functionality. See source code for info.")
71 # endif
72 #elif defined(__clang__)
73 # if ((__clang_major__ > 3) || \
74  (__clang_minor__ == 3 && __clang_minor__ > 5))
75 # define OSMIUM_WITH_REGEX
76 # else
77 # pragma message("Disabling regex functionality")
78 # endif
79 #endif
80 
81 namespace osmium {
82 
86  class StringMatcher {
87 
88  public:
89 
90  // Parent class for all matcher classes. Used for enable_if check.
91  class matcher {
92  };
93 
97  class always_false : public matcher {
98 
99  public:
100 
101  static bool match(const char* /*test_string*/) noexcept {
102  return false;
103  }
104 
105  template <typename TChar, typename TTraits>
106  void print(std::basic_ostream<TChar, TTraits>& out) const {
107  out << "always_false";
108  }
109 
110  }; // class always_false
111 
115  class always_true : public matcher {
116 
117  public:
118 
119  static bool match(const char* /*test_string*/) noexcept {
120  return true;
121  }
122 
123  template <typename TChar, typename TTraits>
124  void print(std::basic_ostream<TChar, TTraits>& out) const {
125  out << "always_true";
126  }
127 
128  }; // class always_true
129 
133  class equal : public matcher {
134 
135  std::string m_str;
136 
137  public:
138 
139  explicit equal(std::string str) :
140  m_str(std::move(str)) {
141  }
142 
143  explicit equal(const char* str) :
144  m_str(str) {
145  }
146 
147  bool match(const char* test_string) const noexcept {
148  return !std::strcmp(m_str.c_str(), test_string);
149  }
150 
151  template <typename TChar, typename TTraits>
152  void print(std::basic_ostream<TChar, TTraits>& out) const {
153  out << "equal[" << m_str << ']';
154  }
155 
156  }; // class equal
157 
161  class prefix : public matcher {
162 
163  std::string m_str;
164 
165  public:
166 
167  explicit prefix(std::string str) :
168  m_str(std::move(str)) {
169  }
170 
171  explicit prefix(const char* str) :
172  m_str(str) {
173  }
174 
175  bool match(const char* test_string) const noexcept {
176  return m_str.compare(0, std::string::npos, test_string, 0, m_str.size()) == 0;
177  }
178 
179  template <typename TChar, typename TTraits>
180  void print(std::basic_ostream<TChar, TTraits>& out) const {
181  out << "prefix[" << m_str << ']';
182  }
183 
184  }; // class prefix
185 
189  class substring : public matcher {
190 
191  std::string m_str;
192 
193  public:
194 
195  explicit substring(std::string str) :
196  m_str(std::move(str)) {
197  }
198 
199  explicit substring(const char* str) :
200  m_str(str) {
201  }
202 
203  bool match(const char* test_string) const noexcept {
204  return std::strstr(test_string, m_str.c_str()) != nullptr;
205  }
206 
207  template <typename TChar, typename TTraits>
208  void print(std::basic_ostream<TChar, TTraits>& out) const {
209  out << "substring[" << m_str << ']';
210  }
211 
212  }; // class substring
213 
214 #ifdef OSMIUM_WITH_REGEX
218  class regex : public matcher {
219 
220  std::regex m_regex;
221 
222  public:
223 
224  explicit regex(std::regex regex) :
225  m_regex(std::move(regex)) {
226  }
227 
228  bool match(const char* test_string) const noexcept {
229  return std::regex_search(test_string, m_regex);
230  }
231 
232  template <typename TChar, typename TTraits>
233  void print(std::basic_ostream<TChar, TTraits>& out) const {
234  out << "regex";
235  }
236 
237  }; // class regex
238 #endif
239 
243  class list : public matcher {
244 
245  std::vector<std::string> m_strings;
246 
247  public:
248 
249  explicit list() = default;
250 
251  explicit list(std::vector<std::string> strings) :
252  m_strings(std::move(strings)) {
253  }
254 
255  list& add_string(const char* str) {
256  m_strings.emplace_back(str);
257  return *this;
258  }
259 
260  list& add_string(const std::string& str) {
261  m_strings.push_back(str);
262  return *this;
263  }
264 
265  bool match(const char* test_string) const noexcept {
266  return std::any_of(m_strings.cbegin(), m_strings.cend(),
267  [&test_string](const std::string& s){
268  return s == test_string;
269  });
270  }
271 
272  template <typename TChar, typename TTraits>
273  void print(std::basic_ostream<TChar, TTraits>& out) const {
274  out << "list[";
275  for (const auto& s : m_strings) {
276  out << '[' << s << ']';
277  }
278  out << ']';
279  }
280 
281  }; // class list
282 
283  private:
284 
285  using matcher_type =
286 #ifdef OSMIUM_USE_STD_VARIANT
287  std::variant
288 #else
289  boost::variant
290 #endif
291  <always_false,
292  always_true,
293  equal,
294  prefix,
295  substring,
296 #ifdef OSMIUM_WITH_REGEX
297  regex,
298 #endif
299  list>;
300 
302 
304 #ifndef OSMIUM_USE_STD_VARIANT
305  : public boost::static_visitor<bool>
306 #endif
307  {
308 
309  const char* m_str;
310 
311  public:
312 
313  explicit match_visitor(const char* str) noexcept :
314  m_str(str) {
315  }
316 
317  template <typename TMatcher>
318  bool operator()(const TMatcher& t) const noexcept {
319  return t.match(m_str);
320  }
321 
322  }; // class match_visitor
323 
324  template <typename TChar, typename TTraits>
326 #ifndef OSMIUM_USE_STD_VARIANT
327  : public boost::static_visitor<void>
328 #endif
329  {
330 
331  std::basic_ostream<TChar, TTraits>* m_out;
332 
333  public:
334 
335  explicit print_visitor(std::basic_ostream<TChar, TTraits>& out) :
336  m_out(&out) {
337  }
338 
339  template <typename TMatcher>
340  void operator()(const TMatcher& t) const noexcept {
341  t.print(*m_out);
342  }
343 
344  }; // class print_visitor
345 
346  public:
347 
353  }
354 
363  // cppcheck-suppress noExplicitConstructor
364  StringMatcher(bool result) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
366  if (result) {
368  }
369  }
370 
376  // cppcheck-suppress noExplicitConstructor
377  StringMatcher(const char* str) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
378  m_matcher(equal{str}) {
379  }
380 
386  // cppcheck-suppress noExplicitConstructor
387  StringMatcher(const std::string& str) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
388  m_matcher(equal{str}) {
389  }
390 
391 #ifdef OSMIUM_WITH_REGEX
397  // cppcheck-suppress noExplicitConstructor
398  StringMatcher(const std::regex& aregex) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
399  m_matcher(regex{aregex}) {
400  }
401 #endif
402 
409  // cppcheck-suppress noExplicitConstructor
410  StringMatcher(const std::vector<std::string>& strings) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
411  m_matcher(list{strings}) {
412  }
413 
421  // cppcheck-suppress noExplicitConstructor
422  template <typename TMatcher, typename X = typename std::enable_if<
423  std::is_base_of<matcher, TMatcher>::value, void>::type>
424  StringMatcher(TMatcher&& matcher) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
425  m_matcher(std::forward<TMatcher>(matcher)) {
426  }
427 
431  bool operator()(const char* str) const noexcept {
432 #ifdef OSMIUM_USE_STD_VARIANT
433  return std::visit(match_visitor{str}, m_matcher);
434 #else
435  return boost::apply_visitor(match_visitor{str}, m_matcher);
436 #endif
437  }
438 
442  bool operator()(const std::string& str) const noexcept {
443  return operator()(str.c_str());
444  }
445 
446  template <typename TChar, typename TTraits>
447  void print(std::basic_ostream<TChar, TTraits>& out) const {
448 #ifdef OSMIUM_USE_STD_VARIANT
449  std::visit(print_visitor<TChar, TTraits>{out}, m_matcher);
450 #else
451  boost::apply_visitor(print_visitor<TChar, TTraits>{out}, m_matcher);
452 #endif
453  }
454 
455  }; // class StringMatcher
456 
457  template <typename TChar, typename TTraits>
458  inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const StringMatcher& matcher) {
459  matcher.print(out);
460  return out;
461  }
462 
463 } // namespace osmium
464 
465 #undef OSMIUM_USE_STD_VARIANT
466 
467 #endif // OSMIUM_UTIL_STRING_MATCHER_HPP
Definition: string_matcher.hpp:97
static bool match(const char *) noexcept
Definition: string_matcher.hpp:101
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:106
Definition: string_matcher.hpp:115
static bool match(const char *) noexcept
Definition: string_matcher.hpp:119
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:124
Definition: string_matcher.hpp:133
equal(const char *str)
Definition: string_matcher.hpp:143
std::string m_str
Definition: string_matcher.hpp:135
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:147
equal(std::string str)
Definition: string_matcher.hpp:139
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:152
Definition: string_matcher.hpp:243
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:265
list & add_string(const std::string &str)
Definition: string_matcher.hpp:260
std::vector< std::string > m_strings
Definition: string_matcher.hpp:245
list & add_string(const char *str)
Definition: string_matcher.hpp:255
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:273
list(std::vector< std::string > strings)
Definition: string_matcher.hpp:251
Definition: string_matcher.hpp:307
match_visitor(const char *str) noexcept
Definition: string_matcher.hpp:313
const char * m_str
Definition: string_matcher.hpp:309
bool operator()(const TMatcher &t) const noexcept
Definition: string_matcher.hpp:318
Definition: string_matcher.hpp:91
Definition: string_matcher.hpp:161
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:180
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:175
prefix(std::string str)
Definition: string_matcher.hpp:167
std::string m_str
Definition: string_matcher.hpp:163
prefix(const char *str)
Definition: string_matcher.hpp:171
Definition: string_matcher.hpp:329
print_visitor(std::basic_ostream< TChar, TTraits > &out)
Definition: string_matcher.hpp:335
std::basic_ostream< TChar, TTraits > * m_out
Definition: string_matcher.hpp:331
void operator()(const TMatcher &t) const noexcept
Definition: string_matcher.hpp:340
Definition: string_matcher.hpp:189
std::string m_str
Definition: string_matcher.hpp:191
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:208
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:203
substring(std::string str)
Definition: string_matcher.hpp:195
substring(const char *str)
Definition: string_matcher.hpp:199
Definition: string_matcher.hpp:86
StringMatcher()
Definition: string_matcher.hpp:351
StringMatcher(const std::vector< std::string > &strings)
Definition: string_matcher.hpp:410
StringMatcher(const char *str)
Definition: string_matcher.hpp:377
bool operator()(const char *str) const noexcept
Definition: string_matcher.hpp:431
boost::variant< always_false, always_true, equal, prefix, substring, list > matcher_type
Definition: string_matcher.hpp:299
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:447
bool operator()(const std::string &str) const noexcept
Definition: string_matcher.hpp:442
matcher_type m_matcher
Definition: string_matcher.hpp:301
StringMatcher(TMatcher &&matcher)
Definition: string_matcher.hpp:424
StringMatcher(bool result)
Definition: string_matcher.hpp:364
StringMatcher(const std::string &str)
Definition: string_matcher.hpp:387
type
Definition: entity_bits.hpp:63
Namespace for everything in the Osmium library.
Definition: assembler.hpp:53
std::basic_ostream< TChar, TTraits > & operator<<(std::basic_ostream< TChar, TTraits > &out, const item_type item_type)
Definition: item_type.hpp:187
Definition: location.hpp:555