1 /*
2   Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
3 
4   This program is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License, version 2.0,
6   as published by the Free Software Foundation.
7 
8   This program is also distributed with certain software (including
9   but not limited to OpenSSL) that is licensed under separate terms,
10   as designated in a particular file or component or in included license
11   documentation.  The authors of MySQL hereby grant you an additional
12   permission to link the program and your derivative works with the
13   separately licensed software that they have included with MySQL.
14 
15   This program is distributed in the hope that it will be useful,
16   but WITHOUT ANY WARRANTY; without even the implied warranty of
17   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18   GNU General Public License for more details.
19 
20   You should have received a copy of the GNU General Public License
21   along with this program; if not, write to the Free Software
22   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
23 */
24 
25 #ifndef MYSQL_HARNESS_UTILITIES_INCLUDED
26 #define MYSQL_HARNESS_UTILITIES_INCLUDED
27 
28 #include <memory>
29 #include <ostream>
30 #include <string>
31 #include <vector>
32 
33 #include "my_compiler.h"
34 
35 #include "harness_export.h"
36 #include "mysql/harness/utility/string.h"
37 #include "router_config.h"
38 
39 namespace mysql_harness {
40 
41 namespace utility {
42 
43 /**
44  * Class to turn C array into range.
45  *
46  * @see make_range
47  */
48 
49 template <class Type>
50 class Range {
51  public:
52   class iterator {
53    public:
iterator(Type * ptr)54     explicit iterator(Type *ptr) : ptr_(ptr) {}
55 
56     iterator &operator++() {
57       ++ptr_;
58       return *this;
59     }
60 
61     bool operator==(const iterator &rhs) { return ptr_ == rhs.ptr_; }
62 
63     bool operator!=(const iterator &rhs) { return ptr_ != rhs.ptr_; }
64 
65     Type &operator*() { return *ptr_; }
66 
67     const Type &operator*() const { return *ptr_; }
68 
69    private:
70     Type *ptr_;
71   };
72 
Range(Type * ptr,size_t length)73   Range(Type *ptr, size_t length) : start_(ptr), finish_(ptr + length) {}
74 
begin()75   iterator begin() { return iterator(start_); }
76 
end()77   iterator end() { return iterator(finish_); }
78 
79  private:
80   Type *start_;
81   Type *finish_;
82 };
83 
84 /**
85  * Create a range from a plain C array.
86  *
87  * This function create a range from a plain array so that arrays can
88  * be used in range-based loops.
89  *
90  * @see Range
91  */
92 
93 template <class Type>
make_range(Type * ptr,size_t length)94 Range<Type> make_range(Type *ptr, size_t length) {
95   return Range<Type>(ptr, length);
96 }
97 
98 /**
99  * Class for creating a reverse range from another range.
100  */
101 
102 template <typename Range>
103 class RangeReverse {
104  public:
RangeReverse(Range & range)105   explicit RangeReverse(Range &range) : range_(range) {}
106 
begin()107   typename Range::reverse_iterator begin() { return range_.rbegin(); }
108 
begin()109   typename Range::const_reverse_iterator begin() const {
110     return range_.rbegin();
111   }
112 
end()113   typename Range::reverse_iterator end() { return range_.rend(); }
114 
end()115   typename Range::const_reverse_iterator end() const { return range_.rend(); }
116 
117  private:
118   Range &range_;
119 };
120 
121 /**
122  * Iterate over a range in reverse.
123  *
124  * Function take a range, which can be any sequence container, and
125  * return a reverse range that iterate the sequence in reverse.
126  *
127  * Typical use-case is:
128  * @code
129  * for (auto item : reverse_iterate(my_list)) {
130  *   ...
131  * }
132  * @endcode
133  */
134 template <typename Range>
reverse(Range & x)135 RangeReverse<Range> reverse(Range &x) {  // NOLINT(runtime/references)
136   return RangeReverse<Range>(x);
137 }
138 
139 template <class Map>
find_range_first(Map & assoc,const typename Map::key_type::first_type & first,typename Map::iterator start)140 std::pair<typename Map::iterator, typename Map::iterator> find_range_first(
141     Map &assoc,  // NOLINT(runtime/references)
142     const typename Map::key_type::first_type &first,
143     typename Map::iterator start) {
144   typename Map::iterator finish = start;
145   while (finish != assoc.end() && finish->first.first == first) ++finish;
146   return make_pair(start, finish);
147 }
148 
149 template <class Map>
find_range_first(Map & assoc,const typename Map::key_type::first_type & first)150 std::pair<typename Map::iterator, typename Map::iterator> find_range_first(
151     Map &assoc,  // NOLINT(runtime/references)
152     const typename Map::key_type::first_type &first) {
153   typedef typename Map::key_type::second_type SType;
154   return find_range_first(assoc, first,
155                           assoc.lower_bound(make_pair(first, SType())));
156 }
157 
158 template <class Map>
159 std::pair<typename Map::const_iterator, typename Map::const_iterator>
find_range_first(const Map & assoc,const typename Map::key_type::first_type & first,typename Map::const_iterator start)160 find_range_first(const Map &assoc,
161                  const typename Map::key_type::first_type &first,
162                  typename Map::const_iterator start) {
163   typename Map::const_iterator finish = start;
164   while (finish != assoc.end() && finish->first.first == first) ++finish;
165   return make_pair(start, finish);
166 }
167 
168 template <class Map>
169 std::pair<typename Map::const_iterator, typename Map::const_iterator>
find_range_first(const Map & assoc,const typename Map::key_type::first_type & first)170 find_range_first(const Map &assoc,
171                  const typename Map::key_type::first_type &first) {
172   typedef typename Map::key_type::second_type SType;
173   return find_range_first(assoc, first,
174                           assoc.lower_bound(make_pair(first, SType())));
175 }
176 
177 std::string dirname(const std::string &path);
178 std::string basename(const std::string &path);
179 
180 /**
181  * Remove starting and trailing delimiters from string.
182  */
183 void strip(std::string *str, const char *chars = " \t\n\r\f\v");
184 HARNESS_EXPORT
185 std::string strip_copy(std::string str, const char *chars = " \t\n\r\f\v");
186 
187 HARNESS_EXPORT
188 MY_ATTRIBUTE((format(printf, 1, 2)))
189 std::string string_format(const char *format, ...);
190 
191 bool matches_glob(const std::string &word, const std::string &pattern);
192 
193 /*
194  * Checks wheter given string matches the pattern using extended posix regex.
195  */
196 bool regex_pattern_matches(const std::string &s, const std::string &pattern);
197 
198 }  // namespace utility
199 
200 }  // namespace mysql_harness
201 #endif /* MYSQL_HARNESS_UTILITIES_INCLUDED */
202