#ifndef _SP_UTILITIES_H__ #define _SP_UTILITIES_H__ #pragma once #include #include #include #include #include #include #include "toolkit.h" #include "ErrorCode.h" #include "SpBase.h" #include #ifndef ASSERT #include #define ASSERT assert #endif #define random(x) (rand() %x) inline static void InitializeRandomSeed(void) { srand((int)time(0)); } inline static int GetRandomDigit(int greatEqual, int lowerThan) { int c = random(lowerThan); while (c < greatEqual) { c = random(lowerThan); } return c; } namespace SP { namespace Utility { inline static int hex2int(const char c) { if (c >= '0' && c <= '9') return (c - '0'); if (c >= 'A' && c <= 'F') return (c - 'A' + 10); if (c >= 'a' && c <= 'f') return (c - 'a' + 10); return 0xFF; } inline bool IsStartWith(std::string const& s, std::string const& prefix) { return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); } inline bool IsStartWith(std::string const& s, char prefixChar) { return !s.empty() && s[0] == prefixChar; } inline bool IsEndWith(std::string const& s, std::string const& suffix) { return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); } inline bool IsEndWith(std::string const& s, char suffixChar) { return !s.empty() && s[s.size() - 1] == suffixChar; } inline bool IsContains(std::string const& s, std::string const& infix) { return s.find(infix) != std::string::npos; } inline bool IsNum(const std::string& value); inline char ToLowerCh(char c) { return static_cast(std::tolower(c)); } inline bool CheckIPv4(const std::string& value); inline void toLowerInPlace(std::string& s) { std::transform(s.begin(), s.end(), s.begin(), ToLowerCh); } inline std::string ToLower(std::string const& s) { std::string lc = s; toLowerInPlace(lc); return lc; } inline std::string ToUpper(const std::string str) { std::string dest; dest.resize(str.size()); std::transform(str.begin(), str.end(), dest.begin(), ::toupper); return dest; } inline std::string ToTrim(std::string const& str) { static char const* whitespaceChars = "\n\r\t "; std::string::size_type start = str.find_first_not_of(whitespaceChars); std::string::size_type end = str.find_last_not_of(whitespaceChars); return start != std::string::npos ? str.substr(start, 1 + end - start) : std::string(); } inline bool replaceInPlace(std::string& str, std::string const& replaceThis, std::string const& withThis) { bool replaced = false; std::size_t i = str.find(replaceThis); while (i != std::string::npos) { replaced = true; str = str.substr(0, i) + withThis + str.substr(i + replaceThis.size()); if (i < str.size() - withThis.size()) i = str.find(replaceThis, i + withThis.size()); else i = std::string::npos; } return replaced; } /** remembe to delete[] return value if not null*/ inline static char* HexStr2Bytes(const std::string& str) { const int sz = str.length(); char* ret = new char[sz / 2 + 1]; if (ret == NULL) { return NULL; } for (int i = 0; i < sz; i += 2) { ret[i / 2] = (char)(((hex2int(str[i])) << 4) | hex2int(str[i + 1])); } ret[sz / 2] = 0x00; return ret; } inline static std::string Bytes2HexStr(char* bytes, std::size_t byteLen) { std::string str(""); const std::string conv("0123456789ABCDEF"); for (std::size_t i = 0; i < byteLen; ++i) { int b = 0x0F & (bytes[i] >> 4); str.push_back(conv[b]); //str.append(1, conv[b]); b = 0x0F & (bytes[i]); str.push_back(conv[b]); //str.append(1, conv[b]); } return str; } template std::string fpToString(T value, int precision) { std::ostringstream oss; oss << std::setprecision(precision) << std::fixed << value; std::string d = oss.str(); std::size_t i = d.find_last_not_of('0'); if (i != std::string::npos && i != d.size() - 1) { if (d[i] == '.') i++; d = d.substr(0, i + 1); } return d; } inline static std::vector Split(std::string str, char splitElem) { std::vector strs; std::string::size_type pos1, pos2; pos2 = str.find(splitElem); pos1 = 0; while (std::string::npos != pos2) { strs.push_back(str.substr(pos1, pos2 - pos1)); pos1 = pos2 + 1; pos2 = str.find(splitElem, pos1); } strs.push_back(str.substr(pos1)); return strs; } inline std::string ExtractClassName(std::string const& className) { std::string strClassName = className; if(IsStartWith(strClassName, '&')) { std::size_t lastColons = strClassName.rfind("::"); std::size_t nextLastColons = strClassName.rfind("::", lastColons - 1); if (nextLastColons == std::string::npos) nextLastColons = 1; strClassName = strClassName.substr(nextLastColons, lastColons - nextLastColons); } return strClassName; } inline bool IsValidUrl(const std::string& value); SPBASE_API std::string W2S(const std::wstring wstr); SPBASE_API std::wstring S2W(const std::string str); SPBASE_API std::string GBK2UTF8(const std::string str); SPBASE_API std::string UTF8ToGBK(const std::string str); } namespace Toolkit { class CConditionVar; class CMutex { public: CMutex() :_in(false) { toolkit_mutex_init(&_mutex); } ~CMutex() { if (_in) { Leave(); } toolkit_mutex_destroy(&_mutex); } void Enter() { toolkit_mutex_lock(&_mutex); _in = true; } void Leave() { toolkit_mutex_unlock(&_mutex); _in = false; } bool TryEnter() { if (0 == toolkit_mutex_trylock(&_mutex)) { _in = true; return true; } return false; } friend class CConditionVar; private: toolkit_mutex_t _mutex; bool _in; }; class CUniqueLock { public: CUniqueLock(CMutex& m) : mutex_(m) { innerLock(); } ~CUniqueLock() { if (owns_) { innerUnlock(); } } private: void innerLock() { mutex_.Enter(); owns_ = true; } void innerUnlock() { owns_ = false; mutex_.Leave(); } CMutex& mutex_; bool owns_; }; class CConditionVar { public: CConditionVar(void) { toolkit_cond_init(&_cond); } ~CConditionVar(void) { toolkit_cond_destroy(&_cond); } void Signal() { toolkit_cond_signal(&_cond); } void Broadcast() { toolkit_cond_broadcast(&_cond); } void Wait(toolkit_mutex_t* mutex_) { toolkit_cond_wait(&_cond, mutex_); } void Wait(CMutex* mutex_) { toolkit_cond_wait(&_cond, &(mutex_->_mutex)); } bool WaitTimeout(toolkit_mutex_t* CMutex, uint64_t millisec) { int ret = -1; ret = toolkit_cond_timedwait(&_cond, CMutex, (uint64_t)(millisec * 1e6)); return ret == 0; } bool WaitTimeout(CMutex* mutex_, uint64_t millisec) { int ret = -1; ret = toolkit_cond_timedwait(&_cond, &(mutex_->_mutex), (uint64_t)(millisec * 1e6)); return ret == 0; } private: toolkit_cond_t _cond; }; class CConditionVarPlus { public: CConditionVarPlus(void) :_active(false) { toolkit_mutex_init(&_mutex); toolkit_cond_init(&_cond); } ~CConditionVarPlus(void) { toolkit_cond_destroy(&_cond); toolkit_mutex_destroy(&_mutex); } void Signal() { //it is usually considered a best practice to perform //the "signal"/"Signal" operation before releasing CMutex m if (!_active) { uint8_t times_ = 0; while (!_active && times_ < 3) { Sleep(100); times_++; } } toolkit_mutex_lock(&_mutex); toolkit_cond_signal(&_cond); _active = false; toolkit_mutex_unlock(&_mutex); } void Broadcast() { if (!_active) { uint8_t times_ = 0; while (!_active && times_ < 3) { Sleep(100); times_++; } } toolkit_mutex_lock(&_mutex); toolkit_cond_broadcast(&_cond); _active = false; toolkit_mutex_unlock(&_mutex); } void Wait() { ASSERT(_active == false); toolkit_mutex_lock(&_mutex); _active = true; toolkit_cond_wait(&_cond, &_mutex); toolkit_mutex_unlock(&_mutex); } bool WaitTimeout(uint64_t millisec) { int ret = -1; ASSERT(_active == false); toolkit_mutex_lock(&_mutex); _active = true; ret = toolkit_cond_timedwait(&_cond, &_mutex, (uint64_t)(millisec * 1e6)); toolkit_mutex_unlock(&_mutex); return ret == 0; } int TryWaitTimeout(uint64_t millisec) { int ret; if (0 == toolkit_mutex_trylock(&_mutex)) { _active = true; ret = toolkit_cond_timedwait(&_cond, &_mutex, (uint64_t)(millisec * 1e6)); if (ret == TOOLKIT_ETIMEDOUT) { ret = Error_TimeOut; _active = false; } toolkit_mutex_unlock(&_mutex); } else { ret = Error_Duplication; } return ret; } private: toolkit_mutex_t _mutex; toolkit_cond_t _cond; bool _active; }; class CSemaphore { public: CSemaphore(void) { toolkit_sem_init(&_sem, 0); } explicit CSemaphore(int init_value) { toolkit_sem_init(&_sem, init_value); } virtual ~CSemaphore() { toolkit_sem_destroy(&_sem); } void Signal() { toolkit_sem_post(&_sem); } void Wait() { toolkit_sem_wait(&_sem); } bool TryWait() { return toolkit_sem_trywait(&_sem) == 0; } private: toolkit_sem_t _sem; }; } } #endif //_SP_UTILITIES_H__