VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstIprtMiniString.cpp@ 101343

最後變更 在這個檔案從101343是 101343,由 vboxsync 提交於 18 月 前

IPRT/ministring: Added C-style endsWith methods.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 23.8 KB
 
1/* $Id: tstIprtMiniString.cpp 101343 2023-10-04 19:30:37Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTCString.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.alldomusa.eu.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * The contents of this file may alternatively be used under the terms
26 * of the Common Development and Distribution License Version 1.0
27 * (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
28 * in the VirtualBox distribution, in which case the provisions of the
29 * CDDL are applicable instead of those of the GPL.
30 *
31 * You may elect to license modified versions of this file under the
32 * terms and conditions of either the GPL or the CDDL or both.
33 *
34 * SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
35 */
36
37
38/*********************************************************************************************************************************
39* Header Files *
40*********************************************************************************************************************************/
41#include <iprt/cpp/ministring.h>
42
43#include <iprt/errcore.h>
44#include <iprt/mem.h>
45#include <iprt/string.h>
46#include <iprt/test.h>
47#include <iprt/uni.h>
48
49
50static void test1Hlp1(const char *pszExpect, const char *pszFormat, ...)
51{
52#if 0
53 va_list va;
54 va_start(va, pszFormat);
55 RTCString strTst(pszFormat, va);
56 va_end(va);
57 RTTESTI_CHECK_MSG(strTst.equals(pszExpect), ("strTst='%s' expected='%s'\n", strTst.c_str(), pszExpect));
58#else
59 RT_NOREF_PV(pszExpect);
60 RT_NOREF_PV(pszFormat);
61#endif
62}
63
64static void test1(RTTEST hTest)
65{
66 RTTestSub(hTest, "Basics");
67
68#define CHECK(expr) RTTESTI_CHECK(expr)
69#define CHECK_DUMP(expr, value) \
70 do { \
71 if (!(expr)) \
72 RTTestFailed(hTest, "%d: FAILED %s, got \"%s\"", __LINE__, #expr, value); \
73 } while (0)
74
75#define CHECK_DUMP_I(expr) \
76 do { \
77 if (!(expr)) \
78 RTTestFailed(hTest, "%d: FAILED %s, got \"%d\"", __LINE__, #expr, expr); \
79 } while (0)
80#define CHECK_EQUAL(Str, szExpect) \
81 do { \
82 if (!(Str).equals(szExpect)) \
83 RTTestIFailed("line %u: expected \"%s\" got \"%s\"", __LINE__, szExpect, (Str).c_str()); \
84 } while (0)
85#define CHECK_EQUAL_I(iRes, iExpect) \
86 do { \
87 if (iRes != iExpect) \
88 RTTestIFailed("line %u: expected \"%zd\" got \"%zd\"", __LINE__, iExpect, iRes); \
89 } while (0)
90
91 RTCString empty;
92 CHECK(empty.length() == 0);
93 CHECK(empty.capacity() == 0);
94
95 empty.reserve(1);
96 CHECK(empty.length() == 0);
97 CHECK(empty.capacity() == 1);
98 char *pszEmpty = empty.mutableRaw();
99 CHECK(pszEmpty != NULL);
100
101 RTCString sixbytes("12345");
102 CHECK(sixbytes.length() == 5);
103 CHECK(sixbytes.capacity() == 6);
104
105 sixbytes.append(RTCString("678"));
106 CHECK(sixbytes.length() == 8);
107 CHECK(sixbytes.capacity() >= 9);
108
109 sixbytes.append("9a");
110 CHECK(sixbytes.length() == 10);
111 CHECK(sixbytes.capacity() >= 11);
112
113 char *psz = sixbytes.mutableRaw();
114 // 123456789a
115 // ^
116 // 0123456
117 psz[6] = '\0';
118 sixbytes.jolt();
119 CHECK(sixbytes.length() == 6);
120 CHECK(sixbytes.capacity() == 7);
121
122 RTCString morebytes("tobereplaced");
123 morebytes = "newstring ";
124 morebytes.append(sixbytes);
125
126 CHECK_DUMP(morebytes == "newstring 123456", morebytes.c_str());
127
128 RTCString third(morebytes);
129 third.reserve(100 * 1024); // 100 KB
130 CHECK_DUMP(third == "newstring 123456", morebytes.c_str() );
131 CHECK(third.capacity() == 100 * 1024);
132 CHECK(third.length() == morebytes.length()); // must not have changed
133
134 RTCString copy1(morebytes);
135 RTCString copy2 = morebytes;
136 CHECK(copy1 == copy2);
137
138 copy1 = NULL;
139 CHECK(copy1.length() == 0);
140
141 copy1 = "";
142 CHECK(copy1.length() == 0);
143
144 CHECK(RTCString("abc") < RTCString("def"));
145 CHECK(RTCString("") < RTCString("def"));
146 CHECK(RTCString("abc") > RTCString(""));
147 CHECK(RTCString("abc") != RTCString("def"));
148 CHECK_DUMP_I(RTCString("def") > RTCString("abc"));
149 CHECK(RTCString("abc") == RTCString("abc"));
150 CHECK(RTCString("").compare("") == 0);
151 CHECK(RTCString("").compare(NULL) == 0);
152 CHECK(RTCString("").compare("a") < 0);
153 CHECK(RTCString("a").compare("") > 0);
154 CHECK(RTCString("a").compare(NULL) > 0);
155
156 CHECK(RTCString("abc") < "def");
157 CHECK(RTCString("abc") != "def");
158 CHECK_DUMP_I(RTCString("def") > "abc");
159 CHECK(RTCString("abc") == "abc");
160
161 CHECK(RTCString("abc").equals("abc"));
162 CHECK(!RTCString("abc").equals("def"));
163 CHECK(RTCString("abc").equalsIgnoreCase("Abc"));
164 CHECK(RTCString("abc").equalsIgnoreCase("ABc"));
165 CHECK(RTCString("abc").equalsIgnoreCase("ABC"));
166 CHECK(!RTCString("abc").equalsIgnoreCase("dBC"));
167 CHECK(RTCString("").equals(""));
168 CHECK(RTCString("").equals(NULL));
169 CHECK(!RTCString("").equals("a"));
170 CHECK(!RTCString("a").equals(""));
171 CHECK(!RTCString("a").equals(NULL));
172 CHECK(RTCString("").equalsIgnoreCase(""));
173 CHECK(RTCString("").equalsIgnoreCase(NULL));
174 CHECK(!RTCString("").equalsIgnoreCase("a"));
175 CHECK(!RTCString("a").equalsIgnoreCase(""));
176
177 copy2.setNull();
178 for (int i = 0; i < 100; ++i)
179 {
180 copy2.reserve(50); // should be ignored after 50 loops
181 copy2.append("1");
182 }
183 CHECK(copy2.length() == 100);
184
185 copy2.setNull();
186 for (int i = 0; i < 100; ++i)
187 {
188 copy2.reserve(50); // should be ignored after 50 loops
189 copy2.append('1');
190 }
191 CHECK(copy2.length() == 100);
192
193 /* printf */
194 {
195 RTCString StrFmt;
196 CHECK(StrFmt.printf("%s-%s-%d", "abc", "def", 42).equals("abc-def-42"));
197 test1Hlp1("abc-42-def", "%s-%d-%s", "abc", 42, "def");
198 test1Hlp1("", "");
199 test1Hlp1("1", "1");
200 test1Hlp1("foobar", "%s", "foobar");
201 }
202
203 /* substring constructors */
204 {
205 RTCString SubStr1("", (size_t)0);
206 CHECK_EQUAL(SubStr1, "");
207
208 RTCString SubStr2("abcdef", 2);
209 CHECK_EQUAL(SubStr2, "ab");
210
211 RTCString SubStr3("abcdef", 1);
212 CHECK_EQUAL(SubStr3, "a");
213
214 RTCString SubStr4("abcdef", 6);
215 CHECK_EQUAL(SubStr4, "abcdef");
216
217 RTCString SubStr5("abcdef", 7);
218 CHECK_EQUAL(SubStr5, "abcdef");
219
220 RTCString SubStrBase("abcdef");
221
222 RTCString SubStr10(SubStrBase, 0);
223 CHECK_EQUAL(SubStr10, "abcdef");
224
225 RTCString SubStr11(SubStrBase, 1);
226 CHECK_EQUAL(SubStr11, "bcdef");
227
228 RTCString SubStr12(SubStrBase, 1, 1);
229 CHECK_EQUAL(SubStr12, "b");
230
231 RTCString SubStr13(SubStrBase, 2, 3);
232 CHECK_EQUAL(SubStr13, "cde");
233
234 RTCString SubStr14(SubStrBase, 2, 4);
235 CHECK_EQUAL(SubStr14, "cdef");
236
237 RTCString SubStr15(SubStrBase, 2, 5);
238 CHECK_EQUAL(SubStr15, "cdef");
239 }
240
241 /* substr() and substrCP() functions */
242 RTCString strTest("");
243 CHECK_EQUAL(strTest.substr(0), "");
244 CHECK_EQUAL(strTest.substrCP(0), "");
245 CHECK_EQUAL(strTest.substr(1), "");
246 CHECK_EQUAL(strTest.substrCP(1), "");
247
248 /* now let's have some non-ASCII to chew on */
249 strTest = "abcdefßäbcdef";
250 // 13 codepoints, but 15 bytes (excluding null terminator);
251 // "ß" and "ä" consume two bytes each
252 CHECK_EQUAL(strTest.substr(0), strTest.c_str());
253 CHECK_EQUAL(strTest.substrCP(0), strTest.c_str());
254
255 CHECK_EQUAL(strTest.substr(2), "cdefßäbcdef");
256 CHECK_EQUAL(strTest.substrCP(2), "cdefßäbcdef");
257
258 CHECK_EQUAL(strTest.substr(2, 2), "cd");
259 CHECK_EQUAL(strTest.substrCP(2, 2), "cd");
260
261 CHECK_EQUAL(strTest.substr(6), "ßäbcdef");
262 CHECK_EQUAL(strTest.substrCP(6), "ßäbcdef");
263
264 CHECK_EQUAL(strTest.substr(6, 2), "ß"); // UTF-8 "ß" consumes two bytes
265 CHECK_EQUAL(strTest.substrCP(6, 1), "ß");
266
267 CHECK_EQUAL(strTest.substr(8), "äbcdef"); // UTF-8 "ß" consumes two bytes
268 CHECK_EQUAL(strTest.substrCP(7), "äbcdef");
269
270 CHECK_EQUAL(strTest.substr(8, 3), "äb"); // UTF-8 "ä" consumes two bytes
271 CHECK_EQUAL(strTest.substrCP(7, 2), "äb");
272
273 CHECK_EQUAL(strTest.substr(14, 1), "f");
274 CHECK_EQUAL(strTest.substrCP(12, 1), "f");
275
276 CHECK_EQUAL(strTest.substr(15, 1), "");
277 CHECK_EQUAL(strTest.substrCP(13, 1), "");
278
279 CHECK_EQUAL(strTest.substr(16, 1), "");
280 CHECK_EQUAL(strTest.substrCP(15, 1), "");
281
282 /* and check cooperation with find() */
283 size_t pos = strTest.find("ß");
284 CHECK_EQUAL(strTest.substr(pos), "ßäbcdef");
285
286 /* check find() */
287 CHECK_EQUAL_I(strTest.find("f"), 5);
288 CHECK_EQUAL_I(strTest.find("f", 0), 5);
289 CHECK_EQUAL_I(strTest.find("f", 3), 5);
290 CHECK_EQUAL_I(strTest.find("f", 6), 14);
291 CHECK_EQUAL_I(strTest.find("f", 9), 14);
292 CHECK_EQUAL_I(strTest.substr(pos).find("d"), 6);
293
294 /* split */
295 RTCList<RTCString> spList1 = RTCString("##abcdef##abcdef####abcdef##").split("##", RTCString::RemoveEmptyParts);
296 RTTESTI_CHECK(spList1.size() == 3);
297 for (size_t i = 0; i < spList1.size(); ++i)
298 RTTESTI_CHECK(spList1.at(i) == "abcdef");
299 RTCList<RTCString> spList2 = RTCString("##abcdef##abcdef####abcdef##").split("##", RTCString::KeepEmptyParts);
300 RTTESTI_CHECK_RETV(spList2.size() == 5);
301 RTTESTI_CHECK(spList2.at(0) == "");
302 RTTESTI_CHECK(spList2.at(1) == "abcdef");
303 RTTESTI_CHECK(spList2.at(2) == "abcdef");
304 RTTESTI_CHECK(spList2.at(3) == "");
305 RTTESTI_CHECK(spList2.at(4) == "abcdef");
306 RTCList<RTCString> spList3 = RTCString().split("##", RTCString::KeepEmptyParts);
307 RTTESTI_CHECK(spList3.size() == 0);
308 RTCList<RTCString> spList4 = RTCString().split("");
309 RTTESTI_CHECK(spList4.size() == 0);
310 RTCList<RTCString> spList5 = RTCString("abcdef").split("");
311 RTTESTI_CHECK_RETV(spList5.size() == 1);
312 RTTESTI_CHECK(spList5.at(0) == "abcdef");
313
314 /* join */
315 RTCList<RTCString> jnList;
316 strTest = RTCString::join(jnList);
317 RTTESTI_CHECK(strTest == "");
318 strTest = RTCString::join(jnList, "##");
319 RTTESTI_CHECK(strTest == "");
320
321 jnList.append("abcdef");
322 strTest = RTCString::join(jnList, "##");
323 RTTESTI_CHECK(strTest == "abcdef");
324
325 jnList.append("abcdef");
326 strTest = RTCString::join(jnList, ";");
327 RTTESTI_CHECK(strTest == "abcdef;abcdef");
328
329 for (size_t i = 0; i < 3; ++i)
330 jnList.append("abcdef");
331 strTest = RTCString::join(jnList);
332 RTTESTI_CHECK(strTest == "abcdefabcdefabcdefabcdefabcdef");
333 strTest = RTCString::join(jnList, "##");
334 RTTESTI_CHECK(strTest == "abcdef##abcdef##abcdef##abcdef##abcdef");
335
336 /* special constructor and assignment arguments */
337 RTCString StrCtor1("");
338 RTTESTI_CHECK(StrCtor1.isEmpty());
339 RTTESTI_CHECK(StrCtor1.length() == 0);
340
341 RTCString StrCtor2(NULL);
342 RTTESTI_CHECK(StrCtor2.isEmpty());
343 RTTESTI_CHECK(StrCtor2.length() == 0);
344
345 RTCString StrCtor1d(StrCtor1);
346 RTTESTI_CHECK(StrCtor1d.isEmpty());
347 RTTESTI_CHECK(StrCtor1d.length() == 0);
348
349 RTCString StrCtor2d(StrCtor2);
350 RTTESTI_CHECK(StrCtor2d.isEmpty());
351 RTTESTI_CHECK(StrCtor2d.length() == 0);
352
353 for (unsigned i = 0; i < 2; i++)
354 {
355 RTCString StrAssign;
356 if (i) StrAssign = "abcdef";
357 StrAssign = (char *)NULL;
358 RTTESTI_CHECK(StrAssign.isEmpty());
359 RTTESTI_CHECK(StrAssign.length() == 0);
360
361 if (i) StrAssign = "abcdef";
362 StrAssign = "";
363 RTTESTI_CHECK(StrAssign.isEmpty());
364 RTTESTI_CHECK(StrAssign.length() == 0);
365
366 if (i) StrAssign = "abcdef";
367 StrAssign = StrCtor1;
368 RTTESTI_CHECK(StrAssign.isEmpty());
369 RTTESTI_CHECK(StrAssign.length() == 0);
370
371 if (i) StrAssign = "abcdef";
372 StrAssign = StrCtor2;
373 RTTESTI_CHECK(StrAssign.isEmpty());
374 RTTESTI_CHECK(StrAssign.length() == 0);
375 }
376
377 /* truncation */
378 RTCString StrTruncate1("abcdef");
379 RTTESTI_CHECK(StrTruncate1.length() == 6);
380 for (int i = 5; i >= 0; i--)
381 {
382 StrTruncate1.truncate(i);
383 RTTESTI_CHECK(StrTruncate1.length() == (size_t)i);
384 }
385
386 RTCString StrTruncate2("01ßä6");
387 CHECK_EQUAL(StrTruncate2, "01ßä6");
388 StrTruncate2.truncate(6);
389 CHECK_EQUAL(StrTruncate2, "01ßä");
390 StrTruncate2.truncate(5);
391 CHECK_EQUAL(StrTruncate2, "01ß");
392 StrTruncate2.truncate(10);
393 CHECK_EQUAL(StrTruncate2, "01ß");
394 StrTruncate2.truncate(4);
395 CHECK_EQUAL(StrTruncate2, "01ß");
396 StrTruncate2.truncate(3);
397 CHECK_EQUAL(StrTruncate2, "01");
398 StrTruncate2.truncate(1);
399 CHECK_EQUAL(StrTruncate2, "0");
400 StrTruncate2.truncate(0);
401 CHECK_EQUAL(StrTruncate2, "");
402
403 /* endsWith */
404 RTCString const strEmpty;
405 strTest = "qwerty";
406 CHECK(strTest.endsWith(strTest));
407 CHECK(strTest.endsWith("qwerty"));
408 CHECK(strTest.endsWith("werty"));
409 CHECK(strTest.endsWith("erty"));
410 CHECK(strTest.endsWith("rty"));
411 CHECK(strTest.endsWith("ty"));
412 CHECK(strTest.endsWith("y"));
413 CHECK(!strTest.endsWith(""));
414 CHECK(strTest.endsWithI("qwerty"));
415 CHECK(strTest.endsWithI("werty"));
416 CHECK(strTest.endsWithI("erty"));
417 CHECK(strTest.endsWithI("rty"));
418 CHECK(strTest.endsWithI("ty"));
419 CHECK(strTest.endsWithI("y"));
420 CHECK(!strTest.endsWithI(""));
421 CHECK(!strTest.endsWith(strEmpty));
422
423 /* startsWith */
424 CHECK(strTest.startsWith(strTest));
425 CHECK(strTest.startsWith("qwerty"));
426 CHECK(strTest.startsWith("qwert"));
427 CHECK(strTest.startsWith("qwer"));
428 CHECK(strTest.startsWith("qwe"));
429 CHECK(strTest.startsWith("qw"));
430 CHECK(strTest.startsWith("q"));
431 CHECK(!strTest.startsWith(""));
432 CHECK(!strTest.startsWith(strEmpty));
433
434#undef CHECK
435#undef CHECK_DUMP
436#undef CHECK_DUMP_I
437#undef CHECK_EQUAL
438}
439
440
441static int mymemcmp(const char *psz1, const char *psz2, size_t cch)
442{
443 for (size_t off = 0; off < cch; off++)
444 if (psz1[off] != psz2[off])
445 {
446 RTTestIFailed("off=%#x psz1=%.*Rhxs psz2=%.*Rhxs\n", off,
447 RT_MIN(cch - off, 8), &psz1[off],
448 RT_MIN(cch - off, 8), &psz2[off]);
449 return psz1[off] > psz2[off] ? 1 : -1;
450 }
451 return 0;
452}
453
454#if 0
455/**
456 * Detects a few annoying unicode points with unstable case folding for UTF-8.
457 *
458 * Unicode 4.01, I think, introduces a few codepoints with lower/upper mappings
459 * that has a different length when encoded as UTF-8. This breaks some
460 * assumptions we used to make. Since it's just a handful codepoints, we'll
461 * detect them and ignore them here. The actual case folding functions in
462 * IPRT will of course deal with this in a more robust manner.
463 *
464 * @returns true if problematic, false if not.
465 * @param uc The codepoints.
466 */
467static bool isUnevenUtf8FoldingCp(RTUNICP uc)
468{
469 RTUNICP ucLower = RTUniCpToLower(uc);
470 RTUNICP ucUpper = RTUniCpToUpper(uc);
471 //return RTUniCpCalcUtf8Len(ucLower) != RTUniCpCalcUtf8Len(ucUpper);
472 return false;
473}
474#endif
475
476static void test2(RTTEST hTest)
477{
478 RTTestSub(hTest, "UTF-8 upper/lower encoding assumption");
479
480#define CHECK_EQUAL(str1, str2) \
481 do \
482 { \
483 RTTESTI_CHECK(strlen((str1).c_str()) == (str1).length()); \
484 RTTESTI_CHECK((str1).length() == (str2).length()); \
485 RTTESTI_CHECK(mymemcmp((str1).c_str(), (str2).c_str(), (str2).length() + 1) == 0); \
486 } while (0)
487
488 RTCString strTmp, strExpect;
489 char szDst[16];
490
491 /* Some simple ascii stuff. */
492 strTmp = "abcdefghijklmnopqrstuvwxyz0123456ABCDEFGHIJKLMNOPQRSTUVWXYZ;-+/\\";
493 strExpect = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456ABCDEFGHIJKLMNOPQRSTUVWXYZ;-+/\\";
494 strTmp.toUpper();
495 CHECK_EQUAL(strTmp, strExpect);
496
497 strTmp.toLower();
498 strExpect = "abcdefghijklmnopqrstuvwxyz0123456abcdefghijklmnopqrstuvwxyz;-+/\\";
499 CHECK_EQUAL(strTmp, strExpect);
500
501 strTmp = "abcdefghijklmnopqrstuvwxyz0123456ABCDEFGHIJKLMNOPQRSTUVWXYZ;-+/\\";
502 strTmp.toLower();
503 CHECK_EQUAL(strTmp, strExpect);
504
505 /* Collect all upper and lower case code points. */
506 RTCString strLower("");
507 strLower.reserve(_4M);
508
509 RTCString strUpper("");
510 strUpper.reserve(_4M);
511
512 for (RTUNICP uc = 1; uc <= 0x10fffd; uc++)
513 {
514 /* Unicode 4.01, I think, introduced a few codepoints with lower/upper mappings
515 that aren't up for roundtrips and which case folding has a different UTF-8
516 length. We'll just skip them here as there are very few:
517 - Dotless small i and dotless capital I folds into ASCII I and i.
518 - The small letter long s folds to ASCII S.
519 - Greek prosgegrammeni folds to iota, which is a letter with both upper
520 and lower case foldings of its own. */
521#if 0 /** @todo totally busted testcase, plz figure out how to fix. */
522 if ( uc == 0x131
523 || uc == 0x130
524 || uc == 0x17f
525 || uc == 0x1fbe
526 )
527 continue;
528
529 if (RTUniCpIsLower(uc))
530 {
531 RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc));
532 strLower.appendCodePoint(uc);
533 }
534 if (RTUniCpIsUpper(uc))
535 {
536 RTTESTI_CHECK_MSG(uc < 0xd800 || (uc > 0xdfff && uc != 0xfffe && uc != 0xffff), ("%#x\n", uc));
537 strUpper.appendCodePoint(uc);
538 }
539#else
540 continue;
541#endif
542 }
543 RTTESTI_CHECK(strlen(strLower.c_str()) == strLower.length());
544 RTTESTI_CHECK(strlen(strUpper.c_str()) == strUpper.length());
545
546 /* Fold each code point in the lower case string and check that it encodes
547 into the same or less number of bytes. */
548 size_t cch = 0;
549 const char *pszCur = strLower.c_str();
550 RTCString strUpper2("");
551 strUpper2.reserve(strLower.length() + 64);
552 for (;;)
553 {
554 RTUNICP ucLower;
555 const char * const pszPrev = pszCur;
556 RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucLower), VINF_SUCCESS);
557 size_t const cchSrc = pszCur - pszPrev;
558 if (!ucLower)
559 break;
560
561 RTUNICP const ucUpper = RTUniCpToUpper(ucLower);
562 const char *pszDstEnd = RTStrPutCp(szDst, ucUpper);
563 size_t const cchDst = pszDstEnd - &szDst[0];
564 RTTESTI_CHECK_MSG(cchSrc >= cchDst,
565 ("ucLower=%#x %u bytes; ucUpper=%#x %u bytes\n",
566 ucLower, cchSrc, ucUpper, cchDst));
567 cch += cchDst;
568 strUpper2.appendCodePoint(ucUpper);
569
570 /* roundtrip stability */
571 RTUNICP const ucUpper2 = RTUniCpToUpper(ucUpper);
572 RTTESTI_CHECK_MSG(ucUpper2 == ucUpper, ("ucUpper2=%#x ucUpper=%#x\n", ucUpper2, ucUpper));
573
574 RTUNICP const ucLower2 = RTUniCpToLower(ucUpper);
575 RTTESTI_CHECK_MSG(ucLower2 == ucLower, ("ucLower2=%#x ucLower=%#x\n", ucLower2, ucLower));
576 RTUNICP const ucUpper3 = RTUniCpToUpper(ucLower2);
577 RTTESTI_CHECK_MSG(ucUpper3 == ucUpper, ("ucUpper3=%#x ucUpper=%#x\n", ucUpper3, ucUpper));
578
579 pszDstEnd = RTStrPutCp(szDst, ucLower2);
580 size_t const cchLower2 = pszDstEnd - &szDst[0];
581 RTTESTI_CHECK_MSG(cchDst == cchLower2,
582 ("ucLower2=%#x %u bytes; ucUpper=%#x %u bytes; ucLower=%#x\n",
583 ucLower2, cchLower2, ucUpper, cchDst, ucLower));
584 }
585 RTTESTI_CHECK(strlen(strUpper2.c_str()) == strUpper2.length());
586 RTTESTI_CHECK_MSG(cch == strUpper2.length(), ("cch=%u length()=%u\n", cch, strUpper2.length()));
587
588 /* the toUpper method shall do the same thing. */
589 strTmp = strLower; CHECK_EQUAL(strTmp, strLower);
590 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
591
592 /* Ditto for the upper case string. */
593 cch = 0;
594 pszCur = strUpper.c_str();
595 RTCString strLower2("");
596 strLower2.reserve(strUpper.length() + 64);
597 for (;;)
598 {
599 RTUNICP ucUpper;
600 const char * const pszPrev = pszCur;
601 RTTESTI_CHECK_RC_BREAK(RTStrGetCpEx(&pszCur, &ucUpper), VINF_SUCCESS);
602 size_t const cchSrc = pszCur - pszPrev;
603 if (!ucUpper)
604 break;
605
606 RTUNICP const ucLower = RTUniCpToLower(ucUpper);
607 const char *pszDstEnd = RTStrPutCp(szDst, ucLower);
608 size_t const cchDst = pszDstEnd - &szDst[0];
609 RTTESTI_CHECK_MSG(cchSrc >= cchDst,
610 ("ucUpper=%#x %u bytes; ucLower=%#x %u bytes\n",
611 ucUpper, cchSrc, ucLower, cchDst));
612
613 cch += cchDst;
614 strLower2.appendCodePoint(ucLower);
615
616 /* roundtrip stability */
617 RTUNICP const ucLower2 = RTUniCpToLower(ucLower);
618 RTTESTI_CHECK_MSG(ucLower2 == ucLower, ("ucLower2=%#x ucLower=%#x\n", ucLower2, ucLower));
619
620 RTUNICP const ucUpper2 = RTUniCpToUpper(ucLower);
621 RTTESTI_CHECK_MSG(ucUpper2 == ucUpper, ("ucUpper2=%#x ucUpper=%#x\n", ucUpper2, ucUpper));
622 RTUNICP const ucLower3 = RTUniCpToLower(ucUpper2);
623 RTTESTI_CHECK_MSG(ucLower3 == ucLower, ("ucLower3=%#x ucLower=%#x\n", ucLower3, ucLower));
624
625 pszDstEnd = RTStrPutCp(szDst, ucUpper2);
626 size_t const cchUpper2 = pszDstEnd - &szDst[0];
627 RTTESTI_CHECK_MSG(cchDst == cchUpper2,
628 ("ucUpper2=%#x %u bytes; ucLower=%#x %u bytes\n",
629 ucUpper2, cchUpper2, ucLower, cchDst));
630 }
631 RTTESTI_CHECK(strlen(strLower2.c_str()) == strLower2.length());
632 RTTESTI_CHECK_MSG(cch == strLower2.length(), ("cch=%u length()=%u\n", cch, strLower2.length()));
633
634 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper);
635 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
636
637 /* Checks of folding stability when nothing shall change. */
638 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper);
639 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper);
640 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper);
641 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper);
642
643 strTmp = strUpper2; CHECK_EQUAL(strTmp, strUpper2);
644 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
645 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
646 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
647
648 strTmp = strLower; CHECK_EQUAL(strTmp, strLower);
649 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower);
650 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower);
651 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower);
652
653 strTmp = strLower2; CHECK_EQUAL(strTmp, strLower2);
654 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
655 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
656 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
657
658 /* Check folding stability for roundtrips. */
659 strTmp = strUpper; CHECK_EQUAL(strTmp, strUpper);
660 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
661 strTmp.toUpper();
662 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
663 strTmp.toUpper();
664 strTmp.toLower(); CHECK_EQUAL(strTmp, strLower2);
665
666 strTmp = strLower; CHECK_EQUAL(strTmp, strLower);
667 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
668 strTmp.toLower();
669 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
670 strTmp.toLower();
671 strTmp.toUpper(); CHECK_EQUAL(strTmp, strUpper2);
672}
673
674
675int main()
676{
677 RTTEST hTest;
678 RTEXITCODE rcExit = RTTestInitAndCreate("tstIprtMiniString", &hTest);
679 if (rcExit == RTEXITCODE_SUCCESS)
680 {
681 RTTestBanner(hTest);
682
683 test1(hTest);
684 test2(hTest);
685
686 rcExit = RTTestSummaryAndDestroy(hTest);
687 }
688 return rcExit;
689}
690
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette