InspIRCd  4.0
stdalgo.h
1 /*
2  * InspIRCd -- Internet Relay Chat Daemon
3  *
4  * Copyright (C) 2018, 2020-2021 Sadie Powell <[email protected]>
5  * Copyright (C) 2014, 2016, 2018 Attila Molnar <[email protected]>
6  *
7  * This file is part of InspIRCd. InspIRCd is free software: you can
8  * redistribute it and/or modify it under the terms of the GNU General Public
9  * License as published by the Free Software Foundation, version 2.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 
21 #pragma once
22 
23 namespace stdalgo
24 {
25  namespace vector
26  {
36  template <typename T>
37  inline void swaperase(typename std::vector<T>& vect, const typename std::vector<T>::iterator& it)
38  {
39  *it = vect.back();
40  vect.pop_back();
41  }
42 
55  template <typename T>
56  inline bool swaperase(typename std::vector<T>& vect, const T& val)
57  {
58  const typename std::vector<T>::iterator it = std::find(vect.begin(), vect.end(), val);
59  if (it != vect.end())
60  {
61  swaperase(vect, it);
62  return true;
63  }
64  return false;
65  }
66  }
67 
68  namespace string
69  {
74  inline const char* tocstr(const char* str)
75  {
76  return str;
77  }
78 
83  inline const char* tocstr(const std::string& str)
84  {
85  return str.c_str();
86  }
87 
93  template <typename S1, typename S2>
94  inline bool equalsci(const S1& str1, const S2& str2)
95  {
96  return (!strcasecmp(tocstr(str1), tocstr(str2)));
97  }
98 
104  template<typename Collection>
105  inline std::string join(const Collection& sequence, char separator = ' ')
106  {
107  std::string joined;
108  if (sequence.empty())
109  return joined;
110 
111  for (const auto& element : sequence)
112  joined.append(ConvToStr(element)).push_back(separator);
113 
114  joined.erase(joined.end() - 1);
115  return joined;
116  }
117 
124  template<typename CharT, typename Traits, typename Alloc>
125  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)
126  {
127  const typename std::basic_string<CharT, Traits, Alloc>::size_type p = str.find(target);
128  if (p == std::basic_string<CharT, Traits, Alloc>::npos)
129  return false;
130  str.replace(p, target.size(), replacement);
131  return true;
132  }
133 
139  template<typename CharT, typename Traits, typename Alloc>
140  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)
141  {
142  if (target.empty())
143  return;
144 
145  typename std::basic_string<CharT, Traits, Alloc>::size_type p = 0;
146  while ((p = str.find(target, p)) != std::basic_string<CharT, Traits, Alloc>::npos)
147  {
148  str.replace(p, target.size(), replacement);
149  p += replacement.size();
150  }
151  }
152  }
153 
158  struct cull_delete
159  {
160  void operator()(Cullable* item);
161  };
162 
167  template <template<typename, typename> class Cont, typename T, typename Alloc>
168  inline void delete_all(const Cont<T*, Alloc>& cont)
169  {
170  std::for_each(cont.begin(), cont.end(), std::default_delete<T>());
171  }
172 
176  template<typename T>
177  void delete_zero(T*& pr)
178  {
179  T* p = pr;
180  pr = NULL;
181  delete p;
182  }
183 
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 
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  {
221  template <char from, char to, char esc>
222  inline void escape(const std::string& str, std::string& out)
223  {
224  for (const auto& c : str)
225  {
226  if (c == esc)
227  out.append(2, esc);
228  else
229  {
230  if (c == from)
231  {
232  out.push_back(esc);
233  out.push_back(to);
234  }
235  else
236  out.push_back(c);
237  }
238  }
239  }
240 
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 
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 
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 
296  namespace map
297  {
303  template<typename Key, typename Value, typename Compare, template<typename...> typename Map>
304  void difference(const Map<Key, Value, Compare>& first, const Map<Key, Value, Compare>& second,
305  Map<Key, std::pair<std::optional<Value>, std::optional<Value>>, Compare>& out)
306  {
307  auto fiter = first.cbegin();
308  auto siter = second.cbegin();
309 
310  while (fiter != first.end())
311  {
312  if (siter == second.end())
313  {
314  // Store the remaining from the first.
315  while (fiter != first.end())
316  {
317  out[fiter->first] = { fiter->second, std::nullopt };
318  fiter++;
319  }
320  return;
321  }
322 
323  if (fiter->first < siter->first)
324  {
325  // The key in first is not in second.
326  out[fiter->first] = { fiter->second, std::nullopt };
327  fiter++;
328  }
329  else if (siter->first < fiter->first)
330  {
331  // The key in second is not in first.
332  out[siter->first] = { std::nullopt, siter->second };
333  siter++;
334  }
335  else if (fiter->second != siter->second)
336  {
337  // The key exists in both but the value differs.
338  out[fiter->first] = { fiter->second, siter->second };
339  fiter++;
340  siter++;
341  }
342  else
343  {
344  // The key/value is identical in both.
345  fiter++;
346  siter++;
347  }
348  }
349 
350  // Store the remaining from the second.
351  while (siter != second.end())
352  {
353  out[siter->first] = { std::nullopt, siter->second };
354  siter++;
355  }
356  }
357  }
358 }
Definition: cull.h:30
Definition: stdalgo.h:159