join 1.0
lightweight network framework library
Loading...
Searching...
No Matches
utils.hpp
Go to the documentation of this file.
1
25#ifndef __JOIN_UTILS_HPP__
26#define __JOIN_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#include <chrono>
39
40// C.
41#include <endian.h>
42#include <cstdint>
43#include <cstddef>
44#include <cstring>
45
46#define JOIN_LIKELY(x) __builtin_expect(!!(x), 1)
47#define JOIN_UNLIKELY(x) __builtin_expect(!!(x), 0)
48
49#define OUT_ENUM(a) case a : return #a
50
51namespace join
52{
53 namespace details
54 {
55 template <typename Type, size_t sz>
56 struct _byteswap
57 {
58 __inline__ Type operator() ([[maybe_unused]] Type val)
59 {
60 throw std::out_of_range ("data size");
61 }
62 };
63
64 template <typename Type>
65 struct _byteswap <Type, 1>
66 {
67 __inline__ Type operator() (Type val)
68 {
69 return val;
70 }
71 };
72
73 template <typename Type>
74 struct _byteswap <Type, 2>
75 {
76 __inline__ Type operator() (Type val)
77 {
78 if (BYTE_ORDER == LITTLE_ENDIAN)
79 {
80 return (val >> 8) | (val << 8);
81 }
82 return val;
83 }
84 };
85
86 template <typename Type>
87 struct _byteswap <Type, 4>
88 {
89 __inline__ Type operator() (Type val)
90 {
91 if (BYTE_ORDER == LITTLE_ENDIAN)
92 {
93 return ((val & 0xff000000) >> 24) |
94 ((val & 0x00ff0000) >> 8 ) |
95 ((val & 0x0000ff00) << 8 ) |
96 ((val & 0x000000ff) << 24);
97 }
98 return val;
99 }
100 };
101
102 template <typename Type>
103 struct _byteswap <Type, 8>
104 {
105 __inline__ Type operator() (Type val)
106 {
107 if (BYTE_ORDER == LITTLE_ENDIAN)
108 {
109 return ((val & 0xff00000000000000ull) >> 56) |
110 ((val & 0x00ff000000000000ull) >> 40) |
111 ((val & 0x0000ff0000000000ull) >> 24) |
112 ((val & 0x000000ff00000000ull) >> 8 ) |
113 ((val & 0x00000000ff000000ull) << 8 ) |
114 ((val & 0x0000000000ff0000ull) << 24) |
115 ((val & 0x000000000000ff00ull) << 40) |
116 ((val & 0x00000000000000ffull) << 56);
117 }
118 return val;
119 }
120 };
121
122 template <>
123 struct _byteswap <float, 4>
124 {
125 __inline__ float operator() (float val)
126 {
127 if (BYTE_ORDER == LITTLE_ENDIAN)
128 {
129 union { float f; uint32_t i; } tmp; tmp.f = val;
130 tmp.i = _byteswap <uint32_t, sizeof (uint32_t)> ()(tmp.i);
131 return tmp.f;
132 }
133 return val;
134 }
135 };
136
137 template<>
138 struct _byteswap <double, 8>
139 {
140 __inline__ double operator() (double val)
141 {
142 if (BYTE_ORDER == LITTLE_ENDIAN)
143 {
144 union { double f; uint64_t i; } tmp; tmp.f = val;
145 tmp.i = _byteswap <uint64_t, sizeof (uint64_t)> ()(tmp.i);
146 return tmp.f;
147 }
148 return val;
149 }
150 };
151
152 template <class Type>
153 struct _swap
154 {
155 __inline__ Type operator() (Type val)
156 {
157 return _byteswap <Type, sizeof (Type)> ()(val);
158 }
159 };
160
162 {
163 bool operator () (const std::string& a, const std::string& b) const noexcept
164 {
165 return ::strcasecmp (a.c_str (), b.c_str ()) < 0;
166 }
167 };
168 }
169
175 template <class Type>
176 __inline__ Type& swap (Type& val)
177 {
178 val = details::_swap <Type> ()(val);
179 return val;
180 }
181
188 __inline__ bool compareNoCase (const std::string& a, const std::string& b)
189 {
190 return ((a.size () == b.size ()) &&
191 std::equal (a.begin (), a.end (), b.begin (), [] (char c1, char c2) {return std::toupper (c1) == std::toupper (c2);}));
192 }
193
199 __inline__ std::string& trimLeft (std::string& s)
200 {
201 return s.erase (0, s.find_first_not_of ("\f\t\v\r\n "));
202 }
203
209 __inline__ std::string& trimRight (std::string& s)
210 {
211 return s.erase (s.find_last_not_of (" \f\t\v\r\n") + 1);
212 }
213
219 __inline__ std::string& trim (std::string& s)
220 {
221 return trimLeft (trimRight (s));
222 }
223
231 __inline__ std::string& replaceAll (std::string& str, const std::string &toReplace, const std::string &by)
232 {
233 size_t pos = 0;
234
235 while ((pos = str.find (toReplace, pos)) != std::string::npos)
236 {
237 str.replace (pos, toReplace.length (), by);
238 pos += by.length ();
239 }
240
241 return str;
242 }
243
250 __inline__ std::vector <std::string> split (const std::string& in, const std::string& delim)
251 {
252 std::vector <std::string> tokens;
253 if (in.size ())
254 {
255 size_t beg = 0, end = in.find (delim);
256 size_t sz = delim.size();
257 while (end != std::string::npos)
258 {
259 tokens.push_back (in.substr (beg, end - beg));
260 beg = end + sz;
261 end = in.find (delim, beg);
262 }
263 tokens.push_back (in.substr (beg));
264 }
265 return tokens;
266 }
267
274 __inline__ std::vector <std::string> rsplit (const std::string& in, const std::string& delim)
275 {
276 std::vector <std::string> tokens;
277 if (in.size ())
278 {
279 size_t beg = in.rfind (delim), end = std::string::npos;
280 size_t sz = delim.size();
281 while (beg != std::string::npos)
282 {
283 tokens.push_back (in.substr (beg + sz, end - beg - sz));
284 end = beg;
285 beg = in.rfind (delim, end - sz);
286 }
287 tokens.push_back (in.substr (0, end));
288 }
289 return tokens;
290 }
291
299 __inline__ bool getline (std::istream& in, std::string& line, std::streamsize max = 1024)
300 {
301 line.clear ();
302
303 while (max--)
304 {
305 char ch = in.get ();
306 if (in.fail ())
307 {
308 return false;
309 }
310
311 if (ch == '\r')
312 {
313 continue;
314 }
315
316 if (ch == '\n')
317 {
318 return true;
319 }
320
321 line.push_back (ch);
322 }
323
325
326 return false;
327 }
328
336 __inline__ bool getline (std::streambuf& in, std::string& line, std::streamsize max = 1024)
337 {
338 std::istream istream (&in);
339 return getline (istream, line, max);
340 }
341
347 __inline__ void dump (const void* data, unsigned long size, std::ostream& out = std::cout)
348 {
349 const uint8_t *buf = reinterpret_cast <const uint8_t *> (data);
350
351 for (int i = 0; i < int (size); i += 16)
352 {
353 out << std::hex << std::uppercase << std::setw (8);
354 out << std::setfill ('0') << i << std::dec << ":";
355
356 for (int j = 0; j < 16; ++j)
357 {
358 if (j % 4 == 0)
359 out << std::dec << " ";
360
361 if (i + j < int (size))
362 {
363 out << std::hex << std::uppercase << std::setw (2);
364 out << std::setfill ('0') << static_cast <int> (buf[i + j]);
365 }
366 else
367 out << std::dec << " ";
368 }
369
370 out << std::dec << " ";
371
372 for (int j = 0; j < 16; ++j)
373 {
374 if (i + j < int (size))
375 {
376 if (isprint (buf[i + j]))
377 out << buf[i + j];
378 else
379 out << ".";
380 }
381 }
382
383 out << std::endl;
384 }
385
386 out << std::endl;
387 }
388
393 template <typename Type>
394 std::enable_if_t <std::numeric_limits <Type>::is_integer, Type>
396 {
397 std::random_device rnd;
398 std::uniform_int_distribution <Type> dist {};
399 return dist (rnd);
400 }
401
408 template <class Func, class... Args>
409 std::chrono::milliseconds benchmark (Func&& func, Args&&... args)
410 {
411 auto beg = std::chrono::high_resolution_clock::now ();
412 func (std::forward <Args> (args)...);
413 auto end = std::chrono::high_resolution_clock::now ();
414 return std::chrono::duration_cast <std::chrono::milliseconds> (end - beg);
415 }
416
422 template <typename Clock, typename Duration>
423 struct timespec toTimespec (std::chrono::time_point <Clock, Duration> timePoint)
424 {
425 auto secs = std::chrono::time_point_cast <std::chrono::seconds> (timePoint);
426 auto ns = std::chrono::time_point_cast <std::chrono::nanoseconds> (timePoint) -
427 std::chrono::time_point_cast <std::chrono::nanoseconds> (secs);
428
429 auto scount = secs.time_since_epoch ().count ();
430 auto ncount = ns.count ();
431
432 return { .tv_sec = scount, .tv_nsec = ncount };
433 }
434}
435
436#endif
Definition acceptor.hpp:32
std::error_code make_error_code(join::Errc code)
Create an std::error_code object.
Definition error.cpp:154
__inline__ std::string & trimRight(std::string &s)
trim right.
Definition utils.hpp:209
__inline__ std::string & trim(std::string &s)
trim.
Definition utils.hpp:219
std::chrono::milliseconds benchmark(Func &&func, Args &&... args)
benchmark function call.
Definition utils.hpp:409
__inline__ std::vector< std::string > split(const std::string &in, const std::string &delim)
split a string using a delimiter.
Definition utils.hpp:250
struct timespec toTimespec(std::chrono::time_point< Clock, Duration > timePoint)
converts time_point to timespec.
Definition utils.hpp:423
std::enable_if_t< std::numeric_limits< Type >::is_integer, Type > randomize()
create a random number.
Definition utils.hpp:395
__inline__ std::string & replaceAll(std::string &str, const std::string &toReplace, const std::string &by)
replace all occurrences of a substring.
Definition utils.hpp:231
__inline__ Type & swap(Type &val)
swaps byte orders.
Definition utils.hpp:176
__inline__ 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:274
__inline__ bool getline(std::istream &in, std::string &line, std::streamsize max=1024)
read line (delimiter "\r\n").
Definition utils.hpp:299
__inline__ std::string & trimLeft(std::string &s)
trim left.
Definition utils.hpp:199
__inline__ bool compareNoCase(const std::string &a, const std::string &b)
case insensitive string comparison.
Definition utils.hpp:188
thread_local std::error_code lastError
last error.
Definition error.cpp:32
__inline__ void dump(const void *data, unsigned long size, std::ostream &out=std::cout)
dump data to standard output stream.
Definition utils.hpp:347
Definition error.hpp:106
Definition utils.hpp:57
__inline__ Type operator()(Type val)
Definition utils.hpp:58
Definition utils.hpp:154
__inline__ Type operator()(Type val)
Definition utils.hpp:155
Definition utils.hpp:162
bool operator()(const std::string &a, const std::string &b) const noexcept
Definition utils.hpp:163