Libosmium  2.13.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 (http://osmcode.org/libosmium).
7 
8 Copyright 2013-2017 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 <cstring>
37 #include <iosfwd>
38 #include <string>
39 #include <vector>
40 
41 #include <regex>
42 
43 // std::regex isn't implemented properly in glibc++ (before the version
44 // delivered with GCC 4.9) and libc++ before the version 3.6, so the use is
45 // disabled by these checks. Checks for GLIBC were based on
46 // http://stackoverflow.com/questions/12530406/is-gcc-4-8-or-earlier-buggy-about-regular-expressions
47 // Checks for libc++ are simply based on compiler defines. This is probably
48 // not optimal but seems to work for now.
49 #if defined(__GLIBCXX__)
50 # if ((__cplusplus >= 201402L) || \
51  defined(_GLIBCXX_REGEX_DFS_QUANTIFIERS_LIMIT) || \
52  defined(_GLIBCXX_REGEX_STATE_LIMIT))
53 # define OSMIUM_WITH_REGEX
54 # else
55 # pragma message("Disabling regex functionality. See source code for info.")
56 # endif
57 #elif defined(__clang__)
58 # if ((__clang_major__ > 3) || \
59  (__clang_minor__ == 3 && __clang_minor__ > 5))
60 # define OSMIUM_WITH_REGEX
61 # else
62 # pragma message("Disabling regex functionality")
63 # endif
64 #endif
65 
66 #include <boost/variant.hpp>
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(const std::string& str) :
127  m_str(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(const std::string& str) :
155  m_str(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(const std::string& str) :
183  m_str(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(const std::regex& regex) :
212  m_regex(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() :
237  m_strings() {
238  }
239 
240  explicit list(const std::vector<std::string>& strings) :
241  m_strings(strings) {
242  }
243 
244  list& add_string(const char* str) {
245  m_strings.push_back(str);
246  return *this;
247  }
248 
249  list& add_string(const std::string& str) {
250  m_strings.push_back(str);
251  return *this;
252  }
253 
254  bool match(const char* test_string) const noexcept {
255  for (const auto& s : m_strings) {
256  if (!std::strcmp(s.c_str(), test_string)) {
257  return true;
258  }
259  }
260  return false;
261 
262  }
263 
264  template <typename TChar, typename TTraits>
265  void print(std::basic_ostream<TChar, TTraits>& out) const {
266  out << "list[";
267  for (const auto& s : m_strings) {
268  out << '[' << s << ']';
269  }
270  out << ']';
271  }
272 
273  }; // class list
274 
275  private:
276 
277  using matcher_type = boost::variant<always_false,
278  always_true,
279  equal,
280  prefix,
281  substring,
282 #ifdef OSMIUM_WITH_REGEX
283  regex,
284 #endif
286 
288 
289  class match_visitor : public boost::static_visitor<bool> {
290 
291  const char* m_str;
292 
293  public:
294 
295  match_visitor(const char* str) noexcept :
296  m_str(str) {
297  }
298 
299  template <typename TMatcher>
300  bool operator()(const TMatcher& t) const noexcept {
301  return t.match(m_str);
302  }
303 
304  }; // class match_visitor
305 
306  template <typename TChar, typename TTraits>
307  class print_visitor : public boost::static_visitor<void> {
308 
309  std::basic_ostream<TChar, TTraits>* m_out;
310 
311  public:
312 
313  print_visitor(std::basic_ostream<TChar, TTraits>& out) :
314  m_out(&out) {
315  }
316 
317  template <typename TMatcher>
318  void operator()(const TMatcher& t) const noexcept {
319  t.print(*m_out);
320  }
321 
322  }; // class print_visitor
323 
324  public:
325 
330  m_matcher(always_false{}) {
331  }
332 
341  StringMatcher(bool result) :
342  m_matcher(always_false{}) {
343  if (result) {
344  m_matcher = always_true{};
345  }
346  }
347 
353  StringMatcher(const char* str) :
354  m_matcher(equal{str}) {
355  }
356 
362  StringMatcher(const std::string& str) :
363  m_matcher(equal{str}) {
364  }
365 
366 #ifdef OSMIUM_WITH_REGEX
367 
372  StringMatcher(const std::regex& aregex) :
373  m_matcher(regex{aregex}) {
374  }
375 #endif
376 
383  StringMatcher(const std::vector<std::string>& strings) :
384  m_matcher(list{strings}) {
385  }
386 
394  template <typename TMatcher, typename std::enable_if<
395  std::is_base_of<matcher, TMatcher>::value, int>::type = 0>
396  StringMatcher(TMatcher&& matcher) :
397  m_matcher(std::forward<TMatcher>(matcher)) {
398  }
399 
403  bool operator()(const char* str) const noexcept {
404  return boost::apply_visitor(match_visitor{str}, m_matcher);
405  }
406 
410  bool operator()(const std::string& str) const noexcept {
411  return operator()(str.c_str());
412  }
413 
414  template <typename TChar, typename TTraits>
415  void print(std::basic_ostream<TChar, TTraits>& out) const {
416  boost::apply_visitor(print_visitor<TChar, TTraits>{out}, m_matcher);
417  }
418 
419  }; // class StringMatcher
420 
421  template <typename TChar, typename TTraits>
422  inline std::basic_ostream<TChar, TTraits>& operator<<(std::basic_ostream<TChar, TTraits>& out, const StringMatcher& matcher) {
423  matcher.print(out);
424  return out;
425  }
426 
427 } // namespace osmium
428 
429 #endif // OSMIUM_UTIL_STRING_MATCHER_HPP
list(const std::vector< std::string > &strings)
Definition: string_matcher.hpp:240
equal(const char *str)
Definition: string_matcher.hpp:130
Definition: string_matcher.hpp:230
StringMatcher(TMatcher &&matcher)
Definition: string_matcher.hpp:396
bool operator()(const char *str) const noexcept
Definition: string_matcher.hpp:403
type
Definition: entity_bits.hpp:63
Definition: string_matcher.hpp:102
StringMatcher(const std::string &str)
Definition: string_matcher.hpp:362
boost::variant< always_false, always_true, equal, prefix, substring, list > matcher_type
Definition: string_matcher.hpp:285
equal(const std::string &str)
Definition: string_matcher.hpp:126
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:111
list & add_string(const char *str)
Definition: string_matcher.hpp:244
Definition: string_matcher.hpp:307
print_visitor(std::basic_ostream< TChar, TTraits > &out)
Definition: string_matcher.hpp:313
Definition: reader_iterator.hpp:39
StringMatcher(const std::vector< std::string > &strings)
Definition: string_matcher.hpp:383
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:254
Definition: string_matcher.hpp:120
bool match(const char *) const noexcept
Definition: string_matcher.hpp:88
StringMatcher()
Definition: string_matcher.hpp:329
Definition: string_matcher.hpp:78
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:415
Definition: string_matcher.hpp:176
match_visitor(const char *str) noexcept
Definition: string_matcher.hpp:295
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:265
Definition: string_matcher.hpp:73
void print(std::basic_ostream< TChar, TTraits > &out) const
Definition: string_matcher.hpp:93
prefix(const std::string &str)
Definition: string_matcher.hpp:154
bool operator()(const TMatcher &t) const noexcept
Definition: string_matcher.hpp:300
substring(const std::string &str)
Definition: string_matcher.hpp:182
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:353
StringMatcher(bool result)
Definition: string_matcher.hpp:341
list & add_string(const std::string &str)
Definition: string_matcher.hpp:249
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:287
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:309
const char * m_str
Definition: string_matcher.hpp:291
Definition: string_matcher.hpp:289
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
list()
Definition: string_matcher.hpp:236
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:410
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:162
std::string m_str
Definition: string_matcher.hpp:122
void operator()(const TMatcher &t) const noexcept
Definition: string_matcher.hpp:318
bool match(const char *test_string) const noexcept
Definition: string_matcher.hpp:134