]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - include/stdalgo.h
Merge tag 'v2.0.27' into master.
[user/henk/code/inspircd.git] / include / stdalgo.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  *   Copyright (C) 2014 Attila Molnar <attilamolnar@hush.com>
5  *
6  * This file is part of InspIRCd.  InspIRCd is free software: you can
7  * redistribute it and/or modify it under the terms of the GNU General Public
8  * License as published by the Free Software Foundation, version 2.
9  *
10  * This program is distributed in the hope that it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #pragma once
21
22 namespace stdalgo
23 {
24         namespace vector
25         {
26                 /**
27                  * Erase a single element from a vector by overwriting it with a copy of the last element,
28                  * which is then removed. This, in contrast to vector::erase(), does not result in all
29                  * elements after the erased element being moved.
30                  * @param vect Vector to remove the element from
31                  * @param it Iterator to the element to remove
32                  * @return Nothing, but all iterators, references and pointers to the erased element and the
33                  * last element are invalidated
34                  */
35                 template <typename T>
36                 inline void swaperase(typename std::vector<T>& vect, const typename std::vector<T>::iterator& it)
37                 {
38                         *it = vect.back();
39                         vect.pop_back();
40                 }
41
42                 /**
43                  * Find and if exists, erase a single element from a vector by overwriting it with a
44                  * copy of the last element, which is then removed. This, in contrast to vector::erase(),
45                  * does not result in all elements after the erased element being moved.
46                  * If the given value occurs multiple times, the one with the lowest index is removed.
47                  * Individual elements are compared to the given value using operator==().
48                  * @param vect Vector to remove the element from
49                  * @param val Value of the element to look for and remove
50                  * @return True if the element was found and removed, false if it wasn't found.
51                  * If true, all iterators, references and pointers pointing to either the first element that
52                  * is equal to val or to the last element are invalidated.
53                  */
54                 template <typename T>
55                 inline bool swaperase(typename std::vector<T>& vect, const T& val)
56                 {
57                         const typename std::vector<T>::iterator it = std::find(vect.begin(), vect.end(), val);
58                         if (it != vect.end())
59                         {
60                                 swaperase(vect, it);
61                                 return true;
62                         }
63                         return false;
64                 }
65         }
66
67         namespace string
68         {
69                 /** Get underlying C string of the string passed as parameter. Useful in template functions.
70                  * @param str C string
71                  * @return Same as input
72                  */
73                 inline const char* tocstr(const char* str)
74                 {
75                         return str;
76                 }
77
78                 /** Get underlying C string of the string passed as parameter. Useful in template functions.
79                  * @param str std::string object
80                  * @return str.c_str()
81                  */
82                 inline const char* tocstr(const std::string& str)
83                 {
84                         return str.c_str();
85                 }
86
87                 /** Check if two strings are equal case insensitively.
88                  * @param str1 First string to compare.
89                  * @param str2 Second string to compare.
90                  * @return True if the strings are equal case-insensitively, false otherwise.
91                  */
92                 template <typename S1, typename S2>
93                 inline bool equalsci(const S1& str1, const S2& str2)
94                 {
95                         return (!strcasecmp(tocstr(str1), tocstr(str2)));
96                 }
97
98                 /** Joins the contents of a vector to a string.
99                  * @param sequence Zero or more items to join.
100                  * @param separator The character to place between the items, defaults to ' ' (space).
101                  * @return The joined string.
102                  */
103                 template<typename Collection>
104                 inline std::string join(const Collection& sequence, char separator = ' ')
105                 {
106                         std::string joined;
107                         if (sequence.empty())
108                                 return joined;
109
110                         for (typename Collection::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter)
111                                 joined.append(ConvToStr(*iter)).push_back(separator);
112
113                         joined.erase(joined.end() - 1);
114                         return joined;
115                 }
116
117                 /** Replace first occurrence of a substring ('target') in a string ('str') with another string ('replacement').
118                  * @param str String to perform replacement in
119                  * @param target String to replace
120                  * @param replacement String to put in place of 'target'
121                  * @return True if 'target' was replaced with 'replacement', false if it was not found in 'str'.
122                  */
123                 template<typename CharT, typename Traits, typename Alloc>
124                 inline bool replace(std::basic_string<CharT, Traits, Alloc>& str, const std::basic_string<CharT, Traits, Alloc>& target, const std::basic_string<CharT, Traits, Alloc>& replacement)
125                 {
126                         const typename std::basic_string<CharT, Traits, Alloc>::size_type p = str.find(target);
127                         if (p == std::basic_string<CharT, Traits, Alloc>::npos)
128                                 return false;
129                         str.replace(p, target.size(), replacement);
130                         return true;
131                 }
132
133                 /** Replace all occurrences of a string ('target') in a string ('str') with another string ('replacement').
134                  * @param str String to perform replacement in
135                  * @param target String to replace
136                  * @param replacement String to put in place of 'target'
137                  */
138                 template<typename CharT, typename Traits, typename Alloc>
139                 inline void replace_all(std::basic_string<CharT, Traits, Alloc>& str, const std::basic_string<CharT, Traits, Alloc>& target, const std::basic_string<CharT, Traits, Alloc>& replacement)
140                 {
141                         if (target.empty())
142                                 return;
143
144                         typename std::basic_string<CharT, Traits, Alloc>::size_type p = 0;
145                         while ((p = str.find(target, p)) != std::basic_string<CharT, Traits, Alloc>::npos)
146                         {
147                                 str.replace(p, target.size(), replacement);
148                                 p += replacement.size();
149                         }
150                 }
151         }
152
153         /**
154          * Deleter that uses operator delete to delete the item
155          */
156         template <typename T>
157         struct defaultdeleter
158         {
159                 void operator()(T* o)
160                 {
161                         delete o;
162                 }
163         };
164
165         /**
166          * Deleter that adds the item to the cull list, that is, queues it for
167          * deletion at the end of the current mainloop iteration
168          */
169         struct culldeleter
170         {
171                 void operator()(classbase* item);
172         };
173
174         /**
175          * Deletes all elements in a container using operator delete
176          * @param cont The container containing the elements to delete
177          */
178         template <template<typename, typename> class Cont, typename T, typename Alloc>
179         inline void delete_all(const Cont<T*, Alloc>& cont)
180         {
181                 std::for_each(cont.begin(), cont.end(), defaultdeleter<T>());
182         }
183
184         /**
185          * Remove an element from a container
186          * @param cont Container to remove the element from
187          * @param val Value of the element to look for and remove
188          * @return True if the element was found and removed, false otherwise
189          */
190         template <template<typename, typename> class Cont, typename T, typename Alloc>
191         inline bool erase(Cont<T, Alloc>& cont, const T& val)
192         {
193                 const typename Cont<T, Alloc>::iterator it = std::find(cont.begin(), cont.end(), val);
194                 if (it != cont.end())
195                 {
196                         cont.erase(it);
197                         return true;
198                 }
199                 return false;
200         }
201
202         /**
203          * Check if an element with the given value is in a container. Equivalent to (std::find(cont.begin(), cont.end(), val) != cont.end()).
204          * @param cont Container to find the element in
205          * @param val Value of the element to look for
206          * @return True if the element was found in the container, false otherwise
207          */
208         template <template<typename, typename> class Cont, typename T, typename Alloc>
209         inline bool isin(const Cont<T, Alloc>& cont, const T& val)
210         {
211                 return (std::find(cont.begin(), cont.end(), val) != cont.end());
212         }
213
214         namespace string
215         {
216                 /**
217                  * Escape a string
218                  * @param str String to escape
219                  * @param out Output, must not be the same string as str
220                  */
221                 template <char from, char to, char esc>
222                 inline void escape(const std::string& str, std::string& out)
223                 {
224                         for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
225                         {
226                                 char c = *i;
227                                 if (c == esc)
228                                         out.append(2, esc);
229                                 else
230                                 {
231                                         if (c == from)
232                                         {
233                                                 out.push_back(esc);
234                                                 c = to;
235                                         }
236                                         out.push_back(c);
237                                 }
238                         }
239                 }
240
241                 /**
242                  * Escape a string using the backslash character as the escape character
243                  * @param str String to escape
244                  * @param out Output, must not be the same string as str
245                  */
246                 template <char from, char to>
247                 inline void escape(const std::string& str, std::string& out)
248                 {
249                         escape<from, to, '\\'>(str, out);
250                 }
251
252                 /**
253                  * Unescape a string
254                  * @param str String to unescape
255                  * @param out Output, must not be the same string as str
256                  * @return True if the string was unescaped, false if an invalid escape sequence is present in the input in which case out will contain a partially unescaped string
257                  */
258                 template<char from, char to, char esc>
259                 inline bool unescape(const std::string& str, std::string& out)
260                 {
261                         for (std::string::const_iterator i = str.begin(); i != str.end(); ++i)
262                         {
263                                 char c = *i;
264                                 if (c == '\\')
265                                 {
266                                         ++i;
267                                         if (i == str.end())
268                                                 return false;
269
270                                         char nextc = *i;
271                                         if (nextc == esc)
272                                                 c = esc;
273                                         else if (nextc != to)
274                                                 return false; // Invalid escape sequence
275                                         else
276                                                 c = from;
277                                 }
278                                 out.push_back(c);
279                         }
280                         return true;
281                 }
282
283                 /**
284                  * Unescape a string using the backslash character as the escape character
285                  * @param str String to unescape
286                  * @param out Output, must not be the same string as str
287                  * @return True if the string was unescaped, false if an invalid escape sequence is present in the input in which case out will contain a partially unescaped string
288                  */
289                 template <char from, char to>
290                 inline bool unescape(const std::string& str, std::string& out)
291                 {
292                         return unescape<from, to, '\\'>(str, out);
293                 }
294         }
295 }