SpUtility.h 9.8 KB

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