join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1
25#ifndef JOIN_CORE_UTILS_HPP
26#define JOIN_CORE_UTILS_HPP
27
28// libjoin.
29#include <join/error.hpp>
30
31// C++.
32#include <stdexcept>
33#include <iostream>
34#include <iomanip>
35#include <chrono>
36#include <random>
37#include <limits>
38
39// C.
40#include <endian.h>
41#include <cstdint>
42#include <cstddef>
43#include <cstring>
44
45#define JOIN_LIKELY(x) __builtin_expect (!!(x), 1)
46#define JOIN_UNLIKELY(x) __builtin_expect (!!(x), 0)
47
48#define OUT_ENUM(a) \
49 case a: \
50 return #a
51
52namespace join
53{
54 namespace details
55 {
56 template <typename Type, size_t sz>
57 struct _byteswap
58 {
59 inline Type operator() ([[maybe_unused]] Type val)
60 {
61 throw std::out_of_range ("data size");
62 }
63 };
64
65 template <typename Type>
66 struct _byteswap<Type, 1>
67 {
68 inline Type operator() (Type val)
69 {
70 return val;
71 }
72 };
73
74 template <typename Type>
75 struct _byteswap<Type, 2>
76 {
77 inline Type operator() (Type val)
78 {
79 if (BYTE_ORDER == LITTLE_ENDIAN)
80 {
81 return (val >> 8) | (val << 8);
82 }
83 return val;
84 }
85 };
86
87 template <typename Type>
88 struct _byteswap<Type, 4>
89 {
90 inline Type operator() (Type val)
91 {
92 if (BYTE_ORDER == LITTLE_ENDIAN)
93 {
94 return ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((val & 0x0000ff00) << 8) |
95 ((val & 0x000000ff) << 24);
96 }
97 return val;
98 }
99 };
100
101 template <typename Type>
102 struct _byteswap<Type, 8>
103 {
104 inline Type operator() (Type val)
105 {
106 if (BYTE_ORDER == LITTLE_ENDIAN)
107 {
108 return ((val & 0xff00000000000000ull) >> 56) | ((val & 0x00ff000000000000ull) >> 40) |
109 ((val & 0x0000ff0000000000ull) >> 24) | ((val & 0x000000ff00000000ull) >> 8) |
110 ((val & 0x00000000ff000000ull) << 8) | ((val & 0x0000000000ff0000ull) << 24) |
111 ((val & 0x000000000000ff00ull) << 40) | ((val & 0x00000000000000ffull) << 56);
112 }
113 return val;
114 }
115 };
116
117 template <>
118 struct _byteswap<float, 4>
119 {
120 inline float operator() (float val)
121 {
122 if (BYTE_ORDER == LITTLE_ENDIAN)
123 {
124 union
125 {
126 float f;
127 uint32_t i;
128 } tmp;
129
130 tmp.f = val;
132 return tmp.f;
133 }
134 return val;
135 }
136 };
137
138 template <>
139 struct _byteswap<double, 8>
140 {
141 inline double operator() (double val)
142 {
143 if (BYTE_ORDER == LITTLE_ENDIAN)
144 {
145 union
146 {
147 double f;
148 uint64_t i;
149 } tmp;
150
151 tmp.f = val;
153 return tmp.f;
154 }
155 return val;
156 }
157 };
158
159 template <class Type>
160 struct _swap
161 {
162 inline Type operator() (Type val)
163 {
164 return _byteswap<Type, sizeof (Type)> () (val);
165 }
166 };
167
169 {
170 bool operator() (const std::string& a, const std::string& b) const noexcept
171 {
172 return ::strcasecmp (a.c_str (), b.c_str ()) < 0;
173 }
174 };
175 }
176
182 template <class Type>
183 inline Type& swap (Type& val)
184 {
185 val = details::_swap<Type> () (val);
186 return val;
187 }
188
195 inline bool compareNoCase (const std::string& a, const std::string& b)
196 {
197 return ((a.size () == b.size ()) && std::equal (a.begin (), a.end (), b.begin (), [] (char c1, char c2) {
198 return std::toupper (c1) == std::toupper (c2);
199 }));
200 }
201
207 inline std::string& trimLeft (std::string& s)
208 {
209 return s.erase (0, s.find_first_not_of ("\f\t\v\r\n "));
210 }
211
217 inline std::string& trimRight (std::string& s)
218 {
219 return s.erase (s.find_last_not_of (" \f\t\v\r\n") + 1);
220 }
221
227 inline std::string& trim (std::string& s)
228 {
229 return trimLeft (trimRight (s));
230 }
231
239 inline std::string& replaceAll (std::string& str, const std::string& toReplace, const std::string& by)
240 {
241 size_t pos = 0;
242
243 while ((pos = str.find (toReplace, pos)) != std::string::npos)
244 {
245 str.replace (pos, toReplace.length (), by);
246 pos += by.length ();
247 }
248
249 return str;
250 }
251
258 inline std::vector<std::string> split (const std::string& in, const std::string& delim)
259 {
260 std::vector<std::string> tokens;
261 if (in.size ())
262 {
263 size_t beg = 0, end = in.find (delim);
264 size_t sz = delim.size ();
265 while (end != std::string::npos)
266 {
267 tokens.push_back (in.substr (beg, end - beg));
268 beg = end + sz;
269 end = in.find (delim, beg);
270 }
271 tokens.push_back (in.substr (beg));
272 }
273 return tokens;
274 }
275
282 inline std::vector<std::string> rsplit (const std::string& in, const std::string& delim)
283 {
284 std::vector<std::string> tokens;
285 if (in.size ())
286 {
287 size_t beg = in.rfind (delim), end = std::string::npos;
288 size_t sz = delim.size ();
289 while (beg != std::string::npos)
290 {
291 tokens.push_back (in.substr (beg + sz, end - beg - sz));
292 end = beg;
293 beg = in.rfind (delim, end - sz);
294 }
295 tokens.push_back (in.substr (0, end));
296 }
297 return tokens;
298 }
299
307 inline bool getline (std::istream& in, std::string& line, std::streamsize max = 1024)
308 {
309 line.clear ();
310
311 while (max--)
312 {
313 char ch = in.get ();
314 if (in.fail ())
315 {
316 return false;
317 }
318
319 if (ch == '\r')
320 {
321 continue;
322 }
323
324 if (ch == '\n')
325 {
326 return true;
327 }
328
329 line.push_back (ch);
330 }
331
333
334 return false;
335 }
336
344 inline bool getline (std::streambuf& in, std::string& line, std::streamsize max = 1024)
345 {
346 std::istream istream (&in);
347 return getline (istream, line, max);
348 }
349
357 inline uint16_t checksum (const uint16_t* data, size_t len, uint16_t current = 0) noexcept
358 {
359 uint32_t sum = current;
360
361 while (len > 1)
362 {
363 sum += *data++;
364 len -= 2;
365 }
366
367 if (len == 1)
368 {
369#if __BYTE_ORDER == __LITTLE_ENDIAN
370 sum += *reinterpret_cast<const uint8_t*> (data);
371#else
372 sum += *reinterpret_cast<const uint8_t*> (data) << 8;
373#endif
374 }
375
376 sum = (sum >> 16) + (sum & 0xffff);
377 sum += (sum >> 16);
378
379 return static_cast<uint16_t> (~sum);
380 }
381
387 inline void dump (const void* data, unsigned long size, std::ostream& out = std::cout)
388 {
389 const uint8_t* buf = reinterpret_cast<const uint8_t*> (data);
390
391 for (int i = 0; i < int (size); i += 16)
392 {
393 out << std::hex << std::uppercase << std::setw (8);
394 out << std::setfill ('0') << i << std::dec << ":";
395
396 for (int j = 0; j < 16; ++j)
397 {
398 if (j % 4 == 0)
399 out << std::dec << " ";
400
401 if (i + j < int (size))
402 {
403 out << std::hex << std::uppercase << std::setw (2);
404 out << std::setfill ('0') << static_cast<int> (buf[i + j]);
405 }
406 else
407 out << std::dec << " ";
408 }
409
410 out << std::dec << " ";
411
412 for (int j = 0; j < 16; ++j)
413 {
414 if (i + j < int (size))
415 {
416 if (isprint (buf[i + j]))
417 out << buf[i + j];
418 else
419 out << ".";
420 }
421 }
422
423 out << std::endl;
424 }
425
426 out << std::endl;
427 }
428
433 template <typename Type>
434 std::enable_if_t<std::numeric_limits<Type>::is_integer, Type> randomize ()
435 {
436 std::random_device rnd;
437 std::uniform_int_distribution<Type> dist{};
438 return dist (rnd);
439 }
440
447 template <class Func, class... Args>
448 std::chrono::milliseconds benchmark (Func&& func, Args&&... args)
449 {
450 auto beg = std::chrono::steady_clock::now ();
451 func (std::forward<Args> (args)...);
452 auto end = std::chrono::steady_clock::now ();
453 return std::chrono::duration_cast<std::chrono::milliseconds> (end - beg);
454 }
455
461 template <typename Clock, typename Duration>
462 struct timespec toTimespec (std::chrono::time_point<Clock, Duration> timePoint)
463 {
464 auto secs = std::chrono::time_point_cast<std::chrono::seconds> (timePoint);
465 auto ns = std::chrono::time_point_cast<std::chrono::nanoseconds> (timePoint) -
466 std::chrono::time_point_cast<std::chrono::nanoseconds> (secs);
467
468 auto scount = secs.time_since_epoch ().count ();
469 auto ncount = ns.count ();
470
471 return {.tv_sec = scount, .tv_nsec = ncount};
472 }
473
479 template <typename Rep, typename Period>
480 struct timespec toTimespec (std::chrono::duration<Rep, Period> duration)
481 {
482 auto secs = std::chrono::duration_cast<std::chrono::seconds> (duration);
483 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (duration - secs);
484
485 auto scount = secs.count ();
486 auto ncount = ns.count ();
487
488 return {.tv_sec = scount, .tv_nsec = ncount};
489 }
490
496 constexpr bool isPow2 (uint64_t value) noexcept
497 {
498 return (value != 0) && ((value & (value - 1)) == 0);
499 }
500
506 constexpr uint64_t nextPow2 (uint64_t value) noexcept
507 {
508 if (value == 0)
509 {
510 return 1;
511 }
512
513 value--;
514 value |= value >> 1;
515 value |= value >> 2;
516 value |= value >> 4;
517 value |= value >> 8;
518 value |= value >> 16;
519 value |= value >> 32;
520
521 return value + 1;
522 }
523}
524
525#endif
Definition acceptor.hpp:32
void dump(const void *data, unsigned long size, std::ostream &out=std::cout)
dump data to standard output stream.
Definition utils.hpp:387
constexpr bool isPow2(uint64_t value) noexcept
check if a value is a power of two.
Definition utils.hpp:496
Type & swap(Type &val)
swaps byte orders.
Definition utils.hpp:183
std::chrono::milliseconds benchmark(Func &&func, Args &&... args)
benchmark function call.
Definition utils.hpp:448
std::string & trim(std::string &s)
trim.
Definition utils.hpp:227
struct timespec toTimespec(std::chrono::time_point< Clock, Duration > timePoint)
converts time_point to timespec.
Definition utils.hpp:462
std::enable_if_t< std::numeric_limits< Type >::is_integer, Type > randomize()
create a random number.
Definition utils.hpp:434
constexpr uint64_t nextPow2(uint64_t value) noexcept
round up to the next power of two.
Definition utils.hpp:506
uint16_t checksum(const uint16_t *data, size_t len, uint16_t current=0) noexcept
get standard 1s complement checksum.
Definition utils.hpp:357
bool compareNoCase(const std::string &a, const std::string &b)
case insensitive string comparison.
Definition utils.hpp:195
std::vector< std::string > split(const std::string &in, const std::string &delim)
split a string using a delimiter.
Definition utils.hpp:258
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:195
thread_local std::error_code lastError
last error.
Definition error.cpp:32
std::string & trimLeft(std::string &s)
trim left.
Definition utils.hpp:207
bool getline(std::istream &in, std::string &line, std::streamsize max=1024)
read line (delimiter "\r\n").
Definition utils.hpp:307
std::vector< std::string > rsplit(const std::string &in, const std::string &delim)
split a string in reverse order using a delimiter.
Definition utils.hpp:282
std::string & replaceAll(std::string &str, const std::string &toReplace, const std::string &by)
replace all occurrences of a substring.
Definition utils.hpp:239
std::string & trimRight(std::string &s)
trim right.
Definition utils.hpp:217
Definition error.hpp:144
Definition utils.hpp:58
Type operator()(Type val)
Definition utils.hpp:59
Definition utils.hpp:161
Type operator()(Type val)
Definition utils.hpp:162
Definition utils.hpp:169
bool operator()(const std::string &a, const std::string &b) const noexcept
Definition utils.hpp:170