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 trim heading and trailing blank characters
88 : : * @details includes [ ' ', '\n', '\r', '\t' ]
89 : : * @param str string to trim
90 : : * @return trimmed string
91 : : */
92 : : std::string trim(const std::string &str);
93 : :
94 : : /**
95 : : * @brief url-encode the provided string
96 : : *
97 : : * @param[in] str the string to encode
98 : : * @return url-encoded (or percent-encoded) std::string
99 : : */
100 : : std::string urlencode(const std::string &str);
101 : :
102 : : /**
103 : : * @brief url-decode the provided string
104 : : *
105 : : * @param[in] str the string to decode
106 : : * @return string with percent-encoding decoded
107 : : */
108 : : std::string urldecode(const std::string &str);
109 : :
110 : : /**
111 : : * @brief flip a pair
112 : : * @details mainly used as an unary-operator
113 : : */
114 : : template<typename A>
115 : : typename std::enable_if<
116 : : std::is_same<std::pair<typename A::first_type, typename A::second_type>,
117 : : A>::value,
118 : : std::pair<typename A::second_type, typename A::first_type>>::type
119 : :
120 : 7 : flip(const A &pair)
121 : : {
122 : : return std::pair<typename A::second_type, typename A::first_type>(
123 : 7 : pair.second, pair.first);
124 : : }
125 : :
126 : : /**
127 : : * @brief flip a map
128 : : * @details useful for introspection objects (to_string/from_string)
129 : : * implementation.
130 : : */
131 : : template<typename A>
132 : : typename std::enable_if<
133 : : std::is_same<std::map<typename A::key_type, typename A::mapped_type>, A>::value,
134 : : std::map<typename A::mapped_type, typename A::key_type>>::type
135 : :
136 : 3 : flip(const A &map)
137 : : {
138 : 3 : std::map<typename A::mapped_type, typename A::key_type> ret;
139 : 3 : std::transform(map.cbegin(), map.cend(), std::inserter(ret, ret.begin()),
140 : : flip<typename A::value_type>);
141 : 3 : return ret;
142 : 0 : }
143 : :
144 : : /**
145 : : * @brief flip an unordered_map
146 : : * @details useful for introspection objects (to_string/from_string)
147 : : * implementation.
148 : : */
149 : : template<typename A>
150 : : typename std::enable_if<
151 : : std::is_same<std::unordered_map<typename A::key_type, typename A::mapped_type>,
152 : : A>::value,
153 : : std::unordered_map<typename A::mapped_type, typename A::key_type>>::type
154 : :
155 : : flip(const A &map)
156 : : {
157 : : std::unordered_map<typename A::mapped_type, typename A::key_type> ret;
158 : : std::transform(map.cbegin(), map.cend(), std::inserter(ret, ret.begin()),
159 : : flip<typename A::value_type>);
160 : : return ret;
161 : : }
162 : :
163 : : /**
164 : : * @brief retrieve map keys in a set
165 : : *
166 : : * @tparam A a map type
167 : : * @return std::set<keys>
168 : : */
169 : : template<typename A>
170 : : typename std::enable_if<
171 : : std::is_same<std::map<typename A::key_type, typename A::mapped_type>, A>::value ||
172 : : std::is_same<
173 : : std::unordered_map<typename A::key_type, typename A::mapped_type>,
174 : : A>::value,
175 : : std::set<typename A::key_type>>::type
176 : :
177 : 1 : keys(const A &map)
178 : : {
179 : 1 : std::set<typename A::key_type> ret;
180 : 1 : std::transform(
181 : : map.cbegin(), map.cend(), std::inserter(ret, ret.begin()),
182 : 2 : [](const typename A::value_type &value) { return value.first; });
183 : 1 : return ret;
184 : 0 : }
185 : :
186 : : /**
187 : : * @brief convert an enum to its underlying type
188 : : *
189 : : * @tparam T enum type
190 : : * @param t enum value to convert
191 : : * @return constexpr std::underlying_type<T>::type
192 : : */
193 : : template<typename T>
194 : 44 : inline constexpr typename std::underlying_type<T>::type enum_cast(T t)
195 : : {
196 : 44 : return static_cast<typename std::underlying_type<T>::type>(t);
197 : : }
198 : :
199 : : /**
200 : : * @brief add const qualifier on object
201 : : * @details useful with `ccut::cow_t` objects to ensure it won't be detached
202 : : * @tparam T const or non-const object
203 : : * @param c value to const cast
204 : : * @return std::add_const<T>::type&
205 : : */
206 : : template<typename T>
207 : 24 : inline typename std::add_const<T>::type &make_const(T &c)
208 : : {
209 : 24 : return c;
210 : : }
211 : :
212 : : /** @} */
213 : : } // namespace ccut
214 : :
215 : : #endif
|