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
6This file is part of Osmium (https://osmcode.org/libosmium).
7
8Copyright 2013-2023 Jochen Topf <jochen@topf.org> and others (see README).
9
10Boost Software License - Version 1.0 - August 17th, 2003
11
12Permission is hereby granted, free of charge, to any person or organization
13obtaining a copy of the software and accompanying documentation covered by
14this license (the "Software") to use, reproduce, display, distribute,
15execute, and transmit the Software, and to prepare derivative works of the
16Software, and to permit third-parties to whom the Software is furnished to
17do so, all subject to the following:
18
19The copyright notices in the Software and this entire statement, including
20the above license grant, this restriction and the following disclaimer,
21must be included in all copies of the Software, in whole or in part, and
22all derivative works of the Software, unless such copies or derivative
23works are solely in the form of machine-executable object code generated by
24a source language processor.
25
26THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32DEALINGS 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
81namespace osmium {
82
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
286#ifdef OSMIUM_USE_STD_VARIANT
287 std::variant
288#else
289 boost::variant
290#endif
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
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
list & add_string(const char *str)
Definition: string_matcher.hpp:255
std::vector< std::string > m_strings
Definition: string_matcher.hpp:245
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