D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
opt
/
alt
/
php83
/
usr
/
include
/
php
/
ext
/
swoole
/
include
/
Filename :
swoole_util.h
back
Copy
/* +----------------------------------------------------------------------+ | Swoole | +----------------------------------------------------------------------+ | This source file is subject to version 2.0 of the Apache license, | | that is bundled with this package in the file LICENSE, and is | | available through the world-wide-web at the following url: | | http://www.apache.org/licenses/LICENSE-2.0.html | | If you did not receive a copy of the Apache2.0 license and are unable| | to obtain it through the world-wide-web, please send a note to | | license@swoole.com so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Tianfeng Han <rango@swoole.com> | | Twosee <twose@qq.com> | +----------------------------------------------------------------------+ */ #pragma once #include <cstdio> #include <cstdarg> #include <cassert> #include <ctime> #include <string> #include <memory> #include <chrono> #include <set> #include <vector> #include <stack> #include <thread> #include <type_traits> #include <algorithm> #define SW_STRUCT_MEMBER_SIZE(_s, _m) sizeof(std::declval<struct _s>()._m) namespace swoole { template <typename T> bool in_range(T value, std::initializer_list<T> allowed_values) { return std::find(allowed_values.begin(), allowed_values.end(), value) != allowed_values.end(); } namespace std_string { template <typename... Args> inline std::string format(const char *format, Args... args) { size_t size = snprintf(nullptr, 0, format, args...) + 1; // Extra space for '\0' std::unique_ptr<char[]> buf(new char[size]); snprintf(buf.get(), size, format, args...); return {buf.get(), buf.get() + size - 1}; // We don't want the '\0' inside } inline std::string vformat(const char *format, va_list args) { va_list _args; va_copy(_args, args); size_t size = vsnprintf(nullptr, 0, format, _args) + 1; // Extra space for '\0' va_end(_args); std::unique_ptr<char[]> buf(new char[size]); vsnprintf(buf.get(), size, format, args); return {buf.get(), buf.get() + size - 1}; // We don't want the '\0' inside } } // namespace std_string // Keep parameter 'steady' as false for backward compatibility. template <typename T> static inline long time(bool steady = false) { if (sw_likely(steady)) { auto now = std::chrono::steady_clock::now(); return std::chrono::duration_cast<T>(now.time_since_epoch()).count(); } else { auto now = std::chrono::system_clock::now(); return std::chrono::duration_cast<T>(now.time_since_epoch()).count(); } } static inline long get_timezone() { using namespace std::chrono; auto now_time_t = system_clock::to_time_t(system_clock::now()); std::tm local_tm{}; localtime_r(&now_time_t, &local_tm); return local_tm.tm_gmtoff; } class DeferTask { std::stack<Callback> list_; public: void add(const Callback &fn) { list_.push(fn); } ~DeferTask() { while (!list_.empty()) { auto fn = list_.top(); fn(nullptr); list_.pop(); } } }; template <typename Fun> class ScopeGuard { public: explicit ScopeGuard(Fun &&f) : _fun(std::forward<Fun>(f)), _active(true) {} ~ScopeGuard() { if (_active) { _fun(); } } void dismiss() { _active = false; } ScopeGuard() = delete; ScopeGuard(const ScopeGuard &) = delete; ScopeGuard &operator=(const ScopeGuard &) = delete; ScopeGuard(ScopeGuard &&rhs) noexcept : _fun(std::move(rhs._fun)), _active(rhs._active) { rhs.dismiss(); } private: Fun _fun; bool _active; }; class BitMap { uint64_t *array_; size_t n_bits_; static size_t get_array_size(size_t n_bits) { return (((n_bits) + 63) / 64 * 8); } size_t get_offset(size_t i) const { assert(i < n_bits_); /* (i / 64) */ return i >> 6; } static uint64_t to_int(const size_t i, const size_t offset) { return static_cast<uint64_t>(1) << (i - (offset << 6)); } public: explicit BitMap(const size_t n_bits) { assert(n_bits > 0); array_ = new uint64_t[get_array_size(n_bits)]; n_bits_ = n_bits; } ~BitMap() { delete[] array_; } void clear() const { memset(array_, 0, sizeof(uint64_t) * get_array_size(n_bits_)); } void set(const size_t i) const { const size_t off = get_offset(i); array_[off] |= to_int(i, off); } void unset(const size_t i) const { const size_t off = get_offset(i); array_[off] &= ~to_int(i, off); } bool get(const size_t i) const { const size_t off = get_offset(i); return array_[off] & to_int(i, off); } }; namespace detail { enum class ScopeGuardOnExit {}; template <typename Fun> inline ScopeGuard<Fun> operator+(ScopeGuardOnExit, Fun &&fn) { return ScopeGuard<Fun>(std::forward<Fun>(fn)); } } // namespace detail #define __SCOPE_GUARD_CONCATENATE_IMPL(s1, s2) s1##s2 #define __SCOPE_GUARD_CONCATENATE(s1, s2) __SCOPE_GUARD_CONCATENATE_IMPL(s1, s2) /** * Call the specified function when exiting the scope, similar to Golang's defer function. * After using this helper macro, * it is not necessary to manually release resources before the return statement of the failed branch. */ #define ON_SCOPE_EXIT \ auto __SCOPE_GUARD_CONCATENATE(ext_exitBlock_, __LINE__) = swoole::detail::ScopeGuardOnExit() + [&]() std::string intersection(const std::vector<std::string> &vec1, std::set<std::string> &vec2); static inline size_t ltrim(char **str, size_t len) { size_t i; for (i = 0; i < len; ++i) { if ('\0' != **str && isspace(**str)) { ++*str; } else { break; } } return len - i; } static inline size_t rtrim(char *str, size_t len) { for (size_t i = len; i > 0;) { if (isspace(str[--i])) { str[i] = 0; len--; } else { break; } } return len; } static inline size_t rtrim(const char *str, size_t len) { for (size_t i = len; i > 0;) { if (isspace(str[--i])) { len--; } else { break; } } return len; } static inline ssize_t substr_len(const char *str, size_t len, char separator, bool before = false) { const auto substr = static_cast<const char *>(memchr(str, separator, len)); if (substr == nullptr) { return -1; } return before ? substr - str : str + len - substr - 1; } static inline bool starts_with(const char *haystack, size_t l_haystack, const char *needle, size_t l_needle) { if (l_needle > l_haystack) { return false; } return memcmp(haystack, needle, l_needle) == 0; } static inline bool starts_with(const std::string &str, const std::string &prefix) { if (prefix.size() > str.size()) { return false; } return std::equal(prefix.begin(), prefix.end(), str.begin()); } static inline bool ends_with(const char *haystack, size_t l_haystack, const char *needle, size_t l_needle) { if (l_needle > l_haystack) { return false; } return memcmp(haystack + l_haystack - l_needle, needle, l_needle) == 0; } } // namespace swoole