SpUtility.h 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. #ifndef _SP_UTILITIES_H__
  2. #define _SP_UTILITIES_H__
  3. #pragma once
  4. #include <vector>
  5. #include <algorithm>
  6. #include <cctype>
  7. #include <iomanip>
  8. #include <sstream>
  9. #include <time.h>
  10. #include "toolkit.h"
  11. #include "ErrorCode.h"
  12. #include "SpBase.h"
  13. #ifdef _MSC_VER
  14. #define SP_SLEEP(ms) Sleep(ms)
  15. #else
  16. #include <unistd.h>
  17. #define SP_SLEEP(ms) usleep((ms) * 1000)
  18. #include <locale.h>
  19. #endif
  20. #ifndef ASSERT
  21. #include <assert.h>
  22. #define ASSERT assert
  23. #endif
  24. #define random(x) (rand() %x)
  25. inline static void InitializeRandomSeed(void)
  26. {
  27. srand((int)time(0));
  28. }
  29. inline static int GetRandomDigit(int greatEqual, int lowerThan)
  30. {
  31. int c = random(lowerThan);
  32. while (c < greatEqual) {
  33. c = random(lowerThan);
  34. }
  35. return c;
  36. }
  37. namespace SP {
  38. namespace Utility {
  39. inline static int hex2int(const char c)
  40. {
  41. if (c >= '0' && c <= '9') return (c - '0');
  42. if (c >= 'A' && c <= 'F') return (c - 'A' + 10);
  43. if (c >= 'a' && c <= 'f') return (c - 'a' + 10);
  44. return 0xFF;
  45. }
  46. inline bool IsStartWith(std::string const& s, std::string const& prefix)
  47. {
  48. return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
  49. }
  50. inline bool IsStartWith(std::string const& s, char prefixChar)
  51. {
  52. return !s.empty() && s[0] == prefixChar;
  53. }
  54. inline bool IsEndWith(std::string const& s, std::string const& suffix)
  55. {
  56. return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
  57. }
  58. inline bool IsEndWith(std::string const& s, char suffixChar)
  59. {
  60. return !s.empty() && s[s.size() - 1] == suffixChar;
  61. }
  62. inline bool IsContains(std::string const& s, std::string const& infix)
  63. {
  64. return s.find(infix) != std::string::npos;
  65. }
  66. inline char ToLowerCh(char c)
  67. {
  68. return static_cast<char>(std::tolower(c));
  69. }
  70. inline void toLowerInPlace(std::string& s)
  71. {
  72. std::transform(s.begin(), s.end(), s.begin(), ToLowerCh);
  73. }
  74. inline std::string ToLower(std::string const& s)
  75. {
  76. std::string lc = s;
  77. toLowerInPlace(lc);
  78. return lc;
  79. }
  80. inline std::string ToUpper(const std::string str)
  81. {
  82. std::string dest;
  83. dest.resize(str.size());
  84. std::transform(str.begin(), str.end(), dest.begin(), ::toupper);
  85. return dest;
  86. }
  87. inline std::string ToTrim(std::string const& str)
  88. {
  89. static char const* whitespaceChars = "\n\r\t ";
  90. std::string::size_type start = str.find_first_not_of(whitespaceChars);
  91. std::string::size_type end = str.find_last_not_of(whitespaceChars);
  92. return start != std::string::npos ? str.substr(start, 1 + end - start) : std::string();
  93. }
  94. inline bool replaceInPlace(std::string& str, std::string const& replaceThis, std::string const& withThis)
  95. {
  96. bool replaced = false;
  97. std::size_t i = str.find(replaceThis);
  98. while (i != std::string::npos) {
  99. replaced = true;
  100. str = str.substr(0, i) + withThis + str.substr(i + replaceThis.size());
  101. if (i < str.size() - withThis.size())
  102. i = str.find(replaceThis, i + withThis.size());
  103. else
  104. i = std::string::npos;
  105. }
  106. return replaced;
  107. }
  108. /** remembe to delete[] return value if not null*/
  109. inline static char* HexStr2Bytes(const std::string& str)
  110. {
  111. const int sz = str.length();
  112. char* ret = new char[sz / 2 + 1];
  113. if (ret == NULL) {
  114. return NULL;
  115. }
  116. for (int i = 0; i < sz; i += 2) {
  117. ret[i / 2] = (char)(((hex2int(str[i])) << 4) | hex2int(str[i + 1]));
  118. }
  119. ret[sz / 2] = 0x00;
  120. return ret;
  121. }
  122. inline static std::string Bytes2HexStr(char* bytes, std::size_t byteLen)
  123. {
  124. std::string str("");
  125. const std::string conv("0123456789ABCDEF");
  126. for (std::size_t i = 0; i < byteLen; ++i) {
  127. int b = 0x0F & (bytes[i] >> 4);
  128. str.push_back(conv[b]);
  129. //str.append(1, conv[b]);
  130. b = 0x0F & (bytes[i]);
  131. str.push_back(conv[b]);
  132. //str.append(1, conv[b]);
  133. }
  134. return str;
  135. }
  136. template<typename T>
  137. std::string fpToString(T value, int precision) {
  138. std::ostringstream oss;
  139. oss << std::setprecision(precision)
  140. << std::fixed
  141. << value;
  142. std::string d = oss.str();
  143. std::size_t i = d.find_last_not_of('0');
  144. if (i != std::string::npos && i != d.size() - 1) {
  145. if (d[i] == '.')
  146. i++;
  147. d = d.substr(0, i + 1);
  148. }
  149. return d;
  150. }
  151. inline static std::vector<std::string> Split(std::string str, char splitElem)
  152. {
  153. std::vector<std::string> strs;
  154. std::string::size_type pos1, pos2;
  155. pos2 = str.find(splitElem);
  156. pos1 = 0;
  157. while (std::string::npos != pos2) {
  158. strs.push_back(str.substr(pos1, pos2 - pos1));
  159. pos1 = pos2 + 1;
  160. pos2 = str.find(splitElem, pos1);
  161. }
  162. strs.push_back(str.substr(pos1));
  163. return strs;
  164. }
  165. inline std::string ExtractClassName(std::string const& className)
  166. {
  167. std::string strClassName = className;
  168. if(IsStartWith(strClassName, '&'))
  169. {
  170. std::size_t lastColons = strClassName.rfind("::");
  171. std::size_t nextLastColons = strClassName.rfind("::", lastColons - 1);
  172. if (nextLastColons == std::string::npos)
  173. nextLastColons = 1;
  174. strClassName = strClassName.substr(nextLastColons, lastColons - nextLastColons);
  175. }
  176. return strClassName;
  177. }
  178. SPBASE_API std::string W2S(const std::wstring wstr);
  179. SPBASE_API std::wstring S2W(const std::string str);
  180. SPBASE_API std::string GBK2UTF8(const std::string str);
  181. SPBASE_API std::string UTF8ToGBK(const std::string str);
  182. }
  183. namespace Toolkit {
  184. class CConditionVar;
  185. class CMutex
  186. {
  187. public:
  188. CMutex() :_in(false)
  189. {
  190. toolkit_mutex_init(&_mutex);
  191. }
  192. ~CMutex() {
  193. if (_in) { Leave(); }
  194. toolkit_mutex_destroy(&_mutex);
  195. }
  196. void Enter() {
  197. toolkit_mutex_lock(&_mutex);
  198. _in = true;
  199. }
  200. void Leave() {
  201. toolkit_mutex_unlock(&_mutex);
  202. _in = false;
  203. }
  204. bool TryEnter() {
  205. if (0 == toolkit_mutex_trylock(&_mutex)) {
  206. _in = true;
  207. return true;
  208. }
  209. return false;
  210. }
  211. friend class CConditionVar;
  212. private:
  213. toolkit_mutex_t _mutex;
  214. bool _in;
  215. };
  216. class CUniqueLock
  217. {
  218. public:
  219. CUniqueLock(CMutex& m) : mutex_(m)
  220. {
  221. innerLock();
  222. }
  223. ~CUniqueLock()
  224. {
  225. if (owns_) {
  226. innerUnlock();
  227. }
  228. }
  229. private:
  230. void innerLock()
  231. {
  232. mutex_.Enter();
  233. owns_ = true;
  234. }
  235. void innerUnlock()
  236. {
  237. owns_ = false;
  238. mutex_.Leave();
  239. }
  240. CMutex& mutex_;
  241. bool owns_;
  242. };
  243. class CConditionVar
  244. {
  245. public:
  246. CConditionVar(void) {
  247. toolkit_cond_init(&_cond);
  248. }
  249. ~CConditionVar(void) {
  250. toolkit_cond_destroy(&_cond);
  251. }
  252. void Signal() {
  253. toolkit_cond_signal(&_cond);
  254. }
  255. void Broadcast() {
  256. toolkit_cond_broadcast(&_cond);
  257. }
  258. void Wait(toolkit_mutex_t* mutex_) {
  259. toolkit_cond_wait(&_cond, mutex_);
  260. }
  261. void Wait(CMutex* mutex_) {
  262. toolkit_cond_wait(&_cond, &(mutex_->_mutex));
  263. }
  264. bool WaitTimeout(toolkit_mutex_t* CMutex, uint64_t millisec) {
  265. int ret = -1;
  266. ret = toolkit_cond_timedwait(&_cond, CMutex, (uint64_t)(millisec * 1e6));
  267. return ret == 0;
  268. }
  269. bool WaitTimeout(CMutex* mutex_, uint64_t millisec) {
  270. int ret = -1;
  271. ret = toolkit_cond_timedwait(&_cond, &(mutex_->_mutex), (uint64_t)(millisec * 1e6));
  272. return ret == 0;
  273. }
  274. private:
  275. toolkit_cond_t _cond;
  276. };
  277. class CConditionVarPlus
  278. {
  279. public:
  280. CConditionVarPlus(void) :_active(false) {
  281. toolkit_mutex_init(&_mutex);
  282. toolkit_cond_init(&_cond);
  283. }
  284. ~CConditionVarPlus(void) {
  285. toolkit_cond_destroy(&_cond);
  286. toolkit_mutex_destroy(&_mutex);
  287. }
  288. void Signal() {
  289. //it is usually considered a best practice to perform
  290. //the "signal"/"Signal" operation before releasing CMutex m
  291. if (!_active) {
  292. uint8_t times_ = 0;
  293. while (!_active && times_ < 3) {
  294. SP_SLEEP(100);
  295. times_++;
  296. }
  297. }
  298. toolkit_mutex_lock(&_mutex);
  299. toolkit_cond_signal(&_cond);
  300. _active = false;
  301. toolkit_mutex_unlock(&_mutex);
  302. }
  303. void Broadcast() {
  304. if (!_active) {
  305. uint8_t times_ = 0;
  306. while (!_active && times_ < 3) {
  307. SP_SLEEP(100);
  308. times_++;
  309. }
  310. }
  311. toolkit_mutex_lock(&_mutex);
  312. toolkit_cond_broadcast(&_cond);
  313. _active = false;
  314. toolkit_mutex_unlock(&_mutex);
  315. }
  316. void Wait() {
  317. ASSERT(_active == false);
  318. toolkit_mutex_lock(&_mutex);
  319. _active = true;
  320. toolkit_cond_wait(&_cond, &_mutex);
  321. toolkit_mutex_unlock(&_mutex);
  322. }
  323. bool WaitTimeout(uint64_t millisec) {
  324. int ret = -1;
  325. ASSERT(_active == false);
  326. toolkit_mutex_lock(&_mutex);
  327. _active = true;
  328. ret = toolkit_cond_timedwait(&_cond, &_mutex, (uint64_t)(millisec * 1e6));
  329. toolkit_mutex_unlock(&_mutex);
  330. return ret == 0;
  331. }
  332. int TryWaitTimeout(uint64_t millisec) {
  333. int ret;
  334. if (0 == toolkit_mutex_trylock(&_mutex)) {
  335. _active = true;
  336. ret = toolkit_cond_timedwait(&_cond, &_mutex, (uint64_t)(millisec * 1e6));
  337. if (ret == TOOLKIT_ETIMEDOUT) {
  338. ret = Error_TimeOut;
  339. _active = false;
  340. }
  341. toolkit_mutex_unlock(&_mutex);
  342. }
  343. else {
  344. ret = Error_Duplication;
  345. }
  346. return ret;
  347. }
  348. private:
  349. toolkit_mutex_t _mutex;
  350. toolkit_cond_t _cond;
  351. bool _active;
  352. };
  353. class CSemaphore
  354. {
  355. public:
  356. CSemaphore(void)
  357. {
  358. toolkit_sem_init(&_sem, 0);
  359. }
  360. explicit CSemaphore(int init_value)
  361. {
  362. toolkit_sem_init(&_sem, init_value);
  363. }
  364. virtual ~CSemaphore()
  365. {
  366. toolkit_sem_destroy(&_sem);
  367. }
  368. void Signal()
  369. {
  370. toolkit_sem_post(&_sem);
  371. }
  372. void Wait()
  373. {
  374. toolkit_sem_wait(&_sem);
  375. }
  376. bool TryWait()
  377. {
  378. return toolkit_sem_trywait(&_sem) == 0;
  379. }
  380. private:
  381. toolkit_sem_t _sem;
  382. };
  383. }
  384. }
  385. #endif //_SP_UTILITIES_H__