util_string.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. /*
  2. * Copyright 2011-2013 Blender Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <stdarg.h>
  17. #include <stdio.h>
  18. #include "util/util_foreach.h"
  19. #include "util/util_string.h"
  20. #include "util/util_windows.h"
  21. #ifdef _WIN32
  22. # ifndef vsnprintf
  23. # define vsnprintf _vsnprintf
  24. # endif
  25. #endif /* _WIN32 */
  26. CCL_NAMESPACE_BEGIN
  27. string string_printf(const char *format, ...)
  28. {
  29. vector<char> str(128, 0);
  30. while (1) {
  31. va_list args;
  32. int result;
  33. va_start(args, format);
  34. result = vsnprintf(&str[0], str.size(), format, args);
  35. va_end(args);
  36. if (result == -1) {
  37. /* not enough space or formatting error */
  38. if (str.size() > 65536) {
  39. assert(0);
  40. return string("");
  41. }
  42. str.resize(str.size() * 2, 0);
  43. continue;
  44. }
  45. else if (result >= (int)str.size()) {
  46. /* not enough space */
  47. str.resize(result + 1, 0);
  48. continue;
  49. }
  50. return string(&str[0]);
  51. }
  52. }
  53. bool string_iequals(const string &a, const string &b)
  54. {
  55. if (a.size() == b.size()) {
  56. for (size_t i = 0; i < a.size(); i++)
  57. if (toupper(a[i]) != toupper(b[i]))
  58. return false;
  59. return true;
  60. }
  61. return false;
  62. }
  63. void string_split(vector<string> &tokens,
  64. const string &str,
  65. const string &separators,
  66. bool skip_empty_tokens)
  67. {
  68. size_t token_start = 0, token_length = 0;
  69. for (size_t i = 0; i < str.size(); ++i) {
  70. const char ch = str[i];
  71. if (separators.find(ch) == string::npos) {
  72. /* Current character is not a separator,
  73. * append it to token by increasing token length.
  74. */
  75. ++token_length;
  76. }
  77. else {
  78. /* Current character is a separator,
  79. * append current token to the list.
  80. */
  81. if (!skip_empty_tokens || token_length > 0) {
  82. string token = str.substr(token_start, token_length);
  83. tokens.push_back(token);
  84. }
  85. token_start = i + 1;
  86. token_length = 0;
  87. }
  88. }
  89. /* Append token from the tail of the string if exists. */
  90. if (token_length) {
  91. string token = str.substr(token_start, token_length);
  92. tokens.push_back(token);
  93. }
  94. }
  95. bool string_startswith(const string &s, const char *start)
  96. {
  97. size_t len = strlen(start);
  98. if (len > s.size())
  99. return 0;
  100. else
  101. return strncmp(s.c_str(), start, len) == 0;
  102. }
  103. bool string_endswith(const string &s, const char *end)
  104. {
  105. size_t len = strlen(end);
  106. if (len > s.size())
  107. return 0;
  108. else
  109. return strncmp(s.c_str() + s.size() - len, end, len) == 0;
  110. }
  111. string string_strip(const string &s)
  112. {
  113. string result = s;
  114. result.erase(0, result.find_first_not_of(' '));
  115. result.erase(result.find_last_not_of(' ') + 1);
  116. return result;
  117. }
  118. void string_replace(string &haystack, const string &needle, const string &other)
  119. {
  120. size_t i = 0, index;
  121. while ((index = haystack.find(needle, i)) != string::npos) {
  122. haystack.replace(index, needle.size(), other);
  123. i = index + other.size();
  124. }
  125. }
  126. string string_remove_trademark(const string &s)
  127. {
  128. string result = s;
  129. /* Special case, so we don;t leave sequential spaces behind. */
  130. /* TODO(sergey): Consider using regex perhaps? */
  131. string_replace(result, " (TM)", "");
  132. string_replace(result, " (R)", "");
  133. string_replace(result, "(TM)", "");
  134. string_replace(result, "(R)", "");
  135. return string_strip(result);
  136. }
  137. string string_from_bool(bool var)
  138. {
  139. if (var)
  140. return "True";
  141. else
  142. return "False";
  143. }
  144. string to_string(const char *str)
  145. {
  146. return string(str);
  147. }
  148. /* Wide char strings helpers for Windows. */
  149. #ifdef _WIN32
  150. wstring string_to_wstring(const string &str)
  151. {
  152. const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
  153. wstring str_wc(length_wc, 0);
  154. MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
  155. return str_wc;
  156. }
  157. string string_from_wstring(const wstring &str)
  158. {
  159. int length_mb = WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.size(), NULL, 0, NULL, NULL);
  160. string str_mb(length_mb, 0);
  161. WideCharToMultiByte(CP_UTF8, 0, str.c_str(), str.size(), &str_mb[0], length_mb, NULL, NULL);
  162. return str_mb;
  163. }
  164. string string_to_ansi(const string &str)
  165. {
  166. const int length_wc = MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), NULL, 0);
  167. wstring str_wc(length_wc, 0);
  168. MultiByteToWideChar(CP_UTF8, 0, str.c_str(), str.length(), &str_wc[0], length_wc);
  169. int length_mb = WideCharToMultiByte(
  170. CP_ACP, 0, str_wc.c_str(), str_wc.size(), NULL, 0, NULL, NULL);
  171. string str_mb(length_mb, 0);
  172. WideCharToMultiByte(CP_ACP, 0, str_wc.c_str(), str_wc.size(), &str_mb[0], length_mb, NULL, NULL);
  173. return str_mb;
  174. }
  175. #endif /* _WIN32 */
  176. string string_human_readable_size(size_t size)
  177. {
  178. static const char suffixes[] = "BKMGTPEZY";
  179. const char *suffix = suffixes;
  180. size_t r = 0;
  181. while (size >= 1024) {
  182. r = size % 1024;
  183. size /= 1024;
  184. suffix++;
  185. }
  186. if (*suffix != 'B')
  187. return string_printf("%.2f%c", double(size * 1024 + r) / 1024.0, *suffix);
  188. else
  189. return string_printf("%zu", size);
  190. }
  191. string string_human_readable_number(size_t num)
  192. {
  193. if (num == 0) {
  194. return "0";
  195. }
  196. /* Add thousands separators. */
  197. char buf[32];
  198. char *p = buf + 31;
  199. *p = '\0';
  200. int i = -1;
  201. while (num) {
  202. if (++i && i % 3 == 0)
  203. *(--p) = ',';
  204. *(--p) = '0' + (num % 10);
  205. num /= 10;
  206. }
  207. return p;
  208. }
  209. CCL_NAMESPACE_END