My Project
FRC.h
1 /*
2  * Copyright (c) 2014, killerbee13
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  * * Neither the name of the copyright holder nor the names of its
16  * contributors may be used to endorse or promote products derived from
17  * this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  *
31  */
32 
33 #ifndef SIMPLE_ALGORITHMS_H_INCLUDED
34 #define SIMPLE_ALGORITHMS_H_INCLUDED
35 
36 // Header containing frequently reused code that is not as easily done without
37 // helper functions
38 
39 #include <algorithm>
40 #include <array>
41 #include <cctype>
42 #include <cmath>
43 #include <complex>
44 #include <fstream>
45 #include <istream>
46 #include <limits>
47 #include <tuple>
48 #include <utility>
49 
50 #include <exception>
51 #include <stdexcept>
52 #include <typeinfo>
53 
54 #if __has_cpp_attribute(fallthrough)
55 #define fallthrough fallthrough
56 #elif __has_cpp_attribute(clang::fallthrough)
57 #define fallthrough clang::fallthrough
58 #elif __has_cpp_attribute(gnu::fallthrough)
59 #define fallthrough gnu::fallthrough
60 #else
61 #define fallthrough fallthrough
62 #endif
63 
64 #if __has_cpp_attribute(maybe_unused)
65 #define maybe_unused maybe_unused
66 #elif __has_cpp_attribute(gnu::unused)
67 #define maybe_unused gnu::unused
68 #else // Just let the compiler show the warning
69 #define maybe_unused maybe_unused
70 #endif
71 
72 #if !FRC_NO_CONVERT
73 #include <sstream>
74 #include <string>
75 // This is the only one that should throw an exception
76 template <typename T>
77 inline T fromStr(const std::string& val) {
78  std::stringstream ss(val);
79  T ret;
80  if (!(ss >> ret).fail())
81  return ret;
82  else
83  throw std::runtime_error("\"" + val + "\" is not a " + typeid(T).name());
84 }
85 template <>
86 inline std::string fromStr(const std::string& val) {
87  return val;
88 }
89 
90 template <typename T>
91 inline T fromStr(const std::string& val, const char* type) {
92  std::stringstream ss(val);
93  T ret;
94  if (!(ss >> ret).fail())
95  return ret;
96  else
97  throw std::runtime_error("\"" + val + "\" is not a " + type);
98 }
99 template <>
100 inline std::string fromStr(const std::string& val,
101  [[maybe_unused]] const char* type) {
102  return val;
103 }
104 #define pFromStr(type, val) fromStr<type>((val), #type)
105 
106 template <typename T>
107 inline std::string toStr(T val) {
108  std::stringstream ss;
109  ss << val;
110  return ss.str();
111 }
112 #endif
113 
114 #if !FRC_NO_ICU
115 #include <unicode/unistr.h>
116 // For elegance
117 template <typename string = std::string>
118 inline string toUTF8(const icu::UnicodeString& s) {
119  string res;
120  return s.toUTF8String(res);
121 }
122 // For consistency
123 template <typename string>
124 inline icu::UnicodeString fromUTF8(string s) {
125  return icu::UnicodeString::fromUTF8(s);
126 }
127 // For elegance
128 template <typename string = std::u32string>
129 inline string toUTF32(const icu::UnicodeString& s) {
130  string res(s.countChar32(), '\0');
131  UErrorCode ec{U_ZERO_ERROR};
132  s.toUTF32(reinterpret_cast<UChar32*>(&res[0]), res.size(), ec);
133  if (U_FAILURE(ec)) {
134  throw ec;
135  }
136  return res;
137 }
138 // For consistency
139 template <typename string>
140 inline icu::UnicodeString fromUTF32(string s) {
141  return icu::UnicodeString::fromUTF32(s.data(), s.length());
142 }
143 
144 inline std::ostream& operator<<(std::ostream& os,
145  const icu::UnicodeString& str) {
146  return os << toUTF8(str);
147 }
148 
149 // ICU basically provides a + so I might as well translate it
150 inline std::string operator+(std::string lhs, const icu::UnicodeString& str) {
151  return str.toUTF8String(lhs);
152 }
153 
154 #if !FRC_NO_CONVERT
155 
156 // For debugging
157 std::string d_toUTF8(const icu::UnicodeString& s);
158 icu::UnicodeString d_fromUTF8(std::string s);
159 
160 template <typename T>
161 inline T fromStr(const icu::UnicodeString& val, const char* type) {
162  return fromStr<T>(toUTF8(val), type);
163 }
164 
165 template <typename T>
166 inline T fromStr(const icu::UnicodeString& val) {
167  return fromStr<T>(toUTF8(val));
168 }
169 #endif
170 #endif
171 
172 #include <numeric>
173 template <typename string, typename vector>
174 inline string join(const vector& in, const string& joiner = {}) {
175  if (in.size() == 0) {
176  return {};
177  } else if (in.size() == 1) {
178  return *in.begin();
179  } else {
180  return std::accumulate(
181  std::next(std::begin(in)), std::end(in), *in.begin(),
182  [&joiner](const string& a, const string& b) -> string {
183  return a + joiner + b;
184  });
185  }
186 }
187 
188 template <typename string>
189 inline string reverseStr(string val) {
190  std::reverse(val.begin(), val.end());
191  return val;
192 }
193 
194 template <typename string>
195 inline string toLower(string str) {
196  std::transform(str.begin(), str.end(), str.begin(), ::tolower);
197  return str;
198 }
199 
200 template <typename string>
201 inline string toUpper(string str) {
202  std::transform(str.begin(), str.end(), str.begin(), ::toupper);
203  return str;
204 }
205 
206 #include <sstream>
207 #include <string>
208 #include <vector>
209 template <typename T>
210 inline std::vector<T> listToVec(std::string list) {
211  std::vector<T> ret;
212  std::stringstream ss(list);
213  std::string tmp;
214  while (!(ss >> tmp).fail()) {
215  ret.push_back(fromStr<T>(tmp));
216  }
217  /*
218  while(list.find_first_of(" ,") != std::string::npos) {
219  std::string entry = list.substr(0, list.find_first_of(" ,"));
220  ret.push_back(fromStr<T>(entry));
221  list = list.substr(entry.size());
222  if (list.find_first_of(" ,") == std::string::npos) {
223  entry = list.substr(0, list.find_first_of(" ,"));
224  ret.push_back(fromStr<T>(entry));
225  list = list.substr(entry.size());
226  }
227  }*/
228  return ret;
229 }
230 
231 template <typename string>
232 inline string repeat(string val, int count) {
233  string tmp;
234  for (int i = 0; i < count; ++i) {
235  tmp += val;
236  }
237  return tmp;
238 }
239 
240 inline std::string repeat(char val, int count) {
241  return std::string(count, val);
242 }
243 
244 #if !FRC_NO_BUILD
245 #include <algorithm>
246 #include <iterator>
247 template <typename Container, typename InputIt, typename UnaryFunction>
248 inline Container build(InputIt first, InputIt last, UnaryFunction f) {
249  Container out;
250  std::transform(first, last, std::back_inserter(out), f);
251  return out;
252 }
253 
254 template <typename Container, typename InputIt, typename InputIt2,
255  typename BinaryFunction>
256 inline Container build(InputIt first, InputIt last, InputIt2 first2,
257  BinaryFunction f) {
258  Container out;
259  std::transform(first, last, first2, std::back_inserter(out), f);
260  return out;
261 }
262 
263 template <typename Container, typename ExecutionPolicy, typename InputIt,
264  typename UnaryFunction>
265 inline Container build(ExecutionPolicy&& policy, InputIt first, InputIt last,
266  UnaryFunction f) {
267  Container out;
268  std::transform(policy, first, last, std::back_inserter(out), f);
269  return out;
270 }
271 
272 template <typename Container, typename ExecutionPolicy, typename InputIt,
273  typename InputIt2, typename BinaryFunction>
274 inline Container build(ExecutionPolicy&& policy, InputIt first, InputIt last,
275  InputIt2 first2, BinaryFunction f) {
276  Container out;
277  std::transform(policy, first, last, first2, std::back_inserter(out), f);
278  return out;
279 }
280 #endif
281 
282 template <typename Number>
283 constexpr inline int digitsOf(Number val) {
284  return std::ceil(std::log10(val));
285 }
286 
287 template <typename Number>
288 constexpr inline int digitsOf(Number val, int base) {
289  return std::ceil(std::log(val) / std::log(base));
290 }
291 
292 template <typename ForwardIterator>
293 inline int digitsList(ForwardIterator first, ForwardIterator last) {
294  return digitsOf(*std::max_element(first, last));
295 }
296 
297 template <typename ForwardIterator>
298 inline int digitsList(ForwardIterator first, ForwardIterator last, int base) {
299  return digitsOf(*std::max_element(first, last), base);
300 }
301 
302 #include <iomanip>
303 // Not working
304 template <typename ostream_type, typename ForwardIterator>
305 inline ostream_type& padList(ostream_type& os, ForwardIterator first,
306  ForwardIterator last, char fill = ' ',
307  int base = 10) {
308  // os<<std::setw(std::ceil(std::log(*std::max_element(first,
309  // last))/std::log(base)))<<std::setfill(fill);
310 
311  // save state of os
312  char fills = os.fill();
313  std::streamsize widths = os.width();
314 
315  os << std::setw(digitsList(first, last, base)) << std::setfill(fill);
316 
317  for (ForwardIterator it = first; it != last; ++it) {
318  os << ' ' << *it;
319  }
320  // restore state of os
321  os << std::setw(widths) << std::setfill(fills);
322  return os;
323 }
324 
325 // Consume all non-spaces to first break, then eat that, too
326 inline std::istream& eatWord(std::istream& is) {
327  do {
328  is.get();
329  } while (!isspace(is.peek()));
330  return is;
331 }
332 
333 // Eat spaces, don't eat an extra
334 inline std::istream& eatSpace(std::istream& is) {
335  while (isspace(is.peek()))
336  is.get();
337  return is;
338 }
339 
340 inline std::string url_encode(const std::string& value) {
341  std::ostringstream escaped;
342  escaped.fill('0');
343  escaped << std::hex;
344 
345  for (std::string::const_iterator i = value.begin(), n = value.end(); i != n;
346  ++i) {
347  std::string::value_type c = (*i);
348 
349  // Keep alphanumeric and other accepted characters intact
350  if (isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~') {
351  escaped << c;
352  continue;
353  }
354 
355  // Any other characters are percent-encoded
356  escaped << std::uppercase;
357  escaped << '%' << std::setw(2) << int((unsigned char)c);
358  escaped << std::nouppercase;
359  }
360 
361  return escaped.str();
362 }
363 
364 template <typename string>
365 inline std::string get_file_contents(string filename) {
366  std::ifstream in{};
367  in.exceptions(std::ios::badbit);
368  in.open(filename, std::ios::in | std::ios::binary);
369  std::string contents;
370  std::array<char, 128> buf;
371  while (in) {
372  in.read(buf.begin(), buf.size());
373  contents.append(buf.begin(), in.gcount());
374  }
375  return contents;
376 }
377 
378 template <typename T, typename F>
379 inline constexpr T quantizeRange(F min, F delta, F val) {
380  return static_cast<T>((val - min) * std::numeric_limits<T>::max() * delta);
381 }
382 
383 // Memnonic aids
384 
385 template <typename T>
386 using Ptr = T*;
387 
388 template <typename T>
389 using PtrToConst = T const*;
390 
391 template <typename T>
392 using ConstPtr = T* const;
393 
394 template <typename T>
395 using ConstPtrToConst = T const* const;
396 
397 #endif // SIMPLE_ALGORITHMS_H_INCLUDED