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#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) \
50 case a: \
51 return #a
52
53namespace join
54{
55 namespace details
56 {
57 template <typename Type, size_t sz>
58 struct _byteswap
59 {
60 inline Type operator() ([[maybe_unused]] Type val)
61 {
62 throw std::out_of_range ("data size");
63 }
64 };
65
66 template <typename Type>
67 struct _byteswap<Type, 1>
68 {
69 inline Type operator() (Type val)
70 {
71 return val;
72 }
73 };
74
75 template <typename Type>
76 struct _byteswap<Type, 2>
77 {
78 inline Type operator() (Type val)
79 {
80 if (BYTE_ORDER == LITTLE_ENDIAN)
81 {
82 return (val >> 8) | (val << 8);
83 }
84 return val;
85 }
86 };
87
88 template <typename Type>
89 struct _byteswap<Type, 4>
90 {
91 inline Type operator() (Type val)
92 {
93 if (BYTE_ORDER == LITTLE_ENDIAN)
94 {
95 return ((val & 0xff000000) >> 24) | ((val & 0x00ff0000) >> 8) | ((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) | ((val & 0x00ff000000000000ull) >> 40) |
110 ((val & 0x0000ff0000000000ull) >> 24) | ((val & 0x000000ff00000000ull) >> 8) |
111 ((val & 0x00000000ff000000ull) << 8) | ((val & 0x0000000000ff0000ull) << 24) |
112 ((val & 0x000000000000ff00ull) << 40) | ((val & 0x00000000000000ffull) << 56);
113 }
114 return val;
115 }
116 };
117
118 template <>
119 struct _byteswap<float, 4>
120 {
121 inline float operator() (float val)
122 {
123 if (BYTE_ORDER == LITTLE_ENDIAN)
124 {
125 union
126 {
127 float f;
128 uint32_t i;
129 } tmp;
130
131 tmp.f = val;
133 return tmp.f;
134 }
135 return val;
136 }
137 };
138
139 template <>
140 struct _byteswap<double, 8>
141 {
142 inline double operator() (double val)
143 {
144 if (BYTE_ORDER == LITTLE_ENDIAN)
145 {
146 union
147 {
148 double f;
149 uint64_t i;
150 } tmp;
151
152 tmp.f = val;
154 return tmp.f;
155 }
156 return val;
157 }
158 };
159
160 template <class Type>
161 struct _swap
162 {
163 inline Type operator() (Type val)
164 {
165 return _byteswap<Type, sizeof (Type)> () (val);
166 }
167 };
168
170 {
171 bool operator() (const std::string& a, const std::string& b) const noexcept
172 {
173 return ::strcasecmp (a.c_str (), b.c_str ()) < 0;
174 }
175 };
176 }
177
183 template <class Type>
184 inline Type& swap (Type& val)
185 {
186 val = details::_swap<Type> () (val);
187 return val;
188 }
189
196 inline bool compareNoCase (const std::string& a, const std::string& b)
197 {
198 return ((a.size () == b.size ()) && std::equal (a.begin (), a.end (), b.begin (), [] (char c1, char c2) {
199 return std::toupper (c1) == std::toupper (c2);
200 }));
201 }
202
208 inline std::string& trimLeft (std::string& s)
209 {
210 return s.erase (0, s.find_first_not_of ("\f\t\v\r\n "));
211 }
212
218 inline std::string& trimRight (std::string& s)
219 {
220 return s.erase (s.find_last_not_of (" \f\t\v\r\n") + 1);
221 }
222
228 inline std::string& trim (std::string& s)
229 {
230 return trimLeft (trimRight (s));
231 }
232
240 inline std::string& replaceAll (std::string& str, const std::string& toReplace, const std::string& by)
241 {
242 size_t pos = 0;
243
244 while ((pos = str.find (toReplace, pos)) != std::string::npos)
245 {
246 str.replace (pos, toReplace.length (), by);
247 pos += by.length ();
248 }
249
250 return str;
251 }
252
259 inline std::vector<std::string> split (const std::string& in, const std::string& delim)
260 {
261 std::vector<std::string> tokens;
262 if (in.size ())
263 {
264 size_t beg = 0, end = in.find (delim);
265 size_t sz = delim.size ();
266 while (end != std::string::npos)
267 {
268 tokens.push_back (in.substr (beg, end - beg));
269 beg = end + sz;
270 end = in.find (delim, beg);
271 }
272 tokens.push_back (in.substr (beg));
273 }
274 return tokens;
275 }
276
283 inline std::vector<std::string> rsplit (const std::string& in, const std::string& delim)
284 {
285 std::vector<std::string> tokens;
286 if (in.size ())
287 {
288 size_t beg = in.rfind (delim), end = std::string::npos;
289 size_t sz = delim.size ();
290 while (beg != std::string::npos)
291 {
292 tokens.push_back (in.substr (beg + sz, end - beg - sz));
293 end = beg;
294 beg = in.rfind (delim, end - sz);
295 }
296 tokens.push_back (in.substr (0, end));
297 }
298 return tokens;
299 }
300
308 inline bool getline (std::istream& in, std::string& line, std::streamsize max = 1024)
309 {
310 line.clear ();
311
312 while (max--)
313 {
314 char ch = in.get ();
315 if (in.fail ())
316 {
317 return false;
318 }
319
320 if (ch == '\r')
321 {
322 continue;
323 }
324
325 if (ch == '\n')
326 {
327 return true;
328 }
329
330 line.push_back (ch);
331 }
332
334
335 return false;
336 }
337
345 inline bool getline (std::streambuf& in, std::string& line, std::streamsize max = 1024)
346 {
347 std::istream istream (&in);
348 return getline (istream, line, max);
349 }
350
356 inline void dump (const void* data, unsigned long size, std::ostream& out = std::cout)
357 {
358 const uint8_t* buf = reinterpret_cast<const uint8_t*> (data);
359
360 for (int i = 0; i < int (size); i += 16)
361 {
362 out << std::hex << std::uppercase << std::setw (8);
363 out << std::setfill ('0') << i << std::dec << ":";
364
365 for (int j = 0; j < 16; ++j)
366 {
367 if (j % 4 == 0)
368 out << std::dec << " ";
369
370 if (i + j < int (size))
371 {
372 out << std::hex << std::uppercase << std::setw (2);
373 out << std::setfill ('0') << static_cast<int> (buf[i + j]);
374 }
375 else
376 out << std::dec << " ";
377 }
378
379 out << std::dec << " ";
380
381 for (int j = 0; j < 16; ++j)
382 {
383 if (i + j < int (size))
384 {
385 if (isprint (buf[i + j]))
386 out << buf[i + j];
387 else
388 out << ".";
389 }
390 }
391
392 out << std::endl;
393 }
394
395 out << std::endl;
396 }
397
402 template <typename Type>
403 std::enable_if_t<std::numeric_limits<Type>::is_integer, Type> randomize ()
404 {
405 std::random_device rnd;
406 std::uniform_int_distribution<Type> dist{};
407 return dist (rnd);
408 }
409
416 template <class Func, class... Args>
417 std::chrono::milliseconds benchmark (Func&& func, Args&&... args)
418 {
419 auto beg = std::chrono::high_resolution_clock::now ();
420 func (std::forward<Args> (args)...);
421 auto end = std::chrono::high_resolution_clock::now ();
422 return std::chrono::duration_cast<std::chrono::milliseconds> (end - beg);
423 }
424
430 template <typename Clock, typename Duration>
431 struct timespec toTimespec (std::chrono::time_point<Clock, Duration> timePoint)
432 {
433 auto secs = std::chrono::time_point_cast<std::chrono::seconds> (timePoint);
434 auto ns = std::chrono::time_point_cast<std::chrono::nanoseconds> (timePoint) -
435 std::chrono::time_point_cast<std::chrono::nanoseconds> (secs);
436
437 auto scount = secs.time_since_epoch ().count ();
438 auto ncount = ns.count ();
439
440 return {.tv_sec = scount, .tv_nsec = ncount};
441 }
442}
443
444#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:356
Type & swap(Type &val)
swaps byte orders.
Definition utils.hpp:184
std::chrono::milliseconds benchmark(Func &&func, Args &&... args)
benchmark function call.
Definition utils.hpp:417
std::string & trim(std::string &s)
trim.
Definition utils.hpp:228
struct timespec toTimespec(std::chrono::time_point< Clock, Duration > timePoint)
converts time_point to timespec.
Definition utils.hpp:431
std::enable_if_t< std::numeric_limits< Type >::is_integer, Type > randomize()
create a random number.
Definition utils.hpp:403
bool compareNoCase(const std::string &a, const std::string &b)
case insensitive string comparison.
Definition utils.hpp:196
std::vector< std::string > split(const std::string &in, const std::string &delim)
split a string using a delimiter.
Definition utils.hpp:259
std::error_code make_error_code(join::Errc code) noexcept
Create an std::error_code object.
Definition error.cpp:150
thread_local std::error_code lastError
last error.
Definition error.cpp:32
std::string & trimLeft(std::string &s)
trim left.
Definition utils.hpp:208
bool getline(std::istream &in, std::string &line, std::streamsize max=1024)
read line (delimiter "\r\n").
Definition utils.hpp:308
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:283
std::string & replaceAll(std::string &str, const std::string &toReplace, const std::string &by)
replace all occurrences of a substring.
Definition utils.hpp:240
std::string & trimRight(std::string &s)
trim right.
Definition utils.hpp:218
Definition error.hpp:137
Definition utils.hpp:59
Type operator()(Type val)
Definition utils.hpp:60
Definition utils.hpp:162
Type operator()(Type val)
Definition utils.hpp:163
Definition utils.hpp:170
bool operator()(const std::string &a, const std::string &b) const noexcept
Definition utils.hpp:171