cmStringAlgorithms.cxx 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
  2. file Copyright.txt or https://cmake.org/licensing for details. */
  3. #include "cmStringAlgorithms.h"
  4. #include <algorithm>
  5. #include <cerrno>
  6. #include <cstddef> // IWYU pragma: keep
  7. #include <cstdio>
  8. #include <cstdlib>
  9. std::string cmTrimWhitespace(cm::string_view str)
  10. {
  11. // XXX(clang-tidy): This declaration and the next cannot be `const auto*`
  12. // because the qualification of `auto` is platform-dependent.
  13. // NOLINTNEXTLINE(readability-qualified-auto)
  14. auto start = str.begin();
  15. while (start != str.end() && cmIsSpace(*start)) {
  16. ++start;
  17. }
  18. if (start == str.end()) {
  19. return std::string();
  20. }
  21. // NOLINTNEXTLINE(readability-qualified-auto)
  22. auto stop = str.end() - 1;
  23. while (cmIsSpace(*stop)) {
  24. --stop;
  25. }
  26. return std::string(start, stop + 1);
  27. }
  28. std::string cmRemoveQuotes(cm::string_view str)
  29. {
  30. // We process only strings that have two quotes at least.
  31. // Also front() and back() are only defined behavior on non empty strings.
  32. if (str.size() >= 2 && //
  33. str.front() == '"' && //
  34. str.back() == '"') {
  35. // Remove a quote from the front and back
  36. str.remove_prefix(1);
  37. str.remove_suffix(1);
  38. }
  39. return std::string(str);
  40. }
  41. std::string cmEscapeQuotes(cm::string_view str)
  42. {
  43. std::string result;
  44. result.reserve(str.size());
  45. for (const char ch : str) {
  46. if (ch == '"') {
  47. result += '\\';
  48. }
  49. result += ch;
  50. }
  51. return result;
  52. }
  53. namespace {
  54. template <std::size_t N, typename T>
  55. inline void MakeDigits(cm::string_view& view, char (&digits)[N],
  56. const char* pattern, T value)
  57. {
  58. int res = std::snprintf(digits, N, pattern, value);
  59. if (res > 0 && res < static_cast<int>(N)) {
  60. view = cm::string_view(digits, static_cast<std::size_t>(res));
  61. }
  62. }
  63. } // unnamed namespace
  64. cmAlphaNum::cmAlphaNum(int val)
  65. {
  66. MakeDigits(this->View_, this->Digits_, "%i", val);
  67. }
  68. cmAlphaNum::cmAlphaNum(unsigned int val)
  69. {
  70. MakeDigits(this->View_, this->Digits_, "%u", val);
  71. }
  72. cmAlphaNum::cmAlphaNum(long int val)
  73. {
  74. MakeDigits(this->View_, this->Digits_, "%li", val);
  75. }
  76. cmAlphaNum::cmAlphaNum(unsigned long int val)
  77. {
  78. MakeDigits(this->View_, this->Digits_, "%lu", val);
  79. }
  80. cmAlphaNum::cmAlphaNum(long long int val)
  81. {
  82. MakeDigits(this->View_, this->Digits_, "%lli", val);
  83. }
  84. cmAlphaNum::cmAlphaNum(unsigned long long int val)
  85. {
  86. MakeDigits(this->View_, this->Digits_, "%llu", val);
  87. }
  88. cmAlphaNum::cmAlphaNum(float val)
  89. {
  90. MakeDigits(this->View_, this->Digits_, "%g", static_cast<double>(val));
  91. }
  92. cmAlphaNum::cmAlphaNum(double val)
  93. {
  94. MakeDigits(this->View_, this->Digits_, "%g", val);
  95. }
  96. std::string cmCatViews(
  97. std::initializer_list<std::pair<cm::string_view, std::string*>> views)
  98. {
  99. std::size_t totalSize = 0;
  100. std::string* rvalueString = nullptr;
  101. std::size_t rvalueStringLength = 0;
  102. std::size_t rvalueStringOffset = 0;
  103. for (auto const& view : views) {
  104. // Find the rvalue string with the largest capacity.
  105. if (view.second &&
  106. (!rvalueString ||
  107. view.second->capacity() > rvalueString->capacity())) {
  108. rvalueString = view.second;
  109. rvalueStringLength = rvalueString->length();
  110. rvalueStringOffset = totalSize;
  111. }
  112. totalSize += view.first.size();
  113. }
  114. std::string result;
  115. std::string::size_type initialLen = 0;
  116. if (rvalueString && rvalueString->capacity() >= totalSize) {
  117. result = std::move(*rvalueString);
  118. } else {
  119. rvalueString = nullptr;
  120. }
  121. result.resize(totalSize);
  122. if (rvalueString && rvalueStringOffset > 0) {
  123. std::copy_backward(result.begin(), result.begin() + rvalueStringLength,
  124. result.begin() + rvalueStringOffset +
  125. rvalueStringLength);
  126. }
  127. std::string::iterator sit = result.begin() + initialLen;
  128. for (auto const& view : views) {
  129. if (rvalueString && view.second == rvalueString) {
  130. sit += rvalueStringLength;
  131. } else {
  132. sit = std::copy_n(view.first.data(), view.first.size(), sit);
  133. }
  134. }
  135. return result;
  136. }
  137. bool cmStrToLong(const char* str, long* value)
  138. {
  139. errno = 0;
  140. char* endp;
  141. *value = strtol(str, &endp, 10);
  142. return (*endp == '\0') && (endp != str) && (errno == 0);
  143. }
  144. bool cmStrToLong(std::string const& str, long* value)
  145. {
  146. return cmStrToLong(str.c_str(), value);
  147. }
  148. bool cmStrToULong(const char* str, unsigned long* value)
  149. {
  150. errno = 0;
  151. char* endp;
  152. while (cmIsSpace(*str)) {
  153. ++str;
  154. }
  155. if (*str == '-') {
  156. return false;
  157. }
  158. *value = strtoul(str, &endp, 10);
  159. return (*endp == '\0') && (endp != str) && (errno == 0);
  160. }
  161. bool cmStrToULong(std::string const& str, unsigned long* value)
  162. {
  163. return cmStrToULong(str.c_str(), value);
  164. }
  165. bool cmStrToLongLong(const char* str, long long* value)
  166. {
  167. errno = 0;
  168. char* endp;
  169. *value = strtoll(str, &endp, 10);
  170. return (*endp == '\0') && (endp != str) && (errno == 0);
  171. }
  172. bool cmStrToLongLong(std::string const& str, long long* value)
  173. {
  174. return cmStrToLongLong(str.c_str(), value);
  175. }
  176. bool cmStrToULongLong(const char* str, unsigned long long* value)
  177. {
  178. errno = 0;
  179. char* endp;
  180. while (cmIsSpace(*str)) {
  181. ++str;
  182. }
  183. if (*str == '-') {
  184. return false;
  185. }
  186. *value = strtoull(str, &endp, 10);
  187. return (*endp == '\0') && (endp != str) && (errno == 0);
  188. }
  189. bool cmStrToULongLong(std::string const& str, unsigned long long* value)
  190. {
  191. return cmStrToULongLong(str.c_str(), value);
  192. }
  193. std::string cmJoin(std::vector<std::string> const& rng,
  194. cm::string_view separator, cm::string_view initial)
  195. {
  196. return cmJoinStrings(rng, separator, initial);
  197. }
  198. std::string cmJoin(cmStringRange const& rng, cm::string_view separator,
  199. cm::string_view initial)
  200. {
  201. return cmJoinStrings(rng, separator, initial);
  202. }