SpUtility.h 9.6 KB

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