StringTest.cpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. #include "../testTools.h"
  2. // TODO: Cannot use casting to parent type at the same time as automatic conversion from const char*
  3. // Cover everything using a single dsr::String type?
  4. // Use "" operand as only constructor?
  5. void fooInPlace(dsr::String& target, const dsr::ReadableString& a, const dsr::ReadableString& b) {
  6. target.clear();
  7. target.append(U"Foo(");
  8. target.append(a);
  9. target.appendChar(U',');
  10. target.append(b);
  11. target.appendChar(U')');
  12. }
  13. dsr::String foo(const dsr::ReadableString& a, const dsr::ReadableString& b) {
  14. dsr::String result;
  15. result.reserve(a.length() + b.length());
  16. fooInPlace(result, a, b);
  17. return result;
  18. }
  19. START_TEST(String)
  20. { // Comparison
  21. dsr::ReadableString litA = U"Testing \u0444";
  22. dsr::ReadableString litB = U"Testing ф";
  23. ASSERT(string_match(litA, litB));
  24. ASSERT(!string_match(litA, U"wrong"));
  25. ASSERT(!string_match(U"wrong", litB));
  26. ASSERT(dsr::string_caseInsensitiveMatch(U"abc 123!", U"ABC 123!"));
  27. ASSERT(!dsr::string_caseInsensitiveMatch(U"abc 123!", U"ABD 123!"));
  28. ASSERT(dsr::string_match(U"aBc 123!", U"aBc 123!"));
  29. ASSERT(!dsr::string_match(U"abc 123!", U"ABC 123!"));
  30. }
  31. { // Concatenation
  32. dsr::String ab = dsr::string_combine(U"a", U"b");
  33. ASSERT_MATCH(ab, U"ab");
  34. dsr::String cd = dsr::string_combine(U"c", U"d");
  35. ASSERT_MATCH(cd, U"cd");
  36. cd = dsr::string_combine(U"c", U"d");
  37. ASSERT_MATCH(cd, U"cd");
  38. auto abcd = ab + cd;
  39. ASSERT_MATCH(abcd, U"abcd");
  40. ASSERT_MATCH(dsr::string_combine(U"a", U"b", U"c", "d"), U"abcd");
  41. }
  42. { // Sub-strings
  43. dsr::ReadableString abcd = U"abcd";
  44. dsr::String efgh = U"efgh";
  45. ASSERT_MATCH(abcd.inclusiveRange(0, 3), U"abcd");
  46. ASSERT_MATCH(abcd.exclusiveRange(1, 2), U"b");
  47. ASSERT_MATCH(efgh.inclusiveRange(2, 3), U"gh");
  48. ASSERT_MATCH(efgh.exclusiveRange(3, 4), U"h");
  49. ASSERT_MATCH(dsr::string_combine(abcd.from(2), efgh.before(2)), U"cdef");
  50. ASSERT_MATCH(abcd.exclusiveRange(0, 0), U""); // No size returns nothing
  51. ASSERT_MATCH(abcd.exclusiveRange(-1, -2), U""); // A negative size doesn't have to be inside
  52. ASSERT_CRASH(abcd.inclusiveRange(-1, -1)); // Index below bound expected
  53. ASSERT_CRASH(abcd.inclusiveRange(4, 4)); // Index above bound expected
  54. }
  55. { // Processing
  56. dsr::String buffer = U"Garbage";
  57. ASSERT_MATCH(buffer, U"Garbage");
  58. buffer = foo(U"Ball", U"åäöÅÄÖ"); // Crash!
  59. ASSERT_MATCH(buffer, U"Foo(Ball,åäöÅÄÖ)"); // Failed
  60. fooInPlace(buffer, U"Å", U"ф");
  61. ASSERT_MATCH(buffer, U"Foo(Å,ф)");
  62. }
  63. { // Numbers
  64. uint32_t x = 0;
  65. int32_t y = -123456;
  66. int64_t z = 100200300400500600ULL;
  67. dsr::String values = dsr::string_combine(U"x = ", x, U", y = ", y, U", z = ", z);
  68. ASSERT_MATCH(values, U"x = 0, y = -123456, z = 100200300400500600");
  69. }
  70. // Upper case
  71. ASSERT_MATCH(dsr::string_upperCase(U"a"), U"A");
  72. ASSERT_MATCH(dsr::string_upperCase(U"aB"), U"AB");
  73. ASSERT_MATCH(dsr::string_upperCase(U"abc"), U"ABC");
  74. ASSERT_MATCH(dsr::string_upperCase(U"abc1"), U"ABC1");
  75. ASSERT_MATCH(dsr::string_upperCase(U"Abc12"), U"ABC12");
  76. ASSERT_MATCH(dsr::string_upperCase(U"ABC123"), U"ABC123");
  77. // Lower case
  78. ASSERT_MATCH(dsr::string_lowerCase(U"a"), U"a");
  79. ASSERT_MATCH(dsr::string_lowerCase(U"aB"), U"ab");
  80. ASSERT_MATCH(dsr::string_lowerCase(U"abc"), U"abc");
  81. ASSERT_MATCH(dsr::string_lowerCase(U"abc1"), U"abc1");
  82. ASSERT_MATCH(dsr::string_lowerCase(U"Abc12"), U"abc12");
  83. ASSERT_MATCH(dsr::string_lowerCase(U"ABC123"), U"abc123");
  84. // Complete white space removal
  85. ASSERT_MATCH(dsr::string_removeAllWhiteSpace(U" "), U"");
  86. ASSERT_MATCH(dsr::string_removeAllWhiteSpace(U" abc\n "), U"abc");
  87. ASSERT_MATCH(dsr::string_removeAllWhiteSpace(U" a \f sentence \r surrounded \n by space \a"), U"asentencesurroundedbyspace");
  88. // White space removal by pointing to a section of the original input
  89. ASSERT_MATCH(dsr::string_removeOuterWhiteSpace(U" "), U"");
  90. ASSERT_MATCH(dsr::string_removeOuterWhiteSpace(U" abc "), U"abc");
  91. ASSERT_MATCH(dsr::string_removeOuterWhiteSpace(U" two words "), U"two words");
  92. ASSERT_MATCH(dsr::string_removeOuterWhiteSpace(U" \" something quoted \" "), U"\" something quoted \"");
  93. // Quote mangling
  94. ASSERT_MATCH(dsr::string_mangleQuote(U""), U"\"\"");
  95. ASSERT_MATCH(dsr::string_mangleQuote(U"1"), U"\"1\"");
  96. ASSERT_MATCH(dsr::string_mangleQuote(U"12"), U"\"12\"");
  97. ASSERT_MATCH(dsr::string_mangleQuote(U"123"), U"\"123\"");
  98. ASSERT_MATCH(dsr::string_mangleQuote(U"abc"), U"\"abc\"");
  99. // Not enough quote signs
  100. ASSERT_CRASH(dsr::string_unmangleQuote(U""));
  101. ASSERT_CRASH(dsr::string_unmangleQuote(U" "));
  102. ASSERT_CRASH(dsr::string_unmangleQuote(U"ab\"cd"));
  103. // Too many quote signs
  104. ASSERT_CRASH(dsr::string_unmangleQuote(U"ab\"cd\"ef\"gh"));
  105. // Basic quote
  106. ASSERT_MATCH(dsr::string_unmangleQuote(U"\"ab\""), U"ab");
  107. // Surrounded quote
  108. ASSERT_MATCH(dsr::string_unmangleQuote(U"\"ab\"cd"), U"ab");
  109. ASSERT_MATCH(dsr::string_unmangleQuote(U"ab\"cd\""), U"cd");
  110. ASSERT_MATCH(dsr::string_unmangleQuote(U"ab\"cd\"ef"), U"cd");
  111. // Mangled quote inside of quote
  112. ASSERT_MATCH(dsr::string_unmangleQuote(U"ab\"c\\\"d\"ef"), U"c\"d");
  113. ASSERT_MATCH(dsr::string_unmangleQuote(dsr::string_mangleQuote(U"c\"d")), U"c\"d");
  114. // Mangle things
  115. dsr::String randomText;
  116. for (int i = 1; i < 100; i++) {
  117. // Randomize previous characters
  118. for (int j = 1; j < i - 1; j++) {
  119. randomText.write(j, (DsrChar)((i * 21 + j * 49 + 136) % 1024));
  120. }
  121. // Add a new random character
  122. randomText.appendChar((i * 21 + 136) % 256);
  123. ASSERT_MATCH(dsr::string_unmangleQuote(dsr::string_mangleQuote(randomText)), randomText);
  124. }
  125. // Number serialization
  126. ASSERT_MATCH(dsr::string_combine(0, U" ", 1), U"0 1");
  127. ASSERT_MATCH(dsr::string_combine(14, U"x", 135), U"14x135");
  128. ASSERT_MATCH(dsr::string_combine(-135), U"-135");
  129. ASSERT_MATCH(dsr::string_combine(-14), U"-14");
  130. ASSERT_MATCH(dsr::string_combine(-1), U"-1");
  131. ASSERT_MATCH(dsr::string_combine(0u), U"0");
  132. ASSERT_MATCH(dsr::string_combine(1u), U"1");
  133. ASSERT_MATCH(dsr::string_combine(14u), U"14");
  134. ASSERT_MATCH(dsr::string_combine(135u), U"135");
  135. // Number parsing
  136. ASSERT_EQUAL(string_toInteger(U"0"), 0);
  137. ASSERT_EQUAL(string_toInteger(U"-0"), 0);
  138. ASSERT_EQUAL(string_toInteger(U"No digits here."), 0);
  139. ASSERT_EQUAL(string_toInteger(U" (12 garbage 34) "), 1234); // You are supposed to catch these errors before converting to an integer
  140. ASSERT_EQUAL(string_toInteger(U""), 0);
  141. ASSERT_EQUAL(string_toInteger(U"1"), 1);
  142. ASSERT_EQUAL(string_toInteger(U"-1"), -1);
  143. ASSERT_EQUAL(string_toInteger(U"1024"), 1024);
  144. ASSERT_EQUAL(string_toInteger(U"-1024"), -1024);
  145. ASSERT_EQUAL(string_toInteger(U"1000000"), 1000000);
  146. ASSERT_EQUAL(string_toInteger(U"-1000000"), -1000000);
  147. ASSERT_EQUAL(string_toInteger(U"123"), 123);
  148. ASSERT_EQUAL(string_toDouble(U"123"), 123.0);
  149. ASSERT_EQUAL(string_toDouble(U"123.456"), 123.456);
  150. { // Splitting
  151. List<ReadableString> result;
  152. string_split_inPlace(result, U"a.b.c.d", U'.');
  153. ASSERT_EQUAL(result.length(), 4);
  154. ASSERT_MATCH(result[0], U"a");
  155. ASSERT_MATCH(result[1], U"b");
  156. ASSERT_MATCH(result[2], U"c");
  157. ASSERT_MATCH(result[3], U"d");
  158. String content = U"One Two Three";
  159. result = string_split(content, U' ');
  160. ASSERT_EQUAL(result.length(), 3);
  161. ASSERT_MATCH(result[0], U"One");
  162. ASSERT_MATCH(result[1], U"Two");
  163. ASSERT_MATCH(result[2], U"Three");
  164. string_split_inPlace(result, U"Four.Five", U'.', true);
  165. ASSERT_EQUAL(result.length(), 5);
  166. ASSERT_MATCH(result[0], U"One");
  167. ASSERT_MATCH(result[1], U"Two");
  168. ASSERT_MATCH(result[2], U"Three");
  169. ASSERT_MATCH(result[3], U"Four");
  170. ASSERT_MATCH(result[4], U"Five");
  171. string_split_inPlace(result, U" 1 | 2 ", U'|');
  172. ASSERT_EQUAL(result.length(), 2);
  173. ASSERT_MATCH(result[0], U" 1 ");
  174. ASSERT_MATCH(result[1], U" 2 ");
  175. }
  176. // TODO: Test taking a part of a parent string with a start offset, leaving the parent scope,
  177. // and expanding with append while the buffer isn't shared but has an offset from buffer start.
  178. // TODO: Assert that buffers are shared when they should, but prevents side-effects when one is being written to.
  179. END_TEST