Branch data Line data Source code
1 : : /*
2 : : ** Copyright (C) 2020 Sylvain Fargier
3 : : **
4 : : ** This software is provided 'as-is', without any express or implied
5 : : ** warranty. In no event will the authors be held liable for any damages
6 : : ** arising from the use of this software.
7 : : **
8 : : ** Permission is granted to anyone to use this software for any purpose,
9 : : ** including commercial applications, and to alter it and redistribute it
10 : : ** freely, subject to the following restrictions:
11 : : **
12 : : ** 1. The origin of this software must not be misrepresented; you must not
13 : : ** claim that you wrote the original software. If you use this software
14 : : ** in a product, an acknowledgment in the product documentation would be
15 : : ** appreciated but is not required.
16 : : ** 2. Altered source versions must be plainly marked as such, and must not be
17 : : ** misrepresented as being the original software.
18 : : ** 3. This notice may not be removed or altered from any source distribution.
19 : : **
20 : : ** Created on: 2022-02-14T16:47:14+01:00
21 : : ** Author: Sylvain Fargier <fargie_s> <fargier.sylvain@free.fr>
22 : : **
23 : : */
24 : :
25 : : #ifndef CCUT_UTILS_HPP__
26 : : #define CCUT_UTILS_HPP__
27 : :
28 : : #include <algorithm>
29 : : #include <cstdint>
30 : : #include <map>
31 : : #include <set>
32 : : #include <string>
33 : : #include <type_traits>
34 : : #include <unordered_map>
35 : : #include <vector>
36 : :
37 : : namespace ccut {
38 : : /**
39 : : * @addtogroup utils utils: various utilities
40 : : * @{
41 : : */
42 : :
43 : : /**
44 : : * @brief get current library version
45 : : * @param[in] extraLong display only semvar or add scm related info
46 : : * @param[in] log log version on console
47 : : */
48 : : std::string ccutVersion(bool extraLong = true, bool log = true);
49 : :
50 : : /**
51 : : * @brief split string according to separator
52 : : * @param str string to split
53 : : * @param separator separator to look for
54 : : * @param out output vector
55 : : * @return out argument
56 : : */
57 : : std::vector<std::string> &split(const std::string &str,
58 : : char separator,
59 : : std::vector<std::string> &out);
60 : :
61 : : /**
62 : : * @brief split substring according to separator
63 : : * @param begin start of substring
64 : : * @param end end of substring (excluded)
65 : : * @param separator separator to look for
66 : : * @param out output vector
67 : : * @return out argument
68 : : */
69 : : std::vector<std::string> &split(const std::string::const_iterator &begin,
70 : : const std::string::const_iterator &end,
71 : : char separator,
72 : : std::vector<std::string> &out);
73 : :
74 : : /**
75 : : * @brief startsWith implementation
76 : : * @details waiting for C++20
77 : : * @param str string to check
78 : : * @param prefix string to search for
79 : : * @return true if str starts with prefix
80 : : */
81 : 4 : inline bool startsWith(const std::string &str, const std::string &prefix)
82 : : {
83 : 4 : return str.compare(0, prefix.size(), prefix) == 0;
84 : : }
85 : :
86 : : /**
87 : : * @brief endsWith implementation
88 : : * @details waiting for C++20
89 : : * @param str string to check
90 : : * @param suffix string to search for
91 : : * @return true if str ends with prefix
92 : : */
93 : 4 : inline bool endsWith(const std::string &str, const std::string &suffix)
94 : : {
95 : 4 : if (suffix.size() > str.size())
96 : 1 : return false;
97 : 3 : return str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0;
98 : : }
99 : :
100 : : /**
101 : : * @brief trim heading and trailing blank characters
102 : : * @details includes [ ' ', '\n', '\r', '\t' ]
103 : : * @param str string to trim
104 : : * @return trimmed string
105 : : */
106 : : std::string trim(const std::string &str);
107 : :
108 : : /**
109 : : * @brief url-encode the provided string
110 : : *
111 : : * @param[in] str the string to encode
112 : : * @return url-encoded (or percent-encoded) std::string
113 : : */
114 : : std::string urlencode(const std::string &str);
115 : :
116 : : /**
117 : : * @brief url-decode the provided string
118 : : *
119 : : * @param[in] str the string to decode
120 : : * @return string with percent-encoding decoded
121 : : */
122 : : std::string urldecode(const std::string &str);
123 : :
124 : : /**
125 : : * @brief flip a pair
126 : : * @details mainly used as an unary-operator
127 : : */
128 : : template<typename A>
129 : : typename std::enable_if<
130 : : std::is_same<std::pair<typename A::first_type, typename A::second_type>,
131 : : A>::value,
132 : : std::pair<typename A::second_type, typename A::first_type>>::type
133 : :
134 : 7 : flip(const A &pair)
135 : : {
136 : : return std::pair<typename A::second_type, typename A::first_type>(
137 : 7 : pair.second, pair.first);
138 : : }
139 : :
140 : : /**
141 : : * @brief flip a map
142 : : * @details useful for introspection objects (to_string/from_string)
143 : : * implementation.
144 : : */
145 : : template<typename A>
146 : : typename std::enable_if<
147 : : std::is_same<std::map<typename A::key_type, typename A::mapped_type>, A>::value,
148 : : std::map<typename A::mapped_type, typename A::key_type>>::type
149 : :
150 : 3 : flip(const A &map)
151 : : {
152 : 3 : std::map<typename A::mapped_type, typename A::key_type> ret;
153 : 3 : std::transform(map.cbegin(), map.cend(), std::inserter(ret, ret.begin()),
154 : : flip<typename A::value_type>);
155 : 3 : return ret;
156 : 0 : }
157 : :
158 : : /**
159 : : * @brief flip an unordered_map
160 : : * @details useful for introspection objects (to_string/from_string)
161 : : * implementation.
162 : : */
163 : : template<typename A>
164 : : typename std::enable_if<
165 : : std::is_same<std::unordered_map<typename A::key_type, typename A::mapped_type>,
166 : : A>::value,
167 : : std::unordered_map<typename A::mapped_type, typename A::key_type>>::type
168 : :
169 : : flip(const A &map)
170 : : {
171 : : std::unordered_map<typename A::mapped_type, typename A::key_type> ret;
172 : : std::transform(map.cbegin(), map.cend(), std::inserter(ret, ret.begin()),
173 : : flip<typename A::value_type>);
174 : : return ret;
175 : : }
176 : :
177 : : /**
178 : : * @brief retrieve map keys in a set
179 : : *
180 : : * @tparam A a map type
181 : : * @return std::set<keys>
182 : : */
183 : : template<typename A>
184 : : typename std::enable_if<
185 : : std::is_same<std::map<typename A::key_type, typename A::mapped_type>, A>::value ||
186 : : std::is_same<
187 : : std::unordered_map<typename A::key_type, typename A::mapped_type>,
188 : : A>::value,
189 : : std::set<typename A::key_type>>::type
190 : :
191 : 1 : keys(const A &map)
192 : : {
193 : 1 : std::set<typename A::key_type> ret;
194 : 1 : std::transform(
195 : : map.cbegin(), map.cend(), std::inserter(ret, ret.begin()),
196 : 2 : [](const typename A::value_type &value) { return value.first; });
197 : 1 : return ret;
198 : 0 : }
199 : :
200 : : /**
201 : : * @brief retrieve map values in a set
202 : : *
203 : : * @tparam A a map type
204 : : * @return std::set<values>
205 : : */
206 : : template<typename A>
207 : : typename std::enable_if<
208 : : std::is_same<std::map<typename A::key_type, typename A::mapped_type>, A>::value ||
209 : : std::is_same<
210 : : std::unordered_map<typename A::key_type, typename A::mapped_type>,
211 : : A>::value,
212 : : std::set<typename A::mapped_type>>::type
213 : :
214 : 1 : values(const A &map)
215 : : {
216 : 1 : std::set<typename A::mapped_type> ret;
217 : 1 : std::transform(
218 : : map.cbegin(), map.cend(), std::inserter(ret, ret.begin()),
219 : 2 : [](const typename A::value_type &value) { return value.second; });
220 : 1 : return ret;
221 : 0 : }
222 : :
223 : : /**
224 : : * @brief convert an enum to its underlying type
225 : : *
226 : : * @tparam T enum type
227 : : * @param t enum value to convert
228 : : * @return constexpr std::underlying_type<T>::type
229 : : */
230 : : template<typename T>
231 : 44 : inline constexpr typename std::underlying_type<T>::type enum_cast(T t)
232 : : {
233 : 44 : return static_cast<typename std::underlying_type<T>::type>(t);
234 : : }
235 : :
236 : : /**
237 : : * @brief add const qualifier on object
238 : : * @details useful with `ccut::cow_t` objects to ensure it won't be detached
239 : : * @tparam T const or non-const object
240 : : * @param c value to const cast
241 : : * @return std::add_const<T>::type&
242 : : */
243 : : template<typename T>
244 : 24 : inline typename std::add_const<T>::type &make_const(T &c)
245 : : {
246 : 24 : return c;
247 : : }
248 : :
249 : : /** @} */
250 : : } // namespace ccut
251 : :
252 : : #endif
|