testStringAlgorithms.cxx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  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 <cmConfigure.h> // IWYU pragma: keep
  4. #include <iostream>
  5. #include <sstream>
  6. #include <string>
  7. #include <type_traits>
  8. #include <utility>
  9. #include <vector>
  10. #include <cm/string_view>
  11. #include "cmStringAlgorithms.h"
  12. int testStringAlgorithms(int /*unused*/, char* /*unused*/[])
  13. {
  14. int failed = 0;
  15. auto assert_ok = [&failed](bool test, cm::string_view title) {
  16. if (test) {
  17. std::cout << "Passed: " << title << "\n";
  18. } else {
  19. std::cout << "Failed: " << title << "\n";
  20. ++failed;
  21. }
  22. };
  23. auto assert_string = [&failed](cm::string_view generated,
  24. cm::string_view expected,
  25. cm::string_view title) {
  26. if (generated == expected) {
  27. std::cout << "Passed: " << title << "\n";
  28. } else {
  29. std::cout << "Failed: " << title << "\n";
  30. std::cout << "Expected: " << expected << "\n";
  31. std::cout << "Got: " << generated << "\n";
  32. ++failed;
  33. }
  34. };
  35. // ----------------------------------------------------------------------
  36. // Test cmTrimWhitespace
  37. {
  38. std::string base = "base";
  39. std::string spaces = " \f\f\n\n\r\r\t\t\v\v";
  40. assert_string(cmTrimWhitespace(spaces + base), base,
  41. "cmTrimWhitespace front");
  42. assert_string(cmTrimWhitespace(base + spaces), base,
  43. "cmTrimWhitespace back");
  44. assert_string(cmTrimWhitespace(spaces + base + spaces), base,
  45. "cmTrimWhitespace front and back");
  46. }
  47. // ----------------------------------------------------------------------
  48. // Test cmRemoveQuotes
  49. {
  50. auto test = [&assert_string](cm::string_view source,
  51. cm::string_view expected,
  52. cm::string_view title) {
  53. assert_string(cmRemoveQuotes(source), expected, title);
  54. };
  55. test("", "", "cmRemoveQuotes empty");
  56. test("\"", "\"", "cmRemoveQuotes single quote");
  57. test("\"\"", "", "cmRemoveQuotes double quote");
  58. test("\"a", "\"a", "cmRemoveQuotes quote char");
  59. test("\"ab", "\"ab", "cmRemoveQuotes quote char char");
  60. test("a\"", "a\"", "cmRemoveQuotes char quote");
  61. test("ab\"", "ab\"", "cmRemoveQuotes char char quote");
  62. test("a", "a", "cmRemoveQuotes single char");
  63. test("ab", "ab", "cmRemoveQuotes two chars");
  64. test("abc", "abc", "cmRemoveQuotes three chars");
  65. test("\"abc\"", "abc", "cmRemoveQuotes quoted chars");
  66. test("\"\"abc\"\"", "\"abc\"", "cmRemoveQuotes quoted quoted chars");
  67. }
  68. // ----------------------------------------------------------------------
  69. // Test cmEscapeQuotes
  70. {
  71. assert_string(cmEscapeQuotes("plain"), "plain", "cmEscapeQuotes plain");
  72. std::string base = "\"base\"\"";
  73. std::string result = "\\\"base\\\"\\\"";
  74. assert_string(cmEscapeQuotes(base), result, "cmEscapeQuotes escaped");
  75. }
  76. // ----------------------------------------------------------------------
  77. // Test cmJoin
  78. {
  79. typedef std::string ST;
  80. typedef std::vector<std::string> VT;
  81. assert_string(cmJoin(ST("abc"), ";"), "a;b;c", "cmJoin std::string");
  82. assert_string(cmJoin(VT{}, ";"), "", "cmJoin std::vector empty");
  83. assert_string(cmJoin(VT{ "a" }, ";"), "a", "cmJoin std::vector single");
  84. assert_string(cmJoin(VT{ "a", "b", "c" }, ";"), "a;b;c",
  85. "cmJoin std::vector multiple");
  86. assert_string(cmJoin(VT{ "a", "b", "c" }, "<=>"), "a<=>b<=>c",
  87. "cmJoin std::vector long sep");
  88. }
  89. // ----------------------------------------------------------------------
  90. // Test cmTokenize
  91. {
  92. typedef std::vector<std::string> VT;
  93. assert_ok(cmTokenize("", ";") == VT{ "" }, "cmTokenize empty");
  94. assert_ok(cmTokenize(";", ";") == VT{ "" }, "cmTokenize sep");
  95. assert_ok(cmTokenize("abc", ";") == VT{ "abc" }, "cmTokenize item");
  96. assert_ok(cmTokenize("abc;", ";") == VT{ "abc" }, "cmTokenize item sep");
  97. assert_ok(cmTokenize(";abc", ";") == VT{ "abc" }, "cmTokenize sep item");
  98. assert_ok(cmTokenize("abc;;efg", ";") == VT{ "abc", "efg" },
  99. "cmTokenize item sep sep item");
  100. assert_ok(cmTokenize("a1;a2;a3;a4", ";") == VT{ "a1", "a2", "a3", "a4" },
  101. "cmTokenize multiple items");
  102. }
  103. // ----------------------------------------------------------------------
  104. // Test cmStrCat
  105. {
  106. int ni = -1100;
  107. unsigned int nui = 1100u;
  108. long int nli = -12000l;
  109. unsigned long int nuli = 12000ul;
  110. long long int nlli = -130000ll;
  111. unsigned long long int nulli = 130000ull;
  112. std::string val =
  113. cmStrCat("<test>", ni, ',', nui, ',', nli, ",", nuli, ", ", nlli,
  114. std::string(", "), nulli, cm::string_view("</test>"));
  115. std::string expect =
  116. "<test>-1100,1100,-12000,12000, -130000, 130000</test>";
  117. assert_string(val, expect, "cmStrCat strings and integers");
  118. }
  119. {
  120. float const val = 1.5f;
  121. float const div = 0.00001f;
  122. float f = 0.0f;
  123. std::istringstream(cmStrCat("", val)) >> f;
  124. f -= val;
  125. assert_ok((f < div) && (f > -div), "cmStrCat float");
  126. }
  127. {
  128. double const val = 1.5;
  129. double const div = 0.00001;
  130. double d = 0.0;
  131. std::istringstream(cmStrCat("", val)) >> d;
  132. d -= val;
  133. assert_ok((d < div) && (d > -div), "cmStrCat double");
  134. }
  135. {
  136. std::string val;
  137. std::string expect;
  138. val.reserve(50 * cmStrLen("cmStrCat move ") + 1);
  139. auto data = val.data();
  140. auto capacity = val.capacity();
  141. bool moved = true;
  142. for (int i = 0; i < 100; i++) {
  143. if (i % 2 == 0) {
  144. val = cmStrCat(std::move(val), "move ");
  145. expect += "move ";
  146. } else {
  147. val = cmStrCat("cmStrCat ", std::move(val));
  148. expect = "cmStrCat " + std::move(expect);
  149. }
  150. if (val.data() != data || val.capacity() != capacity) {
  151. moved = false;
  152. }
  153. }
  154. assert_ok(moved, "cmStrCat move");
  155. assert_string(val, expect, "cmStrCat move");
  156. }
  157. // ----------------------------------------------------------------------
  158. // Test cmWrap
  159. {
  160. typedef std::vector<std::string> VT;
  161. assert_string(cmWrap("<", VT{}, ">", "; "), //
  162. "", //
  163. "cmWrap empty, string prefix and suffix");
  164. assert_string(cmWrap("<", VT{ "abc" }, ">", "; "), //
  165. "<abc>", //
  166. "cmWrap single, string prefix and suffix");
  167. assert_string(cmWrap("<", VT{ "a1", "a2", "a3" }, ">", "; "), //
  168. "<a1>; <a2>; <a3>", //
  169. "cmWrap multiple, string prefix and suffix");
  170. assert_string(cmWrap('<', VT{}, '>', "; "), //
  171. "", //
  172. "cmWrap empty, char prefix and suffix");
  173. assert_string(cmWrap('<', VT{ "abc" }, '>', "; "), //
  174. "<abc>", //
  175. "cmWrap single, char prefix and suffix");
  176. assert_string(cmWrap('<', VT{ "a1", "a2", "a3" }, '>', "; "), //
  177. "<a1>; <a2>; <a3>", //
  178. "cmWrap multiple, char prefix and suffix");
  179. }
  180. // ----------------------------------------------------------------------
  181. // Test cmHas(Literal)Prefix and cmHas(Literal)Suffix
  182. {
  183. std::string str("abc");
  184. assert_ok(cmHasPrefix(str, 'a'), "cmHasPrefix char");
  185. assert_ok(!cmHasPrefix(str, 'c'), "cmHasPrefix char not");
  186. assert_ok(cmHasPrefix(str, "ab"), "cmHasPrefix string");
  187. assert_ok(!cmHasPrefix(str, "bc"), "cmHasPrefix string not");
  188. assert_ok(cmHasPrefix(str, str), "cmHasPrefix complete string");
  189. assert_ok(cmHasLiteralPrefix(str, "ab"), "cmHasLiteralPrefix string");
  190. assert_ok(!cmHasLiteralPrefix(str, "bc"), "cmHasLiteralPrefix string not");
  191. assert_ok(cmHasSuffix(str, 'c'), "cmHasSuffix char");
  192. assert_ok(!cmHasSuffix(str, 'a'), "cmHasSuffix char not");
  193. assert_ok(cmHasSuffix(str, "bc"), "cmHasSuffix string");
  194. assert_ok(!cmHasSuffix(str, "ab"), "cmHasSuffix string not");
  195. assert_ok(cmHasSuffix(str, str), "cmHasSuffix complete string");
  196. assert_ok(cmHasLiteralSuffix(str, "bc"), "cmHasLiteralSuffix string");
  197. assert_ok(!cmHasLiteralSuffix(str, "ab"), "cmHasLiteralPrefix string not");
  198. }
  199. // ----------------------------------------------------------------------
  200. // Test cmStrToLong
  201. {
  202. long value;
  203. assert_ok(cmStrToLong("1", &value) && value == 1,
  204. "cmStrToLong parses a positive decimal integer.");
  205. assert_ok(cmStrToLong(" 1", &value) && value == 1,
  206. "cmStrToLong parses a decimal integer after whitespace.");
  207. assert_ok(cmStrToLong("-1", &value) && value == -1,
  208. "cmStrToLong parses a negative decimal integer.");
  209. assert_ok(
  210. cmStrToLong(" -1", &value) && value == -1,
  211. "cmStrToLong parses a negative decimal integer after whitespace.");
  212. assert_ok(!cmStrToLong("1x", &value),
  213. "cmStrToLong rejects trailing content.");
  214. }
  215. // ----------------------------------------------------------------------
  216. // Test cmStrToULong
  217. {
  218. unsigned long value;
  219. assert_ok(cmStrToULong("1", &value) && value == 1,
  220. "cmStrToULong parses a decimal integer.");
  221. assert_ok(cmStrToULong(" 1", &value) && value == 1,
  222. "cmStrToULong parses a decimal integer after whitespace.");
  223. assert_ok(!cmStrToULong("-1", &value),
  224. "cmStrToULong rejects a negative number.");
  225. assert_ok(!cmStrToULong(" -1", &value),
  226. "cmStrToULong rejects a negative number after whitespace.");
  227. assert_ok(!cmStrToULong("1x", &value),
  228. "cmStrToULong rejects trailing content.");
  229. }
  230. // ----------------------------------------------------------------------
  231. // Test cmStrToLongLong
  232. {
  233. long long value;
  234. assert_ok(cmStrToLongLong("1", &value) && value == 1,
  235. "cmStrToLongLong parses a positive decimal integer.");
  236. assert_ok(cmStrToLongLong(" 1", &value) && value == 1,
  237. "cmStrToLongLong parses a decimal integer after whitespace.");
  238. assert_ok(cmStrToLongLong("-1", &value) && value == -1,
  239. "cmStrToLongLong parses a negative decimal integer.");
  240. assert_ok(
  241. cmStrToLongLong(" -1", &value) && value == -1,
  242. "cmStrToLongLong parses a negative decimal integer after whitespace.");
  243. assert_ok(!cmStrToLongLong("1x", &value),
  244. "cmStrToLongLong rejects trailing content.");
  245. }
  246. // ----------------------------------------------------------------------
  247. // Test cmStrToULongLong
  248. {
  249. unsigned long long value;
  250. assert_ok(cmStrToULongLong("1", &value) && value == 1,
  251. "cmStrToULongLong parses a decimal integer.");
  252. assert_ok(cmStrToULongLong(" 1", &value) && value == 1,
  253. "cmStrToULongLong parses a decimal integer after whitespace.");
  254. assert_ok(!cmStrToULongLong("-1", &value),
  255. "cmStrToULongLong rejects a negative number.");
  256. assert_ok(!cmStrToULongLong(" -1", &value),
  257. "cmStrToULongLong rejects a negative number after whitespace.");
  258. assert_ok(!cmStrToULongLong("1x", &value),
  259. "cmStrToULongLong rejects trailing content.");
  260. }
  261. // ----------------------------------------------------------------------
  262. // Test cmStrLen
  263. {
  264. constexpr auto len = cmStrLen("Hello world!");
  265. assert_ok(len == 12,
  266. "cmStrLen returns length of non-empty literal string");
  267. assert_ok(cmStrLen("") == 0,
  268. "cmStrLen returns length of empty literal string");
  269. }
  270. return failed;
  271. }