2
0

StringUtils.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. #pragma once
  2. #include "Defines.h"
  3. #include <cstring>
  4. #include <string>
  5. #include <sstream>
  6. #include <ctime>
  7. #include <algorithm>
  8. namespace gameplay
  9. {
  10. class GP_API StringUtils
  11. {
  12. public:
  13. /**
  14. * Checks if the string begins with the given prefix.
  15. *
  16. * @param str a non-null pointer to the 0-terminated string.
  17. * @param prefix a non-null pointer to the 0-terminated prefix.
  18. * @return true if the string begins with provided prefix, false otherwise.
  19. */
  20. static inline bool starts_with(const char* str, const char* prefix);
  21. /**
  22. * Checks if the string begins with the given prefix.
  23. *
  24. * @param str a non-null pointer to the 0-terminated string.
  25. * @param prefix a const reference the std::string prefix.
  26. * @return true if the string begins with provided prefix, false otherwise.
  27. */
  28. inline bool starts_with(const char* str, const std::string& prefix);
  29. /**
  30. * Checks if the string begins with the given prefix.
  31. *
  32. * @param str a const reference to the std::string object.
  33. * @param prefix a non-null pointer to the 0-terminated prefix.
  34. * @return true if the string begins with provided prefix, false otherwise.
  35. */
  36. static inline bool starts_with(const std::string& str, const char* prefix);
  37. /**
  38. * Checks if the string begins with the given prefix.
  39. *
  40. * @param str a const reference to the std::string object.
  41. * @param prefix a const reference to the std::string prefix.
  42. *
  43. * @return true if the string begins with provided prefix, false otherwise.
  44. */
  45. static inline bool starts_with(const std::string& str, const std::string& prefix);
  46. /**
  47. * Checks if the string ends with the given suffix.
  48. *
  49. * @param[in] str a non-null pointer to the 0-terminated string.
  50. * @param[in] prefix a non-null pointer to the 0-terminated suffix.
  51. *
  52. * @return true if the string ends with provided suffix, false otherwise.
  53. */
  54. static inline bool ends_with(const char* str, const char* suffix);
  55. /**
  56. * Checks if the string ends with the given suffix.
  57. *
  58. * @param str a non-null pointer to the 0-terminated string.
  59. * @param prefix a const reference to the std::string suffix.
  60. * @return true if the string ends with provided suffix, false otherwise.
  61. */
  62. static inline bool ends_with(const char* str, const std::string& suffix);
  63. /**
  64. * Checks if the string ends with the given suffix.
  65. *
  66. * @param str a const reference to the std::string object.
  67. * @param prefix a non-null pointer to the 0-terminated suffix.
  68. * @return true if the string ends with provided suffix, false otherwise.
  69. */
  70. static inline bool ends_with(const std::string& str, const char* suffix);
  71. /**
  72. * Checks if the string ends with the given suffix.
  73. *
  74. * @param str a const reference to the std::string object.
  75. * @param prefix a const reference to the std::string suffix.
  76. * @return true if the string ends with provided suffix, false otherwise.
  77. */
  78. static inline bool ends_with(const std::string& str, const std::string& suffix);
  79. /**
  80. * Splits a string with a specified delimter string into a std::vector or std::strings.
  81. *
  82. * @param str The string to split.
  83. * @param delimiter The delimter character to split on.
  84. * @return The vector of string that have been split.
  85. */
  86. static inline std::vector<std::string> split(const std::string& str, char delimiter);
  87. /**
  88. * Converts a string to lowercase
  89. *
  90. * @param str The string to be converted to lowercase.
  91. */
  92. static inline void to_lower(std::string& str);
  93. /**
  94. * Converts a string to uppercase
  95. *
  96. * @param str The string to be converted to uppercase.
  97. */
  98. static void to_upper(std::string& str);
  99. /**
  100. * Trims any white space to the left of a string.
  101. *
  102. * @param The string to trim.
  103. * @return The string with the trimed spaces.
  104. */
  105. static inline void ltrim(std::string &str);
  106. /**
  107. * Trims any white space to the right of a string.
  108. *
  109. * @param The string to trim.
  110. * @return The string with the trimed spaces.
  111. */
  112. static inline void rtrim(std::string &str);
  113. /**
  114. * Trims any white space to the lef and right of a string.
  115. *
  116. * note: Doesn't trim the space in the middle
  117. *
  118. * @param The string to trim.
  119. * @return The string with the trimed spaces.
  120. */
  121. static inline void trim(std::string &s);
  122. };
  123. //////////////////////////////////////////////////////////////////////////////
  124. // impl.
  125. inline bool StringUtils::starts_with(const char* str, const char* prefix)
  126. {
  127. GP_ASSERT(str != nullptr);
  128. GP_ASSERT(prefix != nullptr);
  129. if (*str == 0)
  130. {
  131. // empty string vs empty (or not) prefix
  132. return (*prefix == 0);
  133. }
  134. else if (*prefix == 0)
  135. {
  136. // non empty string with empty prefix
  137. return true;
  138. }
  139. size_t n2 = strlen(prefix);
  140. return (strncmp(str, prefix, n2) == 0);
  141. }
  142. inline bool StringUtils::starts_with(const char* str, const std::string& prefix)
  143. {
  144. GP_ASSERT(str != nullptr);
  145. if (*str == 0)
  146. {
  147. // empty string vs empty (or not) prefix
  148. return (prefix.empty());
  149. }
  150. else if (prefix.empty())
  151. {
  152. // non empty string with empty prefix
  153. return true;
  154. }
  155. std::string::size_type n2 = prefix.length();
  156. std::string::size_type n1 = strnlen(str, static_cast<size_t>(n2 + 1));
  157. if (n1 < n2)
  158. {
  159. // string is shorter than prefix
  160. return false;
  161. }
  162. GP_ASSERT(n2 > 0 && n1 >= n2);
  163. return (prefix.compare(0, n2, str, n2) == 0);
  164. }
  165. inline bool StringUtils::starts_with(const std::string& str, const char* prefix)
  166. {
  167. GP_ASSERT(prefix != nullptr);
  168. if (str.empty())
  169. {
  170. // empty string vs empty (or not) prefix
  171. return (*prefix == 0);
  172. }
  173. else if (*prefix == 0)
  174. {
  175. // non empty string with empty prefix
  176. return true;
  177. }
  178. std::string::size_type n2 = strlen(prefix);
  179. std::string::size_type n1 = str.length();
  180. if (n1 < n2)
  181. {
  182. // string is shorter than prefix
  183. return false;
  184. }
  185. GP_ASSERT(n2 > 0 && n1 >= n2);
  186. return (str.compare(0, n2, prefix) == 0);
  187. }
  188. inline bool StringUtils::starts_with(const std::string& str, const std::string& prefix)
  189. {
  190. if (str.empty())
  191. {
  192. // empty string vs empty (or not) prefix
  193. return prefix.empty();
  194. }
  195. else if (prefix.empty())
  196. {
  197. // non empty string with empty prefix
  198. return true;
  199. }
  200. std::string::size_type n2 = prefix.length();
  201. std::string::size_type n1 = str.length();
  202. if (n1 < n2)
  203. {
  204. // string is shorter than prefix
  205. return false;
  206. }
  207. GP_ASSERT(n2 > 0 && n1 >= n2);
  208. return (str.compare(0, n2, prefix) == 0);
  209. }
  210. inline bool StringUtils::ends_with(const char* str, const char* suffix)
  211. {
  212. GP_ASSERT(str != nullptr);
  213. GP_ASSERT(suffix != nullptr);
  214. if (*str == 0)
  215. {
  216. // empty string vs empty (or not) suffix
  217. return (*suffix == 0);
  218. }
  219. else if (*suffix == 0)
  220. {
  221. // non empty string with empty suffix
  222. return true;
  223. }
  224. size_t n2 = strlen(suffix);
  225. size_t n1 = strlen(str);
  226. if (n1 < n2)
  227. {
  228. // string is shorter than suffix
  229. return false;
  230. }
  231. GP_ASSERT(n2 > 0 && n1 >= n2);
  232. return (memcmp(str + n1 - n2, suffix, n2) == 0);
  233. }
  234. inline bool StringUtils::ends_with(const char* str, const std::string& suffix)
  235. {
  236. GP_ASSERT(str != nullptr);
  237. if (*str == 0)
  238. {
  239. // empty string vs empty (or not) suffix
  240. return (suffix.empty());
  241. }
  242. else if (suffix.empty())
  243. {
  244. // non empty string with empty suffix
  245. return true;
  246. }
  247. std::string::size_type n2 = suffix.length();
  248. std::string::size_type n1 = strlen(str);
  249. if (n1 < n2)
  250. {
  251. // string is shorter than suffix
  252. return false;
  253. }
  254. GP_ASSERT(n2 > 0 && n1 >= n2);
  255. return (suffix.compare(0, n2, str + n1 - n2, n2) == 0);
  256. }
  257. inline bool StringUtils::ends_with(const std::string& str, const char* suffix)
  258. {
  259. GP_ASSERT(suffix != nullptr);
  260. if (str.empty())
  261. {
  262. // empty string vs empty (or not) suffix
  263. return (*suffix == 0);
  264. }
  265. else if (*suffix == 0)
  266. {
  267. // non empty string with empty suffix
  268. return true;
  269. }
  270. std::string::size_type n2 = strlen(suffix);
  271. std::string::size_type n1 = str.length();
  272. if (n1 < n2)
  273. {
  274. // string is shorter than suffix
  275. return false;
  276. }
  277. GP_ASSERT(n2 > 0 && n1 >= n2);
  278. return (str.compare(n1 - n2, n2, suffix) == 0);
  279. }
  280. inline bool StringUtils::ends_with(const std::string& str, const std::string& suffix)
  281. {
  282. if (str.empty())
  283. {
  284. // empty string vs empty (or not) prefix
  285. return suffix.empty();
  286. }
  287. else if (suffix.empty())
  288. {
  289. // non empty string with empty prefix
  290. return true;
  291. }
  292. std::string::size_type n2 = suffix.length();
  293. std::string::size_type n1 = str.length();
  294. if (n1 < n2)
  295. {
  296. // string is shorter than suffix
  297. return false;
  298. }
  299. GP_ASSERT(n2 > 0 && n1 >= n2);
  300. return (str.compare(n1 - n2, n2, suffix) == 0);
  301. }
  302. inline std::vector<std::string> StringUtils::split(const std::string& str, char delimiter)
  303. {
  304. std::vector<std::string> tokens;
  305. std::string token;
  306. std::istringstream tokenStream(str);
  307. while (std::getline(tokenStream, token, delimiter))
  308. {
  309. tokens.push_back(token);
  310. }
  311. return tokens;
  312. }
  313. /*void replace_all(std::string& str, const std::string& from, const std::string& to)
  314. {
  315. if(from.empty())
  316. {
  317. return;
  318. }
  319. size_t start_pos = 0;
  320. while((start_pos = str.find(from, start_pos)) != std::string::npos)
  321. {
  322. str.replace(start_pos, from.length(), to);
  323. start_pos += to.length();
  324. }
  325. }*/
  326. inline void StringUtils::to_lower(std::string& str)
  327. {
  328. std::transform(str.begin(), str.end(), str.begin(),
  329. [](char ch) { return static_cast<char>(std::tolower(ch)); });
  330. }
  331. inline void StringUtils::to_upper(std::string& str)
  332. {
  333. std::transform(str.begin(), str.end(), str.begin(),
  334. [](char ch) { return static_cast<char>(std::toupper(ch)); });
  335. }
  336. inline void StringUtils::ltrim(std::string& str)
  337. {
  338. str.erase(str.begin(), std::find_if(str.begin(), str.end(),
  339. [](char ch) { return !std::isspace(ch); }));
  340. }
  341. inline void StringUtils::rtrim(std::string& str)
  342. {
  343. str.erase(std::find_if(str.rbegin(), str.rend(),
  344. [](char ch) { return !std::isspace(ch); }).base(), str.end());
  345. }
  346. inline void StringUtils::trim(std::string& str)
  347. {
  348. ltrim(str);
  349. rtrim(str);
  350. }
  351. }