StringBuilder.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /*
  2. * Copyright (C) 2011 Google Inc. All rights reserved.
  3. * Copyright (C) 2013 Apple Inc. All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are
  7. * met:
  8. *
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above
  12. * copyright notice, this list of conditions and the following disclaimer
  13. * in the documentation and/or other materials provided with the
  14. * distribution.
  15. * * Neither the name of Google Inc. nor the names of its
  16. * contributors may be used to endorse or promote products derived from
  17. * this software without specific prior written permission.
  18. *
  19. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. */
  31. #include "config.h"
  32. #include "WTFStringUtilities.h"
  33. namespace TestWebKitAPI {
  34. static void expectBuilderContent(const String& expected, const StringBuilder& builder)
  35. {
  36. // Not using builder.toString() or builder.toStringPreserveCapacity() because they all
  37. // change internal state of builder.
  38. EXPECT_EQ(expected, String(builder.characters(), builder.length()));
  39. }
  40. void expectEmpty(const StringBuilder& builder)
  41. {
  42. EXPECT_EQ(0U, builder.length());
  43. EXPECT_TRUE(builder.isEmpty());
  44. EXPECT_EQ(0, builder.characters());
  45. }
  46. TEST(StringBuilderTest, DefaultConstructor)
  47. {
  48. StringBuilder builder;
  49. expectEmpty(builder);
  50. }
  51. TEST(StringBuilderTest, Append)
  52. {
  53. StringBuilder builder;
  54. builder.append(String("0123456789"));
  55. expectBuilderContent("0123456789", builder);
  56. builder.append("abcd");
  57. expectBuilderContent("0123456789abcd", builder);
  58. builder.append("efgh", 3);
  59. expectBuilderContent("0123456789abcdefg", builder);
  60. builder.append("");
  61. expectBuilderContent("0123456789abcdefg", builder);
  62. builder.append('#');
  63. expectBuilderContent("0123456789abcdefg#", builder);
  64. builder.toString(); // Test after reifyString().
  65. StringBuilder builder1;
  66. builder.append("", 0);
  67. expectBuilderContent("0123456789abcdefg#", builder);
  68. builder1.append(builder.characters(), builder.length());
  69. builder1.append("XYZ");
  70. builder.append(builder1.characters(), builder1.length());
  71. expectBuilderContent("0123456789abcdefg#0123456789abcdefg#XYZ", builder);
  72. StringBuilder builder2;
  73. builder2.reserveCapacity(100);
  74. builder2.append("xyz");
  75. const UChar* characters = builder2.characters();
  76. builder2.append("0123456789");
  77. ASSERT_EQ(characters, builder2.characters());
  78. builder2.toStringPreserveCapacity(); // Test after reifyString with buffer preserved.
  79. builder2.append("abcd");
  80. ASSERT_EQ(characters, builder2.characters());
  81. // Test appending UChar32 characters to StringBuilder.
  82. StringBuilder builderForUChar32Append;
  83. UChar32 frakturAChar = 0x1D504;
  84. builderForUChar32Append.append(frakturAChar); // The fraktur A is not in the BMP, so it's two UTF-16 code units long.
  85. ASSERT_EQ(2U, builderForUChar32Append.length());
  86. builderForUChar32Append.append(static_cast<UChar32>('A'));
  87. ASSERT_EQ(3U, builderForUChar32Append.length());
  88. const UChar resultArray[] = { U16_LEAD(frakturAChar), U16_TRAIL(frakturAChar), 'A' };
  89. expectBuilderContent(String(resultArray, WTF_ARRAY_LENGTH(resultArray)), builderForUChar32Append);
  90. }
  91. TEST(StringBuilderTest, ToString)
  92. {
  93. StringBuilder builder;
  94. builder.append("0123456789");
  95. String string = builder.toString();
  96. ASSERT_EQ(String("0123456789"), string);
  97. ASSERT_EQ(string.impl(), builder.toString().impl());
  98. // Changing the StringBuilder should not affect the original result of toString().
  99. builder.append("abcdefghijklmnopqrstuvwxyz");
  100. ASSERT_EQ(String("0123456789"), string);
  101. // Changing the StringBuilder should not affect the original result of toString() in case the capacity is not changed.
  102. builder.reserveCapacity(200);
  103. string = builder.toString();
  104. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
  105. builder.append("ABC");
  106. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
  107. // Changing the original result of toString() should not affect the content of the StringBuilder.
  108. String string1 = builder.toString();
  109. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1);
  110. string1.append("DEF");
  111. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), builder.toString());
  112. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABCDEF"), string1);
  113. // Resizing the StringBuilder should not affect the original result of toString().
  114. string1 = builder.toString();
  115. builder.resize(10);
  116. builder.append("###");
  117. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1);
  118. }
  119. TEST(StringBuilderTest, ToStringPreserveCapacity)
  120. {
  121. StringBuilder builder;
  122. builder.append("0123456789");
  123. unsigned capacity = builder.capacity();
  124. String string = builder.toStringPreserveCapacity();
  125. ASSERT_EQ(capacity, builder.capacity());
  126. ASSERT_EQ(String("0123456789"), string);
  127. ASSERT_EQ(string.impl(), builder.toStringPreserveCapacity().impl());
  128. ASSERT_EQ(string.characters(), builder.characters());
  129. // Changing the StringBuilder should not affect the original result of toStringPreserveCapacity().
  130. builder.append("abcdefghijklmnopqrstuvwxyz");
  131. ASSERT_EQ(String("0123456789"), string);
  132. // Changing the StringBuilder should not affect the original result of toStringPreserveCapacity() in case the capacity is not changed.
  133. builder.reserveCapacity(200);
  134. capacity = builder.capacity();
  135. string = builder.toStringPreserveCapacity();
  136. ASSERT_EQ(capacity, builder.capacity());
  137. ASSERT_EQ(string.characters(), builder.characters());
  138. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
  139. builder.append("ABC");
  140. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyz"), string);
  141. // Changing the original result of toStringPreserveCapacity() should not affect the content of the StringBuilder.
  142. capacity = builder.capacity();
  143. String string1 = builder.toStringPreserveCapacity();
  144. ASSERT_EQ(capacity, builder.capacity());
  145. ASSERT_EQ(string1.characters(), builder.characters());
  146. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1);
  147. string1.append("DEF");
  148. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), builder.toStringPreserveCapacity());
  149. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABCDEF"), string1);
  150. // Resizing the StringBuilder should not affect the original result of toStringPreserveCapacity().
  151. capacity = builder.capacity();
  152. string1 = builder.toStringPreserveCapacity();
  153. ASSERT_EQ(capacity, builder.capacity());
  154. ASSERT_EQ(string.characters(), builder.characters());
  155. builder.resize(10);
  156. builder.append("###");
  157. ASSERT_EQ(String("0123456789abcdefghijklmnopqrstuvwxyzABC"), string1);
  158. }
  159. TEST(StringBuilderTest, Clear)
  160. {
  161. StringBuilder builder;
  162. builder.append("0123456789");
  163. builder.clear();
  164. expectEmpty(builder);
  165. }
  166. TEST(StringBuilderTest, Array)
  167. {
  168. StringBuilder builder;
  169. builder.append("0123456789");
  170. EXPECT_EQ('0', static_cast<char>(builder[0]));
  171. EXPECT_EQ('9', static_cast<char>(builder[9]));
  172. builder.toString(); // Test after reifyString().
  173. EXPECT_EQ('0', static_cast<char>(builder[0]));
  174. EXPECT_EQ('9', static_cast<char>(builder[9]));
  175. }
  176. TEST(StringBuilderTest, Resize)
  177. {
  178. StringBuilder builder;
  179. builder.append("0123456789");
  180. builder.resize(10);
  181. EXPECT_EQ(10U, builder.length());
  182. expectBuilderContent("0123456789", builder);
  183. builder.resize(8);
  184. EXPECT_EQ(8U, builder.length());
  185. expectBuilderContent("01234567", builder);
  186. builder.toString();
  187. builder.resize(7);
  188. EXPECT_EQ(7U, builder.length());
  189. expectBuilderContent("0123456", builder);
  190. builder.resize(0);
  191. expectEmpty(builder);
  192. }
  193. TEST(StringBuilderTest, Equal)
  194. {
  195. StringBuilder builder1;
  196. StringBuilder builder2;
  197. ASSERT_TRUE(builder1 == builder2);
  198. ASSERT_TRUE(equal(builder1, static_cast<LChar*>(0), 0));
  199. ASSERT_TRUE(builder1 == String());
  200. ASSERT_TRUE(String() == builder1);
  201. ASSERT_TRUE(builder1 != String("abc"));
  202. builder1.append("123");
  203. builder1.reserveCapacity(32);
  204. builder2.append("123");
  205. builder1.reserveCapacity(64);
  206. ASSERT_TRUE(builder1 == builder2);
  207. ASSERT_TRUE(builder1 == String("123"));
  208. ASSERT_TRUE(String("123") == builder1);
  209. builder2.append("456");
  210. ASSERT_TRUE(builder1 != builder2);
  211. ASSERT_TRUE(builder2 != builder1);
  212. ASSERT_TRUE(String("123") != builder2);
  213. ASSERT_TRUE(builder2 != String("123"));
  214. builder2.toString(); // Test after reifyString().
  215. ASSERT_TRUE(builder1 != builder2);
  216. builder2.resize(3);
  217. ASSERT_TRUE(builder1 == builder2);
  218. builder1.toString(); // Test after reifyString().
  219. ASSERT_TRUE(builder1 == builder2);
  220. }
  221. TEST(StringBuilderTest, CanShrink)
  222. {
  223. StringBuilder builder;
  224. builder.reserveCapacity(256);
  225. ASSERT_TRUE(builder.canShrink());
  226. for (int i = 0; i < 256; i++)
  227. builder.append('x');
  228. ASSERT_EQ(builder.length(), builder.capacity());
  229. ASSERT_FALSE(builder.canShrink());
  230. }
  231. TEST(StringBuilderTest, ToAtomicString)
  232. {
  233. StringBuilder builder;
  234. builder.append("123");
  235. AtomicString atomicString = builder.toAtomicString();
  236. ASSERT_EQ(String("123"), atomicString);
  237. builder.reserveCapacity(256);
  238. ASSERT_TRUE(builder.canShrink());
  239. for (int i = builder.length(); i < 128; i++)
  240. builder.append('x');
  241. AtomicString atomicString1 = builder.toAtomicString();
  242. ASSERT_EQ(128u, atomicString1.length());
  243. ASSERT_EQ('x', atomicString1[127]);
  244. // Later change of builder should not affect the atomic string.
  245. for (int i = builder.length(); i < 256; i++)
  246. builder.append('x');
  247. ASSERT_EQ(128u, atomicString1.length());
  248. ASSERT_FALSE(builder.canShrink());
  249. String string = builder.toString();
  250. AtomicString atomicString2 = builder.toAtomicString();
  251. // They should share the same StringImpl.
  252. ASSERT_EQ(atomicString2.impl(), string.impl());
  253. }
  254. TEST(StringBuilderTest, ToAtomicStringOnEmpty)
  255. {
  256. { // Default constructed.
  257. StringBuilder builder;
  258. AtomicString atomicString = builder.toAtomicString();
  259. ASSERT_EQ(emptyAtom, atomicString);
  260. }
  261. { // With capacity.
  262. StringBuilder builder;
  263. builder.reserveCapacity(64);
  264. AtomicString atomicString = builder.toAtomicString();
  265. ASSERT_EQ(emptyAtom, atomicString);
  266. }
  267. { // AtomicString constructed from a null string.
  268. StringBuilder builder;
  269. builder.append(String());
  270. AtomicString atomicString = builder.toAtomicString();
  271. ASSERT_EQ(emptyAtom, atomicString);
  272. }
  273. { // AtomicString constructed from an empty string.
  274. StringBuilder builder;
  275. builder.append(emptyString());
  276. AtomicString atomicString = builder.toAtomicString();
  277. ASSERT_EQ(emptyAtom, atomicString);
  278. }
  279. { // AtomicString constructed from an empty StringBuilder.
  280. StringBuilder builder;
  281. StringBuilder emptyBuilder;
  282. builder.append(emptyBuilder);
  283. AtomicString atomicString = builder.toAtomicString();
  284. ASSERT_EQ(emptyAtom, atomicString);
  285. }
  286. { // AtomicString constructed from an empty char* string.
  287. StringBuilder builder;
  288. builder.append("", 0);
  289. AtomicString atomicString = builder.toAtomicString();
  290. ASSERT_EQ(emptyAtom, atomicString);
  291. }
  292. { // Cleared StringBuilder.
  293. StringBuilder builder;
  294. builder.appendLiteral("WebKit");
  295. builder.clear();
  296. AtomicString atomicString = builder.toAtomicString();
  297. ASSERT_EQ(emptyAtom, atomicString);
  298. }
  299. }
  300. } // namespace