25#ifndef JOIN_CORE_UTILS_HPP
26#define JOIN_CORE_UTILS_HPP
48#define JOIN_ALWAYS_INLINE inline __attribute__ ((always_inline))
50#define JOIN_LIKELY(x) __builtin_expect (!!(x), 1)
51#define JOIN_UNLIKELY(x) __builtin_expect (!!(x), 0)
63 bool operator() (
const std::string& a,
const std::string& b)
const noexcept
65 return ::strcasecmp (a.c_str (), b.c_str ()) < 0;
74 template <
typename Exception,
typename... Args>
75 [[noreturn]]
__attribute__ ((cold, noinline))
void throwException (Args&&... args)
77 throw Exception (std::forward<Args> (args)...);
86 inline Type&
swap (Type& val)
87 requires (std::is_arithmetic_v<Type> &&
sizeof (Type) <=
sizeof (uint64_t))
89 if constexpr (std::endian::native == std::endian::little)
91 if constexpr (
sizeof (Type) ==
sizeof (uint16_t))
93 val = std::bit_cast<Type> (__builtin_bswap16 (std::bit_cast<uint16_t> (val)));
95 else if constexpr (
sizeof (Type) ==
sizeof (uint32_t))
97 val = std::bit_cast<Type> (__builtin_bswap32 (std::bit_cast<uint32_t> (val)));
99 else if constexpr (
sizeof (Type) ==
sizeof (uint64_t))
101 val = std::bit_cast<Type> (__builtin_bswap64 (std::bit_cast<uint64_t> (val)));
115 return ((a.size () == b.size ()) && std::equal (a.begin (), a.end (), b.begin (), [] (
char c1,
char c2) {
116 return std::toupper (c1) == std::toupper (c2);
127 return s.erase (0, s.find_first_not_of (
"\f\t\v\r\n "));
137 return s.erase (s.find_last_not_of (
" \f\t\v\r\n") + 1);
145 inline std::string&
trim (std::string& s)
157 inline std::string&
replaceAll (std::string& str,
const std::string& toReplace,
const std::string& by)
161 while ((pos = str.find (toReplace, pos)) != std::string::npos)
163 str.replace (pos, toReplace.length (), by);
176 inline std::vector<std::string>
split (
const std::string& in,
const std::string& delim)
178 std::vector<std::string> tokens;
181 size_t beg = 0, end = in.find (delim);
182 size_t sz = delim.size ();
183 while (end != std::string::npos)
185 tokens.push_back (in.substr (beg, end - beg));
187 end = in.find (delim, beg);
189 tokens.push_back (in.substr (beg));
200 inline std::vector<std::string>
rsplit (
const std::string& in,
const std::string& delim)
202 std::vector<std::string> tokens;
205 size_t beg = in.rfind (delim), end = std::string::npos;
206 size_t sz = delim.size ();
207 while (beg != std::string::npos)
209 tokens.push_back (in.substr (beg + sz, end - beg - sz));
211 beg = in.rfind (delim, end - sz);
213 tokens.push_back (in.substr (0, end));
225 inline bool getline (std::istream& in, std::string& line, std::streamsize max = 1024)
262 inline bool getline (std::streambuf& in, std::string& line, std::streamsize max = 1024)
264 std::istream istream (&in);
265 return getline (istream, line, max);
276 inline bool readBytes (
const char*& cur,
const char* end,
void* out,
size_t size)
noexcept
278 if (size >
static_cast<size_t> (end - cur))
284 ::memcpy (out, cur, size);
298 inline bool writeBytes (
char*& cur,
const char* end,
const void* in,
size_t size)
noexcept
300 if (size >
static_cast<size_t> (end - cur))
306 ::memcpy (cur, in, size);
319 inline uint16_t
checksum (
const uint16_t* data,
size_t len, uint16_t current = 0) noexcept
321 uint32_t sum = current;
331 if constexpr (std::endian::native == std::endian::little)
333 sum += *
reinterpret_cast<const uint8_t*
> (data);
337 sum += *
reinterpret_cast<const uint8_t*
> (data) << 8;
341 sum = (sum >> 16) + (sum & 0xffff);
344 return static_cast<uint16_t
> (~sum);
352 inline void dump (
const void* data,
unsigned long size, std::ostream& out = std::cout)
354 const uint8_t* buf =
reinterpret_cast<const uint8_t*
> (data);
355 std::ostringstream oss;
357 for (
int i = 0; i < int (size); i += 16)
359 oss << std::hex << std::uppercase << std::setw (8);
360 oss << std::setfill (
'0') << i << std::dec <<
":";
362 for (
int j = 0; j < 16; ++j)
365 oss << std::dec <<
" ";
367 if (i + j <
int (size))
369 oss << std::hex << std::uppercase << std::setw (2);
370 oss << std::setfill ('0') << static_cast<int> (buf[i + j]);
373 oss << std::dec <<
" ";
376 oss << std::dec <<
" ";
378 for (
int j = 0; j < 16; ++j)
380 if (i + j <
int (size))
382 if (isprint (buf[i + j]))
394 out << oss.str () << std::flush;
401 template <
typename Type>
404 static_assert (std::is_integral_v<Type>,
"randomize requires an integral type");
405 thread_local std::random_device rnd;
406 std::uniform_int_distribution<Type> dist{};
416 template <
class Func,
class... Args>
417 std::chrono::milliseconds
benchmark (Func&& func, Args&&... args)
419 auto beg = std::chrono::steady_clock::now ();
420 func (std::forward<Args> (args)...);
421 auto end = std::chrono::steady_clock::now ();
422 return std::chrono::duration_cast<std::chrono::milliseconds> (end - beg);
430 template <
typename Clock,
typename Duration>
431 struct timespec
toTimespec (
std::chrono::time_point<Clock, Duration> timePoint)
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);
437 auto scount = secs.time_since_epoch ().count ();
438 auto ncount = ns.count ();
440 return {.tv_sec = scount, .tv_nsec = ncount};
448 template <
typename Rep,
typename Period>
451 auto secs = std::chrono::duration_cast<std::chrono::seconds> (duration);
452 auto ns = std::chrono::duration_cast<std::chrono::nanoseconds> (duration - secs);
454 auto scount = secs.count ();
455 auto ncount = ns.count ();
457 return {.tv_sec = scount, .tv_nsec = ncount};
465 constexpr bool isPow2 (uint64_t value)
noexcept
467 return (value != 0) && ((value & (value - 1)) == 0);
475 constexpr uint64_t
nextPow2 (uint64_t value)
noexcept
487 value |= value >> 16;
488 value |= value >> 32;
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:352
constexpr bool isPow2(uint64_t value) noexcept
check if a value is a power of two.
Definition utils.hpp:465
__attribute__((cold, noinline)) void throwException(Args &&... args)
throw an exception out of the hot path.
Definition utils.hpp:75
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:145
Type & swap(Type &val)
swaps byte orders.
Definition utils.hpp:86
struct timespec toTimespec(std::chrono::time_point< Clock, Duration > timePoint)
converts time_point to timespec.
Definition utils.hpp:431
constexpr uint64_t nextPow2(uint64_t value) noexcept
round up to the next power of two.
Definition utils.hpp:475
bool readBytes(const char *&cur, const char *end, void *out, size_t size) noexcept
read bytes from a buffer.
Definition utils.hpp:276
uint16_t checksum(const uint16_t *data, size_t len, uint16_t current=0) noexcept
get standard 1s complement checksum.
Definition utils.hpp:319
bool compareNoCase(const std::string &a, const std::string &b)
case insensitive string comparison.
Definition utils.hpp:113
Type randomize()
create a random number.
Definition utils.hpp:402
std::vector< std::string > split(const std::string &in, const std::string &delim)
split a string using a delimiter.
Definition utils.hpp:176
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:125
bool getline(std::istream &in, std::string &line, std::streamsize max=1024)
read line (delimiter "\r\n").
Definition utils.hpp:225
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:200
bool writeBytes(char *&cur, const char *end, const void *in, size_t size) noexcept
write bytes to a buffer.
Definition utils.hpp:298
std::string & replaceAll(std::string &str, const std::string &toReplace, const std::string &by)
replace all occurrences of a substring.
Definition utils.hpp:157
std::string & trimRight(std::string &s)
trim right.
Definition utils.hpp:135
bool operator()(const std::string &a, const std::string &b) const noexcept
Definition utils.hpp:63