Libosmium  2.17.1
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-2021 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 <algorithm>
39 #include <cstring>
40 #include <iosfwd>
41 #include <regex>
42 #include <string>
43 #include <utility>
44 #include <vector>
45 
46 // std::regex isn't implemented properly in glibc++ (before the version
47 // delivered with GCC 4.9) and libc++ before the version 3.6, so the use is
48 // disabled by these checks. Checks for GLIBC were based on
49 // https://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
50 // Checks for libc++ are simply based on compiler defines. This is probably
51 // not optimal but seems to work for now.
52 #if defined(__GLIBCXX__)
53 # if ((__cplusplus >= 201402L) || \
54  defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
55  defined(_GLIBCXX_REGEX_STATE_LIMIT))
56 # define OSMIUM_WITH_REGEX
57 # else
58 # pragma message("Disabling regex functionality. See source code for info.")
59 # endif
60 #elif defined(__clang__)
61 # if ((__clang_major__ > 3) || \
62  (__clang_minor__ == 3 && __clang_minor__ > 5))
63 # define OSMIUM_WITH_REGEX
64 # else
65 # pragma message("Disabling regex functionality")
66 # endif
67 #endif
68 
69 namespace osmium {
70 
74  class StringMatcher {
75 
76  public:
77 
78  // Parent class for all matcher classes. Used for enable_if check.
79  class matcher {
80  };
81 
85  class always_false : public matcher {
86 
87  public:
88 
89  static bool match(const char* /*test_string*/) noexcept {
90  return false;
91  }
92 
93  template <typename TChar, typename TTraits>
94  void print(std::basic_ostream<TChar, TTraits>& out) const {
95  out << "always_false";
96  }
97 
98  }; // class always_false
99 
103  class always_true : public matcher {
104 
105  public:
106 
107  static bool match(const char* /*test_string*/) noexcept {
108  return true;
109  }
110 
111  template <typename TChar, typename TTraits>
112  void print(std::basic_ostream<TChar, TTraits>& out) const {
113  out << "always_true";
114  }
115 
116  }; // class always_true
117 
121  class equal : public matcher {
122 
123  std::string m_str;
124 
125  public:
126 
127  explicit equal(std::string str) :
128  m_str(std::move(str)) {
129  }
130 
131  explicit equal(const char* str) :
132  m_str(str) {
133  }
134 
135  bool match(const char* test_string) const noexcept {
136  return !std::strcmp(m_str.c_str(), test_string);
137  }
138 
139  template <typename TChar, typename TTraits>
140  void print(std::basic_ostream<TChar, TTraits>& out) const {
141  out << "equal[" << m_str << ']';
142  }
143 
144  }; // class equal
145 
149  class prefix : public matcher {
150 
151  std::string m_str;
152 
153  public:
154 
155  explicit prefix(std::string str) :
156  m_str(std::move(str)) {
157  }
158 
159  explicit prefix(const char* str) :
160  m_str(str) {
161  }
162 
163  bool match(const char* test_string) const noexcept {
164  return m_str.compare(0, std::string::npos, test_string, 0, m_str.size()) == 0;
165  }
166 
167  template <typename TChar, typename TTraits>
168  void print(std::basic_ostream<TChar, TTraits>& out) const {
169  out << "prefix[" << m_str << ']';
170  }
171 
172  }; // class prefix
173 
177  class substring : public matcher {
178 
179  std::string m_str;
180 
181  public:
182 
183  explicit substring(std::string str) :
184  m_str(std::move(str)) {
185  }
186 
187  explicit substring(const char* str) :
188  m_str(str) {
189  }
190 
191  bool match(const char* test_string) const noexcept {
192  return std::strstr(test_string, m_str.c_str()) != nullptr;
193  }
194 
195  template <typename TChar, typename TTraits>
196  void print(std::basic_ostream<TChar, TTraits>& out) const {
197  out << "substring[" << m_str << ']';
198  }
199 
200  }; // class substring
201 
202 #ifdef OSMIUM_WITH_REGEX
206  class regex : public matcher {
207 
208  std::regex m_regex;
209 
210  public:
211 
212  explicit regex(std::regex regex) :
213  m_regex(std::move(regex)) {
214  }
215 
216  bool match(const char* test_string) const noexcept {
217  return std::regex_search(test_string, m_regex);
218  }
219 
220  template <typename TChar, typename TTraits>
221  void print(std::basic_ostream<TChar, TTraits>& out) const {
222  out << "regex";
223  }
224 
225  }; // class regex
226 #endif
227 
231  class list : public matcher {
232 
233  std::vector<std::string> m_strings;
234 
235  public:
236 
237  explicit list() = default;
238 
239  explicit list(std::vector<std::string> strings) :
240  m_strings(std::move(strings)) {
241  }
242 
243  list& add_string(const char* str) {
244  m_strings.emplace_back(str);
245  return *this;
246  }
247 
248  list& add_string(const std::string& str) {
249  m_strings.push_back(str);
250  return *this;
251  }
252 
253  bool match(const char* test_string) const noexcept {
254  return std::any_of(m_strings.cbegin(), m_strings.cend(),
255  [&test_string](const std::string& s){
256  return s == test_string;
257  });
258  }
259 
260  template <typename TChar, typename TTraits>
261  void print(std::basic_ostream<TChar, TTraits>& out) const {
262  out << "list[";
263  for (const auto& s : m_strings) {
264  out << '[' << s << ']';
265  }
266  out << ']';
267  }
268 
269  }; // class list
270 
271  private:
272 
273  using matcher_type = boost::variant<always_false,
274  always_true,
275  equal,
276  prefix,
277  substring,
278 #ifdef OSMIUM_WITH_REGEX
279  regex,
280 #endif
281  list>;
282 
284 
285  class match_visitor : public boost::static_visitor<bool> {
286 
287  const char* m_str;
288 
289  public:
290 
291  explicit match_visitor(const char* str) noexcept :
292  m_str(str) {
293  }
294 
295  template <typename TMatcher>
296  bool operator()(const TMatcher& t) const noexcept {
297  return t.match(m_str);
298  }
299 
300  }; // class match_visitor
301 
302  template <typename TChar, typename TTraits>
303  class print_visitor : public boost::static_visitor<void> {
304 
305  std::basic_ostream<TChar, TTraits>* m_out;
306 
307  public:
308 
309  explicit print_visitor(std::basic_ostream<TChar, TTraits>& out) :
310  m_out(&out) {
311  }
312 
313  template <typename TMatcher>
314  void operator()(const TMatcher& t) const noexcept {
315  t.print(*m_out);
316  }
317 
318  }; // class print_visitor
319 
320  public:
321 
327  }
328 
337  // cppcheck-suppress noExplicitConstructor
338  StringMatcher(bool result) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
340  if (result) {
342  }
343  }
344 
350  // cppcheck-suppress noExplicitConstructor
351  StringMatcher(const char* str) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
352  m_matcher(equal{str}) {
353  }
354 
360  // cppcheck-suppress noExplicitConstructor
361  StringMatcher(const std::string& str) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
362  m_matcher(equal{str}) {
363  }
364 
365 #ifdef OSMIUM_WITH_REGEX
371  // cppcheck-suppress noExplicitConstructor
372  StringMatcher(const std::regex& aregex) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
373  m_matcher(regex{aregex}) {
374  }
375 #endif
376 
383  // cppcheck-suppress noExplicitConstructor
384  StringMatcher(const std::vector<std::string>& strings) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
385  m_matcher(list{strings}) {
386  }
387 
395  // cppcheck-suppress noExplicitConstructor
396  template <typename TMatcher, typename X = typename std::enable_if<
397  std::is_base_of<matcher, TMatcher>::value, void>::type>
398  StringMatcher(TMatcher&& matcher) : // NOLINT(google-explicit-constructor, hicpp-explicit-conversions)
399  m_matcher(std::forward<TMatcher>(matcher)) {
400  }
401 
405  bool operator()(const char* str) const noexcept {
406  return boost::apply_visitor(match_visitor{str}, m_matcher);
407  }
408 
412  bool operator()(const std::string& str) const noexcept {
413  return operator()(str.c_str());
414  }
415 
416  template <typename TChar, typename TTraits>
417  void print(std::basic_ostream<TChar, TTraits>& out) const {
418  boost::apply_visitor(print_visitor<TChar, TTraits>{out}, m_matcher);
419  }
420 
421  }; // class StringMatcher
422 
423  template <typename TChar, typename TTraits>
424  inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const StringMatcher& matcher) {
425  matcher.print(out);
426  return out;
427  }
428 
429 } // namespace osmium
430 
431 #endif // OSMIUM_UTIL_STRING_MATCHER_HPP
Definition: string_matcher.hpp:85
static bool match(const char *) noexcept
Definition: string_matcher.hpp:89
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:94
Definition: string_matcher.hpp:103
static bool match(const char *) noexcept
Definition: string_matcher.hpp:107
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:112
Definition: string_matcher.hpp:121
equal(const char *str)
Definition: string_matcher.hpp:131
std::string m_str
Definition: string_matcher.hpp:123
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:135
equal(std::string str)
Definition: string_matcher.hpp:127
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:140
Definition: string_matcher.hpp:231
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:253
list & add_string(const std::string &str)
Definition: string_matcher.hpp:248
std::vector< std::string > m_strings
Definition: string_matcher.hpp:233
list & add_string(const char *str)
Definition: string_matcher.hpp:243
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:261
list(std::vector< std::string > strings)
Definition: string_matcher.hpp:239
Definition: string_matcher.hpp:285
match_visitor(const char *str) noexcept
Definition: string_matcher.hpp:291
const char * m_str
Definition: string_matcher.hpp:287
bool operator()(const TMatcher &t) const noexcept
Definition: string_matcher.hpp:296
Definition: string_matcher.hpp:79
Definition: string_matcher.hpp:149
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:168
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:163
prefix(std::string str)
Definition: string_matcher.hpp:155
std::string m_str
Definition: string_matcher.hpp:151
prefix(const char *str)
Definition: string_matcher.hpp:159
Definition: string_matcher.hpp:303
print_visitor(std::basic_ostream< TChar, TTraits > &out)
Definition: string_matcher.hpp:309
std::basic_ostream< TChar, TTraits > * m_out
Definition: string_matcher.hpp:305
void operator()(const TMatcher &t) const noexcept
Definition: string_matcher.hpp:314
Definition: string_matcher.hpp:177
std::string m_str
Definition: string_matcher.hpp:179
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:196
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:191
substring(std::string str)
Definition: string_matcher.hpp:183
substring(const char *str)
Definition: string_matcher.hpp:187
Definition: string_matcher.hpp:74
StringMatcher()
Definition: string_matcher.hpp:325
StringMatcher(const std::vector< std::string > &strings)
Definition: string_matcher.hpp:384
StringMatcher(const char *str)
Definition: string_matcher.hpp:351
bool operator()(const char *str) const noexcept
Definition: string_matcher.hpp:405
boost::variant< always_false, always_true, equal, prefix, substring, list > matcher_type
Definition: string_matcher.hpp:281
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:417
bool operator()(const std::string &str) const noexcept
Definition: string_matcher.hpp:412
matcher_type m_matcher
Definition: string_matcher.hpp:283
StringMatcher(TMatcher &&matcher)
Definition: string_matcher.hpp:398
StringMatcher(bool result)
Definition: string_matcher.hpp:338
StringMatcher(const std::string &str)
Definition: string_matcher.hpp:361
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:551