VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstUtf8.cpp@ 33563

Last change on this file since 33563 was 33563, checked in by vboxsync, 14 years ago

iprt:ministring: Added the java-style equals() and equalsIgnoreCase() as equals() can optimize the comparison by first checking if the length is the same (compare() cannot as it needs to determin the ordering). Added appendCodePoint() for UTF-8. Fixed the incorrect assumption in toUpper and toLower that the string length remained unchanged - the string might shrink as the folded code points may have a shorter encoding. Added testcase that verifies that a code point will not grow during folding and that have a stable encoding length after it has been changed in a folding.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 50.1 KB
Line 
1/* $Id: tstUtf8.cpp 33563 2010-10-28 14:46:26Z vboxsync $ */
2/** @file
3 * IPRT Testcase - UTF-8 and UTF-16 string conversions.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include <iprt/string.h>
31
32#include <iprt/uni.h>
33#include <iprt/uuid.h>
34#include <iprt/time.h>
35#include <iprt/stream.h>
36#include <iprt/alloc.h>
37#include <iprt/assert.h>
38#include <iprt/err.h>
39#include <iprt/rand.h>
40#include <iprt/test.h>
41
42
43
44/**
45 * Generate a random codepoint for simple UTF-16 encoding.
46 */
47static RTUTF16 GetRandUtf16(void)
48{
49 RTUTF16 wc;
50 do
51 {
52 wc = (RTUTF16)RTRandU32Ex(1, 0xffff);
53 } while (wc >= 0xd800 && wc <= 0xdfff);
54 return wc;
55}
56
57
58/**
59 *
60 */
61static void test1(RTTEST hTest)
62{
63 static const char s_szBadString1[] = "Bad \xe0\x13\x0";
64 static const char s_szBadString2[] = "Bad \xef\xbf\xc3";
65 int rc;
66 char *pszUtf8;
67 char *pszCurrent;
68 PRTUTF16 pwsz;
69 PRTUTF16 pwszRand;
70
71 /*
72 * Invalid UTF-8 to UCS-2 test.
73 */
74 RTTestSub(hTest, "Feeding bad UTF-8 to RTStrToUtf16");
75 rc = RTStrToUtf16(s_szBadString1, &pwsz);
76 RTTEST_CHECK_MSG(hTest, rc == VERR_NO_TRANSLATION || rc == VERR_INVALID_UTF8_ENCODING,
77 (hTest, "Conversion of first bad UTF-8 string to UTF-16 apparantly succeeded. It shouldn't. rc=%Rrc\n", rc));
78 rc = RTStrToUtf16(s_szBadString2, &pwsz);
79 RTTEST_CHECK_MSG(hTest, rc == VERR_NO_TRANSLATION || rc == VERR_INVALID_UTF8_ENCODING,
80 (hTest, "Conversion of second bad UTF-8 strings to UTF-16 apparantly succeeded. It shouldn't. rc=%Rrc\n", rc));
81
82 /*
83 * Test current CP conversion.
84 */
85 RTTestSub(hTest, "Rand UTF-16 -> UTF-8 -> CP -> UTF-8");
86 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz));
87 for (int i = 0; i < 30; i++)
88 pwszRand[i] = GetRandUtf16();
89 pwszRand[30] = 0;
90
91 rc = RTUtf16ToUtf8(pwszRand, &pszUtf8);
92 if (rc == VINF_SUCCESS)
93 {
94 rc = RTStrUtf8ToCurrentCP(&pszCurrent, pszUtf8);
95 if (rc == VINF_SUCCESS)
96 {
97 rc = RTStrCurrentCPToUtf8(&pszUtf8, pszCurrent);
98 if (rc == VINF_SUCCESS)
99 RTTestPassed(hTest, "Random UTF-16 -> UTF-8 -> Current -> UTF-8 successful.\n");
100 else
101 RTTestFailed(hTest, "%d: The third part of random UTF-16 -> UTF-8 -> Current -> UTF-8 failed with return value %Rrc.",
102 __LINE__, rc);
103 }
104 else if (rc == VERR_NO_TRANSLATION)
105 RTTestPassed(hTest, "The second part of random UTF-16 -> UTF-8 -> Current -> UTF-8 returned VERR_NO_TRANSLATION. This is probably as it should be.\n");
106 else
107 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> Current -> UTF-8 failed with return value %Rrc.",
108 __LINE__, rc);
109 }
110 else
111 RTTestFailed(hTest, "%d: The first part of random UTF-16 -> UTF-8 -> Current -> UTF-8 failed with return value %Rrc.",
112 __LINE__, rc);
113
114 /*
115 * Generate a new random string.
116 */
117 RTTestSub(hTest, "Random UTF-16 -> UTF-8 -> UTF-16");
118 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz));
119 for (int i = 0; i < 30; i++)
120 pwszRand[i] = GetRandUtf16();
121 pwszRand[30] = 0;
122 rc = RTUtf16ToUtf8(pwszRand, &pszUtf8);
123 if (rc == VINF_SUCCESS)
124 {
125 rc = RTStrToUtf16(pszUtf8, &pwsz);
126 if (rc == VINF_SUCCESS)
127 {
128 int i;
129 for (i = 0; pwszRand[i] == pwsz[i] && pwsz[i] != 0; i++)
130 /* nothing */;
131 if (pwszRand[i] == pwsz[i] && pwsz[i] == 0)
132 RTTestPassed(hTest, "Random UTF-16 -> UTF-8 -> UTF-16 successful.\n");
133 else
134 {
135 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> UTF-16 failed.", __LINE__);
136 RTTestPrintf(hTest, RTTESTLVL_FAILURE, "First differing character is at position %d and has the value %x.\n", i, pwsz[i]);
137 }
138 }
139 else
140 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> UTF-16 failed with return value %Rrc.",
141 __LINE__, rc);
142 }
143 else
144 RTTestFailed(hTest, "%d: The first part of random UTF-16 -> UTF-8 -> UTF-16 failed with return value %Rrc.",
145 __LINE__, rc);
146
147 /*
148 * Generate yet another random string and convert it to a buffer.
149 */
150 RTTestSub(hTest, "Random RTUtf16ToUtf8Ex + RTStrToUtf16");
151 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz));
152 for (int i = 0; i < 30; i++)
153 pwszRand[i] = GetRandUtf16();
154 pwszRand[30] = 0;
155
156 char szUtf8Array[120];
157 char *pszUtf8Array = szUtf8Array;
158 rc = RTUtf16ToUtf8Ex(pwszRand, RTSTR_MAX, &pszUtf8Array, 120, NULL);
159 if (rc == 0)
160 {
161 rc = RTStrToUtf16(pszUtf8Array, &pwsz);
162 if (rc == 0)
163 {
164 int i;
165 for (i = 0; pwszRand[i] == pwsz[i] && pwsz[i] != 0; i++)
166 ;
167 if (pwsz[i] == 0 && i >= 8)
168 RTTestPassed(hTest, "Random UTF-16 -> fixed length UTF-8 -> UTF-16 successful.\n");
169 else
170 {
171 RTTestFailed(hTest, "%d: Incorrect conversion of UTF-16 -> fixed length UTF-8 -> UTF-16.\n", __LINE__);
172 RTTestPrintf(hTest, RTTESTLVL_FAILURE, "First differing character is at position %d and has the value %x.\n", i, pwsz[i]);
173 }
174 }
175 else
176 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> fixed length UTF-8 -> UTF-16 failed with return value %Rrc.\n", __LINE__, rc);
177 }
178 else
179 RTTestFailed(hTest, "%d: The first part of random UTF-16 -> fixed length UTF-8 -> UTF-16 failed with return value %Rrc.\n", __LINE__, rc);
180
181 /*
182 * And again.
183 */
184 RTTestSub(hTest, "Random RTUtf16ToUtf8 + RTStrToUtf16Ex");
185 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz));
186 for (int i = 0; i < 30; i++)
187 pwszRand[i] = GetRandUtf16();
188 pwszRand[30] = 0;
189
190 RTUTF16 wszBuf[70];
191 PRTUTF16 pwsz2Buf = wszBuf;
192 rc = RTUtf16ToUtf8(pwszRand, &pszUtf8);
193 if (rc == 0)
194 {
195 rc = RTStrToUtf16Ex(pszUtf8, RTSTR_MAX, &pwsz2Buf, 70, NULL);
196 if (rc == 0)
197 {
198 int i;
199 for (i = 0; pwszRand[i] == pwsz2Buf[i] && pwsz2Buf[i] != 0; i++)
200 ;
201 if (pwszRand[i] == 0 && pwsz2Buf[i] == 0)
202 RTTestPassed(hTest, "Random UTF-16 -> UTF-8 -> fixed length UTF-16 successful.\n");
203 else
204 {
205 RTTestFailed(hTest, "%d: Incorrect conversion of random UTF-16 -> UTF-8 -> fixed length UTF-16.\n", __LINE__);
206 RTTestPrintf(hTest, RTTESTLVL_FAILURE, "First differing character is at position %d and has the value %x.\n", i, pwsz2Buf[i]);
207 }
208 }
209 else
210 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> fixed length UTF-16 failed with return value %Rrc.\n", __LINE__, rc);
211 }
212 else
213 RTTestFailed(hTest, "%d: The first part of random UTF-16 -> UTF-8 -> fixed length UTF-16 failed with return value %Rrc.\n",
214 __LINE__, rc);
215 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz));
216 for (int i = 0; i < 30; i++)
217 pwszRand[i] = GetRandUtf16();
218 pwszRand[30] = 0;
219
220 rc = RTUtf16ToUtf8Ex(pwszRand, RTSTR_MAX, &pszUtf8Array, 20, NULL);
221 if (rc == VERR_BUFFER_OVERFLOW)
222 RTTestPassed(hTest, "Random UTF-16 -> fixed length UTF-8 with too short buffer successfully rejected.\n");
223 else
224 RTTestFailed(hTest, "%d: Random UTF-16 -> fixed length UTF-8 with too small buffer returned value %d instead of VERR_BUFFER_OVERFLOW.\n",
225 __LINE__, rc);
226
227 /*
228 * last time...
229 */
230 RTTestSub(hTest, "Random RTUtf16ToUtf8 + RTStrToUtf16Ex");
231 pwszRand = (PRTUTF16)RTMemAlloc(31 * sizeof(*pwsz));
232 for (int i = 0; i < 30; i++)
233 pwszRand[i] = GetRandUtf16();
234 pwszRand[30] = 0;
235
236 rc = RTUtf16ToUtf8(pwszRand, &pszUtf8);
237 if (rc == VINF_SUCCESS)
238 {
239 rc = RTStrToUtf16Ex(pszUtf8, RTSTR_MAX, &pwsz2Buf, 20, NULL);
240 if (rc == VERR_BUFFER_OVERFLOW)
241 RTTestPassed(hTest, "Random UTF-16 -> UTF-8 -> fixed length UTF-16 with too short buffer successfully rejected.\n");
242 else
243 RTTestFailed(hTest, "%d: The second part of random UTF-16 -> UTF-8 -> fixed length UTF-16 with too short buffer returned value %Rrc instead of VERR_BUFFER_OVERFLOW.\n",
244 __LINE__, rc);
245 }
246 else
247 RTTestFailed(hTest, "%d:The first part of random UTF-16 -> UTF-8 -> fixed length UTF-16 failed with return value %Rrc.\n",
248 __LINE__, rc);
249
250
251 RTTestSubDone(hTest);
252}
253
254
255static RTUNICP g_uszAll[0x110000 - 1 - 0x800 - 2 + 1];
256static RTUTF16 g_wszAll[0xfffe - (0xe000 - 0xd800) + (0x110000 - 0x10000) * 2];
257static char g_szAll[0x7f + (0x800 - 0x80) * 2 + (0xfffe - 0x800 - (0xe000 - 0xd800))* 3 + (0x110000 - 0x10000) * 4 + 1];
258
259static void whereami(int cBits, size_t off)
260{
261 if (cBits == 8)
262 {
263 if (off < 0x7f)
264 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", off + 1);
265 else if (off < 0xf7f)
266 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", (off - 0x7f) / 2 + 0x80);
267 else if (off < 0x27f7f)
268 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", (off - 0xf7f) / 3 + 0x800);
269 else if (off < 0x2df79)
270 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", (off - 0x27f7f) / 3 + 0xe000);
271 else if (off < 0x42df79)
272 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 U+%#x\n", (off - 0x2df79) / 4 + 0x10000);
273 else
274 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-8 ???\n");
275 }
276 else if (cBits == 16)
277 {
278 if (off < 0xd7ff*2)
279 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-16 U+%#x\n", off / 2 + 1);
280 else if (off < 0xf7fd*2)
281 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-16 U+%#x\n", (off - 0xd7ff*2) / 2 + 0xe000);
282 else if (off < 0x20f7fd)
283 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-16 U+%#x\n", (off - 0xf7fd*2) / 4 + 0x10000);
284 else
285 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "UTF-16 ???\n");
286 }
287 else
288 {
289 if (off < (0xd800 - 1) * sizeof(RTUNICP))
290 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "RTUNICP U+%#x\n", off / sizeof(RTUNICP) + 1);
291 else if (off < (0xfffe - 0x800 - 1) * sizeof(RTUNICP))
292 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "RTUNICP U+%#x\n", off / sizeof(RTUNICP) + 0x800 + 1);
293 else
294 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "RTUNICP U+%#x\n", off / sizeof(RTUNICP) + 0x800 + 1 + 2);
295 }
296}
297
298int mymemcmp(const void *pv1, const void *pv2, size_t cb, int cBits)
299{
300 const uint8_t *pb1 = (const uint8_t *)pv1;
301 const uint8_t *pb2 = (const uint8_t *)pv2;
302 for (size_t off = 0; off < cb; off++)
303 {
304 if (pb1[off] != pb2[off])
305 {
306 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "mismatch at %#x: ", off);
307 whereami(cBits, off);
308 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off-1, pb1[off-1], pb2[off-1]);
309 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, "*%#x: %02x != %02x!\n", off, pb1[off], pb2[off]);
310 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+1, pb1[off+1], pb2[off+1]);
311 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+2, pb1[off+2], pb2[off+2]);
312 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+3, pb1[off+3], pb2[off+3]);
313 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+4, pb1[off+4], pb2[off+4]);
314 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+5, pb1[off+5], pb2[off+5]);
315 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+6, pb1[off+6], pb2[off+6]);
316 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+7, pb1[off+7], pb2[off+7]);
317 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+8, pb1[off+8], pb2[off+8]);
318 RTTestPrintf(NIL_RTTEST, RTTESTLVL_FAILURE, " %#x: %02x != %02x!\n", off+9, pb1[off+9], pb2[off+9]);
319 return 1;
320 }
321 }
322 return 0;
323}
324
325
326void InitStrings()
327{
328 /*
329 * Generate unicode string containing all the legal UTF-16 codepoints, both UTF-16 and UTF-8 version.
330 */
331 /* the simple code point array first */
332 unsigned i = 0;
333 RTUNICP uc = 1;
334 while (uc < 0xd800)
335 g_uszAll[i++] = uc++;
336 uc = 0xe000;
337 while (uc < 0xfffe)
338 g_uszAll[i++] = uc++;
339 uc = 0x10000;
340 while (uc < 0x110000)
341 g_uszAll[i++] = uc++;
342 g_uszAll[i++] = 0;
343 Assert(RT_ELEMENTS(g_uszAll) == i);
344
345 /* the utf-16 one */
346 i = 0;
347 uc = 1;
348 //RTPrintf("tstUtf8: %#x=%#x", i, uc);
349 while (uc < 0xd800)
350 g_wszAll[i++] = uc++;
351 uc = 0xe000;
352 //RTPrintf(" %#x=%#x", i, uc);
353 while (uc < 0xfffe)
354 g_wszAll[i++] = uc++;
355 uc = 0x10000;
356 //RTPrintf(" %#x=%#x", i, uc);
357 while (uc < 0x110000)
358 {
359 g_wszAll[i++] = 0xd800 | ((uc - 0x10000) >> 10);
360 g_wszAll[i++] = 0xdc00 | ((uc - 0x10000) & 0x3ff);
361 uc++;
362 }
363 //RTPrintf(" %#x=%#x\n", i, uc);
364 g_wszAll[i++] = '\0';
365 Assert(RT_ELEMENTS(g_wszAll) == i);
366
367 /*
368 * The utf-8 one
369 */
370 i = 0;
371 uc = 1;
372 //RTPrintf("tstUtf8: %#x=%#x", i, uc);
373 while (uc < 0x80)
374 g_szAll[i++] = uc++;
375 //RTPrintf(" %#x=%#x", i, uc);
376 while (uc < 0x800)
377 {
378 g_szAll[i++] = 0xc0 | (uc >> 6);
379 g_szAll[i++] = 0x80 | (uc & 0x3f);
380 Assert(!((uc >> 6) & ~0x1f));
381 uc++;
382 }
383 //RTPrintf(" %#x=%#x", i, uc);
384 while (uc < 0xd800)
385 {
386 g_szAll[i++] = 0xe0 | (uc >> 12);
387 g_szAll[i++] = 0x80 | ((uc >> 6) & 0x3f);
388 g_szAll[i++] = 0x80 | (uc & 0x3f);
389 Assert(!((uc >> 12) & ~0xf));
390 uc++;
391 }
392 uc = 0xe000;
393 //RTPrintf(" %#x=%#x", i, uc);
394 while (uc < 0xfffe)
395 {
396 g_szAll[i++] = 0xe0 | (uc >> 12);
397 g_szAll[i++] = 0x80 | ((uc >> 6) & 0x3f);
398 g_szAll[i++] = 0x80 | (uc & 0x3f);
399 Assert(!((uc >> 12) & ~0xf));
400 uc++;
401 }
402 uc = 0x10000;
403 //RTPrintf(" %#x=%#x", i, uc);
404 while (uc < 0x110000)
405 {
406 g_szAll[i++] = 0xf0 | (uc >> 18);
407 g_szAll[i++] = 0x80 | ((uc >> 12) & 0x3f);
408 g_szAll[i++] = 0x80 | ((uc >> 6) & 0x3f);
409 g_szAll[i++] = 0x80 | (uc & 0x3f);
410 Assert(!((uc >> 18) & ~0x7));
411 uc++;
412 }
413 //RTPrintf(" %#x=%#x\n", i, uc);
414 g_szAll[i++] = '\0';
415 Assert(RT_ELEMENTS(g_szAll) == i);
416}
417
418
419void test2(RTTEST hTest)
420{
421 /*
422 * Convert to UTF-8 and back.
423 */
424 RTTestSub(hTest, "UTF-16 -> UTF-8 -> UTF-16");
425 char *pszUtf8;
426 int rc = RTUtf16ToUtf8(&g_wszAll[0], &pszUtf8);
427 if (rc == VINF_SUCCESS)
428 {
429 if (mymemcmp(pszUtf8, g_szAll, sizeof(g_szAll), 8))
430 RTTestFailed(hTest, "UTF-16 -> UTF-8 mismatch!");
431
432 PRTUTF16 pwszUtf16;
433 rc = RTStrToUtf16(pszUtf8, &pwszUtf16);
434 if (rc == VINF_SUCCESS)
435 {
436 if (mymemcmp(pwszUtf16, g_wszAll, sizeof(g_wszAll), 16))
437 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed compare!");
438 RTUtf16Free(pwszUtf16);
439 }
440 else
441 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed, rc=%Rrc.", rc);
442 RTStrFree(pszUtf8);
443 }
444 else
445 RTTestFailed(hTest, "UTF-16 -> UTF-8 failed, rc=%Rrc.", rc);
446
447
448 /*
449 * Convert to UTF-16 and back. (just in case the above test fails)
450 */
451 RTTestSub(hTest, "UTF-8 -> UTF-16 -> UTF-8");
452 PRTUTF16 pwszUtf16;
453 rc = RTStrToUtf16(&g_szAll[0], &pwszUtf16);
454 if (rc == VINF_SUCCESS)
455 {
456 if (mymemcmp(pwszUtf16, g_wszAll, sizeof(g_wszAll), 16))
457 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed compare!");
458
459 rc = RTUtf16ToUtf8(pwszUtf16, &pszUtf8);
460 if (rc == VINF_SUCCESS)
461 {
462 if (mymemcmp(pszUtf8, g_szAll, sizeof(g_szAll), 8))
463 RTTestFailed(hTest, "UTF-16 -> UTF-8 failed compare!");
464 RTStrFree(pszUtf8);
465 }
466 else
467 RTTestFailed(hTest, "UTF-16 -> UTF-8 failed, rc=%Rrc.", rc);
468 RTUtf16Free(pwszUtf16);
469 }
470 else
471 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed, rc=%Rrc.", rc);
472
473 /*
474 * Convert UTF-8 to CPs.
475 */
476 RTTestSub(hTest, "UTF-8 -> UNI -> UTF-8");
477 PRTUNICP paCps;
478 rc = RTStrToUni(g_szAll, &paCps);
479 if (rc == VINF_SUCCESS)
480 {
481 if (mymemcmp(paCps, g_uszAll, sizeof(g_uszAll), 32))
482 RTTestFailed(hTest, "UTF-8 -> UTF-16 failed, rc=%Rrc.", rc);
483
484 size_t cCps;
485 rc = RTStrToUniEx(g_szAll, RTSTR_MAX, &paCps, RT_ELEMENTS(g_uszAll), &cCps);
486 if (rc == VINF_SUCCESS)
487 {
488 if (cCps != RT_ELEMENTS(g_uszAll) - 1)
489 RTTestFailed(hTest, "wrong Code Point count %zu, expected %zu\n", cCps, RT_ELEMENTS(g_uszAll) - 1);
490 }
491 else
492 RTTestFailed(hTest, "UTF-8 -> Code Points failed, rc=%Rrc.\n", rc);
493
494 /** @todo RTCpsToUtf8 or something. */
495 }
496 else
497 RTTestFailed(hTest, "UTF-8 -> Code Points failed, rc=%Rrc.\n", rc);
498
499 /*
500 * Check the various string lengths.
501 */
502 RTTestSub(hTest, "Lengths");
503 size_t cuc1 = RTStrCalcUtf16Len(g_szAll);
504 size_t cuc2 = RTUtf16Len(g_wszAll);
505 if (cuc1 != cuc2)
506 RTTestFailed(hTest, "cuc1=%zu != cuc2=%zu\n", cuc1, cuc2);
507 //size_t cuc3 = RTUniLen(g_uszAll);
508
509
510 /*
511 * Enumerate the strings.
512 */
513 RTTestSub(hTest, "Code Point Getters and Putters");
514 char *pszPut1Base = (char *)RTMemAlloc(sizeof(g_szAll));
515 AssertRelease(pszPut1Base);
516 char *pszPut1 = pszPut1Base;
517 PRTUTF16 pwszPut2Base = (PRTUTF16)RTMemAlloc(sizeof(g_wszAll));
518 AssertRelease(pwszPut2Base);
519 PRTUTF16 pwszPut2 = pwszPut2Base;
520 const char *psz1 = g_szAll;
521 const char *psz2 = g_szAll;
522 PCRTUTF16 pwsz3 = g_wszAll;
523 PCRTUTF16 pwsz4 = g_wszAll;
524 for (;;)
525 {
526 /*
527 * getters
528 */
529 RTUNICP uc1;
530 rc = RTStrGetCpEx(&psz1, &uc1);
531 if (RT_FAILURE(rc))
532 {
533 RTTestFailed(hTest, "RTStrGetCpEx failed with rc=%Rrc at %.10Rhxs", rc, psz2);
534 whereami(8, psz2 - &g_szAll[0]);
535 break;
536 }
537 char *pszPrev1 = RTStrPrevCp(g_szAll, psz1);
538 if (pszPrev1 != psz2)
539 {
540 RTTestFailed(hTest, "RTStrPrevCp returned %p expected %p!", pszPrev1, psz2);
541 whereami(8, psz2 - &g_szAll[0]);
542 break;
543 }
544 RTUNICP uc2 = RTStrGetCp(psz2);
545 if (uc2 != uc1)
546 {
547 RTTestFailed(hTest, "RTStrGetCpEx and RTStrGetCp returned different CPs: %RTunicp != %RTunicp", uc2, uc1);
548 whereami(8, psz2 - &g_szAll[0]);
549 break;
550 }
551 psz2 = RTStrNextCp(psz2);
552 if (psz2 != psz1)
553 {
554 RTTestFailed(hTest, "RTStrGetCpEx and RTStrGetNext returned different next pointer!");
555 whereami(8, psz2 - &g_szAll[0]);
556 break;
557 }
558
559 RTUNICP uc3;
560 rc = RTUtf16GetCpEx(&pwsz3, &uc3);
561 if (RT_FAILURE(rc))
562 {
563 RTTestFailed(hTest, "RTUtf16GetCpEx failed with rc=%Rrc at %.10Rhxs", rc, pwsz4);
564 whereami(16, pwsz4 - &g_wszAll[0]);
565 break;
566 }
567 if (uc3 != uc2)
568 {
569 RTTestFailed(hTest, "RTUtf16GetCpEx and RTStrGetCp returned different CPs: %RTunicp != %RTunicp", uc3, uc2);
570 whereami(16, pwsz4 - &g_wszAll[0]);
571 break;
572 }
573 RTUNICP uc4 = RTUtf16GetCp(pwsz4);
574 if (uc3 != uc4)
575 {
576 RTTestFailed(hTest, "RTUtf16GetCpEx and RTUtf16GetCp returned different CPs: %RTunicp != %RTunicp", uc3, uc4);
577 whereami(16, pwsz4 - &g_wszAll[0]);
578 break;
579 }
580 pwsz4 = RTUtf16NextCp(pwsz4);
581 if (pwsz4 != pwsz3)
582 {
583 RTTestFailed(hTest, "RTUtf16GetCpEx and RTUtf16GetNext returned different next pointer!");
584 whereami(8, pwsz4 - &g_wszAll[0]);
585 break;
586 }
587
588
589 /*
590 * putters
591 */
592 pszPut1 = RTStrPutCp(pszPut1, uc1);
593 if (pszPut1 - pszPut1Base != psz1 - &g_szAll[0])
594 {
595 RTTestFailed(hTest, "RTStrPutCp is not at the same offset! %p != %p",
596 pszPut1 - pszPut1Base, psz1 - &g_szAll[0]);
597 whereami(8, psz2 - &g_szAll[0]);
598 break;
599 }
600
601 pwszPut2 = RTUtf16PutCp(pwszPut2, uc3);
602 if (pwszPut2 - pwszPut2Base != pwsz3 - &g_wszAll[0])
603 {
604 RTTestFailed(hTest, "RTStrPutCp is not at the same offset! %p != %p",
605 pwszPut2 - pwszPut2Base, pwsz3 - &g_wszAll[0]);
606 whereami(8, pwsz4 - &g_wszAll[0]);
607 break;
608 }
609
610
611 /* the end? */
612 if (!uc1)
613 break;
614 }
615
616 /* check output if we seems to have made it thru it all. */
617 if (psz2 == &g_szAll[sizeof(g_szAll)])
618 {
619 if (mymemcmp(pszPut1Base, g_szAll, sizeof(g_szAll), 8))
620 RTTestFailed(hTest, "RTStrPutCp encoded the string incorrectly.");
621 if (mymemcmp(pwszPut2Base, g_wszAll, sizeof(g_wszAll), 16))
622 RTTestFailed(hTest, "RTUtf16PutCp encoded the string incorrectly.");
623 }
624
625 RTMemFree(pszPut1Base);
626 RTMemFree(pwszPut2Base);
627
628 RTTestSubDone(hTest);
629}
630
631
632/**
633 * Check case insensitivity.
634 */
635void test3(RTTEST hTest)
636{
637 RTTestSub(hTest, "Case Sensitivitity");
638
639 if ( RTUniCpToLower('a') != 'a'
640 || RTUniCpToLower('A') != 'a'
641 || RTUniCpToLower('b') != 'b'
642 || RTUniCpToLower('B') != 'b'
643 || RTUniCpToLower('Z') != 'z'
644 || RTUniCpToLower('z') != 'z'
645 || RTUniCpToUpper('c') != 'C'
646 || RTUniCpToUpper('C') != 'C'
647 || RTUniCpToUpper('z') != 'Z'
648 || RTUniCpToUpper('Z') != 'Z')
649 RTTestFailed(hTest, "RTUniToUpper/Lower failed basic tests.\n");
650
651 if (RTUtf16ICmp(g_wszAll, g_wszAll))
652 RTTestFailed(hTest, "RTUtf16ICmp failed the basic test.\n");
653
654 if (RTUtf16Cmp(g_wszAll, g_wszAll))
655 RTTestFailed(hTest, "RTUtf16Cmp failed the basic test.\n");
656
657 static RTUTF16 s_wszTst1a[] = { 'a', 'B', 'c', 'D', 'E', 'f', 'g', 'h', 'i', 'j', 'K', 'L', 'm', 'N', 'o', 'P', 'q', 'r', 'S', 't', 'u', 'V', 'w', 'x', 'Y', 'Z', 0xc5, 0xc6, 0xf8, 0 };
658 static RTUTF16 s_wszTst1b[] = { 'A', 'B', 'c', 'd', 'e', 'F', 'G', 'h', 'i', 'J', 'k', 'l', 'M', 'n', 'O', 'p', 'Q', 'R', 's', 't', 'U', 'v', 'w', 'X', 'y', 'z', 0xe5, 0xe6, 0xd8, 0 };
659 if ( RTUtf16ICmp(s_wszTst1b, s_wszTst1b)
660 || RTUtf16ICmp(s_wszTst1a, s_wszTst1a)
661 || RTUtf16ICmp(s_wszTst1a, s_wszTst1b)
662 || RTUtf16ICmp(s_wszTst1b, s_wszTst1a)
663 )
664 RTTestFailed(hTest, "RTUtf16ICmp failed the alphabet test.\n");
665
666 if ( RTUtf16Cmp(s_wszTst1b, s_wszTst1b)
667 || RTUtf16Cmp(s_wszTst1a, s_wszTst1a)
668 || !RTUtf16Cmp(s_wszTst1a, s_wszTst1b)
669 || !RTUtf16Cmp(s_wszTst1b, s_wszTst1a)
670 )
671 RTTestFailed(hTest, "RTUtf16Cmp failed the alphabet test.\n");
672
673 RTTestSubDone(hTest);
674}
675
676
677/**
678 * Test the RTStr*Cmp functions.
679 */
680void TstRTStrXCmp(RTTEST hTest)
681{
682#define CHECK_DIFF(expr, op) \
683 do \
684 { \
685 int iDiff = expr; \
686 if (!(iDiff op 0)) \
687 RTTestFailed(hTest, "%d: %d " #op " 0: %s\n", __LINE__, iDiff, #expr); \
688 } while (0)
689
690/** @todo test the non-ascii bits. */
691
692 RTTestSub(hTest, "RTStrCmp");
693 CHECK_DIFF(RTStrCmp(NULL, NULL), == );
694 CHECK_DIFF(RTStrCmp(NULL, ""), < );
695 CHECK_DIFF(RTStrCmp("", NULL), > );
696 CHECK_DIFF(RTStrCmp("", ""), == );
697 CHECK_DIFF(RTStrCmp("abcdef", "abcdef"), == );
698 CHECK_DIFF(RTStrCmp("abcdef", "abcde"), > );
699 CHECK_DIFF(RTStrCmp("abcde", "abcdef"), < );
700 CHECK_DIFF(RTStrCmp("abcdeg", "abcdef"), > );
701 CHECK_DIFF(RTStrCmp("abcdef", "abcdeg"), < );
702 CHECK_DIFF(RTStrCmp("abcdeF", "abcdef"), < );
703 CHECK_DIFF(RTStrCmp("abcdef", "abcdeF"), > );
704
705
706 RTTestSub(hTest, "RTStrNCmp");
707 CHECK_DIFF(RTStrNCmp(NULL, NULL, RTSTR_MAX), == );
708 CHECK_DIFF(RTStrNCmp(NULL, "", RTSTR_MAX), < );
709 CHECK_DIFF(RTStrNCmp("", NULL, RTSTR_MAX), > );
710 CHECK_DIFF(RTStrNCmp("", "", RTSTR_MAX), == );
711 CHECK_DIFF(RTStrNCmp("abcdef", "abcdef", RTSTR_MAX), == );
712 CHECK_DIFF(RTStrNCmp("abcdef", "abcde", RTSTR_MAX), > );
713 CHECK_DIFF(RTStrNCmp("abcde", "abcdef", RTSTR_MAX), < );
714 CHECK_DIFF(RTStrNCmp("abcdeg", "abcdef", RTSTR_MAX), > );
715 CHECK_DIFF(RTStrNCmp("abcdef", "abcdeg", RTSTR_MAX), < );
716 CHECK_DIFF(RTStrNCmp("abcdeF", "abcdef", RTSTR_MAX), < );
717 CHECK_DIFF(RTStrNCmp("abcdef", "abcdeF", RTSTR_MAX), > );
718
719 CHECK_DIFF(RTStrNCmp("abcdef", "fedcba", 0), ==);
720 CHECK_DIFF(RTStrNCmp("abcdef", "abcdeF", 5), ==);
721 CHECK_DIFF(RTStrNCmp("abcdef", "abcdeF", 6), > );
722
723
724 RTTestSub(hTest, "RTStrICmp");
725 CHECK_DIFF(RTStrICmp(NULL, NULL), == );
726 CHECK_DIFF(RTStrICmp(NULL, ""), < );
727 CHECK_DIFF(RTStrICmp("", NULL), > );
728 CHECK_DIFF(RTStrICmp("", ""), == );
729 CHECK_DIFF(RTStrICmp("abcdef", "abcdef"), == );
730 CHECK_DIFF(RTStrICmp("abcdef", "abcde"), > );
731 CHECK_DIFF(RTStrICmp("abcde", "abcdef"), < );
732 CHECK_DIFF(RTStrICmp("abcdeg", "abcdef"), > );
733 CHECK_DIFF(RTStrICmp("abcdef", "abcdeg"), < );
734
735 CHECK_DIFF(RTStrICmp("abcdeF", "abcdef"), ==);
736 CHECK_DIFF(RTStrICmp("abcdef", "abcdeF"), ==);
737 CHECK_DIFF(RTStrICmp("ABCDEF", "abcdef"), ==);
738 CHECK_DIFF(RTStrICmp("abcdef", "ABCDEF"), ==);
739 CHECK_DIFF(RTStrICmp("AbCdEf", "aBcDeF"), ==);
740 CHECK_DIFF(RTStrICmp("AbCdEg", "aBcDeF"), > );
741 CHECK_DIFF(RTStrICmp("AbCdEG", "aBcDef"), > ); /* diff performed on the lower case cp. */
742
743
744
745 RTTestSub(hTest, "RTStrNICmp");
746 CHECK_DIFF(RTStrNICmp(NULL, NULL, RTSTR_MAX), == );
747 CHECK_DIFF(RTStrNICmp(NULL, "", RTSTR_MAX), < );
748 CHECK_DIFF(RTStrNICmp("", NULL, RTSTR_MAX), > );
749 CHECK_DIFF(RTStrNICmp("", "", RTSTR_MAX), == );
750 CHECK_DIFF(RTStrNICmp(NULL, NULL, 0), == );
751 CHECK_DIFF(RTStrNICmp(NULL, "", 0), == );
752 CHECK_DIFF(RTStrNICmp("", NULL, 0), == );
753 CHECK_DIFF(RTStrNICmp("", "", 0), == );
754 CHECK_DIFF(RTStrNICmp("abcdef", "abcdef", RTSTR_MAX), == );
755 CHECK_DIFF(RTStrNICmp("abcdef", "abcde", RTSTR_MAX), > );
756 CHECK_DIFF(RTStrNICmp("abcde", "abcdef", RTSTR_MAX), < );
757 CHECK_DIFF(RTStrNICmp("abcdeg", "abcdef", RTSTR_MAX), > );
758 CHECK_DIFF(RTStrNICmp("abcdef", "abcdeg", RTSTR_MAX), < );
759
760 CHECK_DIFF(RTStrNICmp("abcdeF", "abcdef", RTSTR_MAX), ==);
761 CHECK_DIFF(RTStrNICmp("abcdef", "abcdeF", RTSTR_MAX), ==);
762 CHECK_DIFF(RTStrNICmp("ABCDEF", "abcdef", RTSTR_MAX), ==);
763 CHECK_DIFF(RTStrNICmp("abcdef", "ABCDEF", RTSTR_MAX), ==);
764 CHECK_DIFF(RTStrNICmp("AbCdEf", "aBcDeF", RTSTR_MAX), ==);
765 CHECK_DIFF(RTStrNICmp("AbCdEg", "aBcDeF", RTSTR_MAX), > );
766 CHECK_DIFF(RTStrNICmp("AbCdEG", "aBcDef", RTSTR_MAX), > ); /* diff performed on the lower case cp. */
767
768 CHECK_DIFF(RTStrNICmp("ABCDEF", "fedcba", 0), ==);
769 CHECK_DIFF(RTStrNICmp("AbCdEg", "aBcDeF", 5), ==);
770 CHECK_DIFF(RTStrNICmp("AbCdEf", "aBcDeF", 5), ==);
771 CHECK_DIFF(RTStrNICmp("AbCdE", "aBcDe", 5), ==);
772 CHECK_DIFF(RTStrNICmp("AbCdE", "aBcDeF", 5), ==);
773 CHECK_DIFF(RTStrNICmp("AbCdEf", "aBcDe", 5), ==);
774 CHECK_DIFF(RTStrNICmp("AbCdEg", "aBcDeF", 6), > );
775 CHECK_DIFF(RTStrNICmp("AbCdEG", "aBcDef", 6), > ); /* diff performed on the lower case cp. */
776 /* We should continue using byte comparison when we hit the invalid CP. Will assert in debug builds. */
777 // CHECK_DIFF(RTStrNICmp("AbCd\xff""eg", "aBcD\xff""eF", 6), ==);
778
779 RTTestSubDone(hTest);
780}
781
782
783
784/**
785 * Check case insensitivity.
786 */
787void TstRTStrPurgeEncoding(RTTEST hTest)
788{
789 RTTestSub(hTest, "RTStrPurgeEncoding");
790
791 /*
792 * Test some good strings.
793 */
794 char sz1[] = "1234567890wertyuiopsdfghjklzxcvbnm";
795 char sz1Copy[sizeof(sz1)];
796 memcpy(sz1Copy, sz1, sizeof(sz1));
797
798 RTTESTI_CHECK_RETV(RTStrPurgeEncoding(sz1) == 0);
799 RTTESTI_CHECK_RETV(!memcmp(sz1, sz1Copy, sizeof(sz1)));
800
801 char *pszAll = RTStrDup(g_szAll);
802 if (pszAll)
803 {
804 RTTESTI_CHECK(RTStrPurgeEncoding(pszAll) == 0);
805 RTTESTI_CHECK(!memcmp(pszAll, g_szAll, sizeof(g_szAll)));
806 RTStrFree(pszAll);
807 }
808
809 /*
810 * Test some bad stuff.
811 */
812 struct
813 {
814 size_t cErrors;
815 unsigned char szIn[5];
816 const char *pszExpect;
817 } aTests[] =
818 {
819 { 0, { '1', '2', '3', '4', '\0' }, "1234" },
820 { 1, { 0x80, '2', '3', '4', '\0' }, "?234" },
821 { 1, { '1', 0x80, '3', '4', '\0' }, "1?34" },
822 { 1, { '1', '2', 0x80, '4', '\0' }, "12?4" },
823 { 1, { '1', '2', '3', 0x80, '\0' }, "123?" },
824 { 2, { 0x80, 0x81, '3', '4', '\0' }, "??34" },
825 { 2, { '1', 0x80, 0x81, '4', '\0' }, "1??4" },
826 { 2, { '1', '2', 0x80, 0x81, '\0' }, "12??" },
827 };
828 for (size_t i = 0; i < RT_ELEMENTS(aTests); i++)
829 {
830 size_t cErrors = RTStrPurgeEncoding((char *)aTests[i].szIn);
831 if (cErrors != aTests[i].cErrors)
832 RTTestFailed(hTest, "#%u: cErrors=%u expected %u\n", i, cErrors, aTests[i].cErrors);
833 else if (strcmp((char *)aTests[i].szIn, aTests[i].pszExpect))
834 RTTestFailed(hTest, "#%u: %.5Rhxs expected %.5Rhxs (%s)\n", i, aTests[i].szIn, aTests[i].pszExpect, aTests[i].pszExpect);
835 }
836
837 RTTestSubDone(hTest);
838}
839
840
841/**
842 * Benchmark stuff.
843 */
844void Benchmarks(RTTEST hTest)
845{
846 static union
847 {
848 RTUTF16 wszBuf[sizeof(g_wszAll)];
849 char szBuf[sizeof(g_szAll)];
850 } s_Buf;
851
852 RTTestSub(hTest, "Benchmarks");
853/** @todo add RTTest* methods for reporting benchmark results. */
854 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Benchmarking RTStrToUtf16Ex: "); /** @todo figure this stuff into the test framework. */
855 PRTUTF16 pwsz = &s_Buf.wszBuf[0];
856 int rc = RTStrToUtf16Ex(&g_szAll[0], RTSTR_MAX, &pwsz, RT_ELEMENTS(s_Buf.wszBuf), NULL);
857 if (RT_SUCCESS(rc))
858 {
859 int i;
860 uint64_t u64Start = RTTimeNanoTS();
861 for (i = 0; i < 100; i++)
862 {
863 rc = RTStrToUtf16Ex(&g_szAll[0], RTSTR_MAX, &pwsz, RT_ELEMENTS(s_Buf.wszBuf), NULL);
864 if (RT_FAILURE(rc))
865 {
866 RTTestFailed(hTest, "UTF-8 -> UTF-16 benchmark failed at i=%d, rc=%Rrc\n", i, rc);
867 break;
868 }
869 }
870 uint64_t u64Elapsed = RTTimeNanoTS() - u64Start;
871 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%d in %'RI64 ns\n", i, u64Elapsed);
872 }
873
874 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "Benchmarking RTUtf16ToUtf8Ex: ");
875 char *psz = &s_Buf.szBuf[0];
876 rc = RTUtf16ToUtf8Ex(&g_wszAll[0], RTSTR_MAX, &psz, RT_ELEMENTS(s_Buf.szBuf), NULL);
877 if (RT_SUCCESS(rc))
878 {
879 int i;
880 uint64_t u64Start = RTTimeNanoTS();
881 for (i = 0; i < 100; i++)
882 {
883 rc = RTUtf16ToUtf8Ex(&g_wszAll[0], RTSTR_MAX, &psz, RT_ELEMENTS(s_Buf.szBuf), NULL);
884 if (RT_FAILURE(rc))
885 {
886 RTTestFailed(hTest, "UTF-16 -> UTF-8 benchmark failed at i=%d, rc=%Rrc\n", i, rc);
887 break;
888 }
889 }
890 uint64_t u64Elapsed = RTTimeNanoTS() - u64Start;
891 RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "%d in %'RI64 ns\n", i, u64Elapsed);
892 }
893
894 RTTestSubDone(hTest);
895}
896
897
898/**
899 * Tests RTStrEnd
900 */
901static void testStrEnd(RTTEST hTest)
902{
903 RTTestSub(hTest, "RTStrEnd");
904
905 static char const s_szEmpty[1] = "";
906 RTTESTI_CHECK(RTStrEnd(s_szEmpty, 0) == NULL);
907 RTTESTI_CHECK(RTStrEnd(s_szEmpty, 1) == &s_szEmpty[0]);
908 for (size_t i = 0; i < _1M; i++)
909 RTTESTI_CHECK(RTStrEnd(s_szEmpty, ~i) == &s_szEmpty[0]);
910
911}
912
913
914/**
915 * Tests RTStrStr and RTStrIStr.
916 */
917static void testStrStr(RTTEST hTest)
918{
919#define CHECK_NULL(expr) \
920 do { \
921 const char *pszRet = expr; \
922 if (pszRet != NULL) \
923 RTTestFailed(hTest, "%d: %#x -> %s expected NULL", __LINE__, #expr, pszRet); \
924 } while (0)
925
926#define CHECK(expr, expect) \
927 do { \
928 const char *pszRet = expr; \
929 if ( (pszRet != NULL && (expect) == NULL) \
930 || (pszRet == NULL && (expect) != NULL) \
931 || strcmp(pszRet, (expect)) \
932 ) \
933 RTTestFailed(hTest, "%d: %#x -> %s expected %s", __LINE__, #expr, pszRet, (expect)); \
934 } while (0)
935
936
937 RTTestSub(hTest, "RTStrStr");
938 CHECK(RTStrStr("abcdef", ""), "abcdef");
939 CHECK_NULL(RTStrStr("abcdef", NULL));
940 CHECK_NULL(RTStrStr(NULL, ""));
941 CHECK_NULL(RTStrStr(NULL, NULL));
942 CHECK(RTStrStr("abcdef", "abcdef"), "abcdef");
943 CHECK(RTStrStr("abcdef", "b"), "bcdef");
944 CHECK(RTStrStr("abcdef", "bcdef"), "bcdef");
945 CHECK(RTStrStr("abcdef", "cdef"), "cdef");
946 CHECK(RTStrStr("abcdef", "cde"), "cdef");
947 CHECK(RTStrStr("abcdef", "cd"), "cdef");
948 CHECK(RTStrStr("abcdef", "c"), "cdef");
949 CHECK(RTStrStr("abcdef", "f"), "f");
950 CHECK(RTStrStr("abcdef", "ef"), "ef");
951 CHECK(RTStrStr("abcdef", "e"), "ef");
952 CHECK_NULL(RTStrStr("abcdef", "z"));
953 CHECK_NULL(RTStrStr("abcdef", "A"));
954 CHECK_NULL(RTStrStr("abcdef", "F"));
955
956 RTTestSub(hTest, "RTStrIStr");
957 CHECK(RTStrIStr("abcdef", ""), "abcdef");
958 CHECK_NULL(RTStrIStr("abcdef", NULL));
959 CHECK_NULL(RTStrIStr(NULL, ""));
960 CHECK_NULL(RTStrIStr(NULL, NULL));
961 CHECK(RTStrIStr("abcdef", "abcdef"), "abcdef");
962 CHECK(RTStrIStr("abcdef", "Abcdef"), "abcdef");
963 CHECK(RTStrIStr("abcdef", "ABcDeF"), "abcdef");
964 CHECK(RTStrIStr("abcdef", "b"), "bcdef");
965 CHECK(RTStrIStr("abcdef", "B"), "bcdef");
966 CHECK(RTStrIStr("abcdef", "bcdef"), "bcdef");
967 CHECK(RTStrIStr("abcdef", "BCdEf"), "bcdef");
968 CHECK(RTStrIStr("abcdef", "bCdEf"), "bcdef");
969 CHECK(RTStrIStr("abcdef", "bcdEf"), "bcdef");
970 CHECK(RTStrIStr("abcdef", "BcdEf"), "bcdef");
971 CHECK(RTStrIStr("abcdef", "cdef"), "cdef");
972 CHECK(RTStrIStr("abcdef", "cde"), "cdef");
973 CHECK(RTStrIStr("abcdef", "cd"), "cdef");
974 CHECK(RTStrIStr("abcdef", "c"), "cdef");
975 CHECK(RTStrIStr("abcdef", "f"), "f");
976 CHECK(RTStrIStr("abcdeF", "F"), "F");
977 CHECK(RTStrIStr("abcdef", "F"), "f");
978 CHECK(RTStrIStr("abcdef", "ef"), "ef");
979 CHECK(RTStrIStr("EeEef", "e"), "EeEef");
980 CHECK(RTStrIStr("EeEef", "E"), "EeEef");
981 CHECK(RTStrIStr("EeEef", "EE"), "EeEef");
982 CHECK(RTStrIStr("EeEef", "EEE"), "EeEef");
983 CHECK(RTStrIStr("EeEef", "EEEF"), "eEef");
984 CHECK_NULL(RTStrIStr("EeEef", "z"));
985
986#undef CHECK
987#undef CHECK_NULL
988 RTTestSubDone(hTest);
989}
990
991
992void testUtf8Latin1(RTTEST hTest)
993{
994 RTTestSub(hTest, "Latin-1 <-> Utf-8 conversion functions");
995
996 /* Test Utf8 -> Latin1 */
997 size_t cch_szAll = 0;
998 size_t cbShort = RTStrCalcLatin1Len(g_szAll);
999 RTTEST_CHECK(hTest, cbShort == 0);
1000 int rc = RTStrCalcLatin1LenEx(g_szAll, 383, &cch_szAll);
1001 RTTEST_CHECK(hTest, (cch_szAll == 255));
1002 rc = RTStrCalcLatin1LenEx(g_szAll, RTSTR_MAX, &cch_szAll);
1003 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION);
1004 char *psz = NULL;
1005 char szShort[256] = { 0 };
1006 memcpy(szShort, g_szAll, 255);
1007 cbShort = RTStrCalcLatin1Len(szShort);
1008 RTTEST_CHECK(hTest, cbShort == 191);
1009 rc = RTStrToLatin1(szShort, &psz);
1010 RTTEST_CHECK_RC_OK(hTest, rc);
1011 if (RT_SUCCESS(rc))
1012 {
1013 RTTEST_CHECK(hTest, (strlen(psz) == 191));
1014 for (unsigned i = 0, j = 1; psz[i] != '\0'; ++i, ++j)
1015 if (psz[i] != (char) j)
1016 {
1017 RTTestFailed(hTest, "conversion of g_szAll to Latin1 failed at position %u\n", i);
1018 break;
1019 }
1020 }
1021 RTStrFree(psz);
1022 rc = RTStrToLatin1(g_szAll, &psz);
1023 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION);
1024 char sz[512];
1025 char *psz2 = &sz[0];
1026 size_t cchActual = 0;
1027 rc = RTStrToLatin1Ex(g_szAll, sizeof(sz) - 1, &psz2, sizeof(sz),
1028 &cchActual);
1029 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION);
1030 RTTEST_CHECK_MSG(hTest, cchActual == 0,
1031 (hTest, "cchActual=%lu\n", cchActual));
1032 rc = RTStrToLatin1Ex(g_szAll, 383, &psz2, sizeof(sz),
1033 &cchActual);
1034 RTTEST_CHECK_RC_OK(hTest, rc);
1035 if (RT_SUCCESS(rc))
1036 {
1037 RTTEST_CHECK(hTest, (cchActual == 255));
1038 RTTEST_CHECK(hTest, (cchActual == strlen(sz)));
1039 for (unsigned i = 0, j = 1; psz2[i] != '\0'; ++i, ++j)
1040 if (psz2[i] != (char) j)
1041 {
1042 RTTestFailed(hTest, "second conversion of g_szAll to Latin1 failed at position %u\n", i);
1043 break;
1044 }
1045 }
1046 rc = RTStrToLatin1Ex(g_szAll, 129, &psz2, 128, &cchActual);
1047 RTTEST_CHECK_RC(hTest, rc, VERR_BUFFER_OVERFLOW);
1048 RTTEST_CHECK_MSG(hTest, cchActual == 128,
1049 (hTest, "cchActual=%lu\n", cchActual));
1050 rc = RTStrToLatin1Ex(g_szAll, 383, &psz, 0, &cchActual);
1051 RTTEST_CHECK_RC_OK(hTest, rc);
1052 if (RT_SUCCESS(rc))
1053 {
1054 RTTEST_CHECK(hTest, (cchActual == 255));
1055 RTTEST_CHECK(hTest, (cchActual == strlen(psz)));
1056 for (unsigned i = 0, j = 1; psz[i] != '\0'; ++i, ++j)
1057 if ( ((j < 0x100) && (psz[i] != (char) j))
1058 || ((j > 0xff) && psz[i] != '?'))
1059 {
1060 RTTestFailed(hTest, "third conversion of g_szAll to Latin1 failed at position %u\n", i);
1061 break;
1062 }
1063 }
1064 const char *pszBad = "Hello\xDC\xD8";
1065 rc = RTStrToLatin1Ex(pszBad, RTSTR_MAX, &psz2, sizeof(sz),
1066 &cchActual);
1067 RTTEST_CHECK_RC(hTest, rc, VERR_INVALID_UTF8_ENCODING);
1068 RTStrFree(psz);
1069
1070 /* Test Latin1 -> Utf8 */
1071 const char *pszLat1 = "\x01\x20\x40\x80\x81";
1072 RTTEST_CHECK(hTest, RTLatin1CalcUtf8Len(pszLat1) == 7);
1073 rc = RTLatin1CalcUtf8LenEx(pszLat1, 3, &cchActual);
1074 RTTEST_CHECK_RC_OK(hTest, rc);
1075 if (RT_SUCCESS(rc))
1076 RTTEST_CHECK(hTest, cchActual == 3);
1077 rc = RTLatin1CalcUtf8LenEx(pszLat1, RTSTR_MAX, &cchActual);
1078 RTTEST_CHECK_RC_OK(hTest, rc);
1079 if (RT_SUCCESS(rc))
1080 RTTEST_CHECK(hTest, cchActual == 7);
1081 char *pch = NULL;
1082 char ch[8];
1083 char *pch2 = &ch[0];
1084 cchActual = 0;
1085 rc = RTLatin1ToUtf8(pszLat1, &pch);
1086 RTTEST_CHECK_RC_OK(hTest, rc);
1087 if (RT_SUCCESS(rc))
1088 RTTEST_CHECK(hTest, !strcmp(pch, "\x01\x20\x40\xC2\x80\xC2\x81"));
1089 RTStrFree(pch);
1090 rc = RTLatin1ToUtf8Ex(pszLat1, RTSTR_MAX, &pch, 0, &cchActual);
1091 RTTEST_CHECK_RC_OK(hTest, rc);
1092 if (RT_SUCCESS(rc))
1093 {
1094 RTTEST_CHECK(hTest, (cchActual == 7));
1095 RTTEST_CHECK(hTest, !strcmp(pch, "\x01\x20\x40\xC2\x80\xC2\x81"));
1096 }
1097 RTStrFree(pch);
1098 rc = RTLatin1ToUtf8Ex(pszLat1, RTSTR_MAX, &pch, 0, NULL);
1099 RTTEST_CHECK_RC_OK(hTest, rc);
1100 if (RT_SUCCESS(rc))
1101 RTTEST_CHECK(hTest, !strcmp(pch, "\x01\x20\x40\xC2\x80\xC2\x81"));
1102 RTStrFree(pch);
1103 rc = RTLatin1ToUtf8Ex(pszLat1, RTSTR_MAX, &pch2, RT_ELEMENTS(ch),
1104 &cchActual);
1105 RTTEST_CHECK_RC_OK(hTest, rc);
1106 if (RT_SUCCESS(rc))
1107 {
1108 RTTEST_CHECK(hTest, (cchActual == 7));
1109 RTTEST_CHECK(hTest, !strcmp(pch2, "\x01\x20\x40\xC2\x80\xC2\x81"));
1110 }
1111 rc = RTLatin1ToUtf8Ex(pszLat1, 3, &pch2, RT_ELEMENTS(ch),
1112 &cchActual);
1113 RTTEST_CHECK_RC_OK(hTest, rc);
1114 if (RT_SUCCESS(rc))
1115 {
1116 RTTEST_CHECK(hTest, (cchActual == 3));
1117 RTTEST_CHECK(hTest, !strcmp(pch2, "\x01\x20\x40"));
1118 }
1119 rc = RTLatin1ToUtf8Ex(pszLat1, RTSTR_MAX, &pch2, RT_ELEMENTS(ch) - 1,
1120 &cchActual);
1121 RTTEST_CHECK_RC(hTest, rc, VERR_BUFFER_OVERFLOW);
1122 RTTEST_CHECK(hTest, (cchActual == 7));
1123 RTTestSubDone(hTest);
1124}
1125
1126
1127void testUtf16Latin1(RTTEST hTest)
1128{
1129 RTTestSub(hTest, "Latin-1 <-> Utf-16 conversion functions");
1130
1131 /* Test Utf16 -> Latin1 */
1132 size_t cch_szAll = 0;
1133 size_t cbShort = RTUtf16CalcLatin1Len(g_wszAll);
1134 RTTEST_CHECK(hTest, cbShort == 0);
1135 int rc = RTUtf16CalcLatin1LenEx(g_wszAll, 255, &cch_szAll);
1136 RTTEST_CHECK(hTest, (cch_szAll == 255));
1137 rc = RTUtf16CalcLatin1LenEx(g_wszAll, RTSTR_MAX, &cch_szAll);
1138 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION);
1139 char *psz = NULL;
1140 RTUTF16 wszShort[256] = { 0 };
1141 for (unsigned i = 0; i < 255; ++i)
1142 wszShort[i] = i + 1;
1143 cbShort = RTUtf16CalcLatin1Len(wszShort);
1144 RTTEST_CHECK(hTest, cbShort == 255);
1145 rc = RTUtf16ToLatin1(wszShort, &psz);
1146 RTTEST_CHECK_RC_OK(hTest, rc);
1147 if (RT_SUCCESS(rc))
1148 {
1149 RTTEST_CHECK(hTest, (strlen(psz) == 255));
1150 for (unsigned i = 0, j = 1; psz[i] != '\0'; ++i, ++j)
1151 if (psz[i] != (char) j)
1152 {
1153 RTTestFailed(hTest, "conversion of g_wszAll to Latin1 failed at position %u\n", i);
1154 break;
1155 }
1156 }
1157 RTStrFree(psz);
1158 rc = RTUtf16ToLatin1(g_wszAll, &psz);
1159 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION);
1160 char sz[512];
1161 char *psz2 = &sz[0];
1162 size_t cchActual = 0;
1163 rc = RTUtf16ToLatin1Ex(g_wszAll, sizeof(sz) - 1, &psz2, sizeof(sz),
1164 &cchActual);
1165 RTTEST_CHECK_RC(hTest, rc, VERR_NO_TRANSLATION);
1166 RTTEST_CHECK_MSG(hTest, cchActual == 0,
1167 (hTest, "cchActual=%lu\n", cchActual));
1168 rc = RTUtf16ToLatin1Ex(g_wszAll, 255, &psz2, sizeof(sz),
1169 &cchActual);
1170 RTTEST_CHECK_RC_OK(hTest, rc);
1171 if (RT_SUCCESS(rc))
1172 {
1173 RTTEST_CHECK(hTest, (cchActual == 255));
1174 RTTEST_CHECK(hTest, (cchActual == strlen(sz)));
1175 for (unsigned i = 0, j = 1; psz2[i] != '\0'; ++i, ++j)
1176 if (psz2[i] != (char) j)
1177 {
1178 RTTestFailed(hTest, "second conversion of g_wszAll to Latin1 failed at position %u\n", i);
1179 break;
1180 }
1181 }
1182 rc = RTUtf16ToLatin1Ex(g_wszAll, 128, &psz2, 128, &cchActual);
1183 RTTEST_CHECK_RC(hTest, rc, VERR_BUFFER_OVERFLOW);
1184 RTTEST_CHECK_MSG(hTest, cchActual == 128,
1185 (hTest, "cchActual=%lu\n", cchActual));
1186 rc = RTUtf16ToLatin1Ex(g_wszAll, 255, &psz, 0, &cchActual);
1187 RTTEST_CHECK_RC_OK(hTest, rc);
1188 if (RT_SUCCESS(rc))
1189 {
1190 RTTEST_CHECK(hTest, (cchActual == 255));
1191 RTTEST_CHECK(hTest, (cchActual == strlen(psz)));
1192 for (unsigned i = 0, j = 1; psz[i] != '\0'; ++i, ++j)
1193 if ( ((j < 0x100) && (psz[i] != (char) j))
1194 || ((j > 0xff) && psz[i] != '?'))
1195 {
1196 RTTestFailed(hTest, "third conversion of g_wszAll to Latin1 failed at position %u\n", i);
1197 break;
1198 }
1199 }
1200 const char *pszBad = "H\0e\0l\0l\0o\0\0\xDC\0\xD8\0";
1201 rc = RTUtf16ToLatin1Ex((RTUTF16 *) pszBad, RTSTR_MAX, &psz2, sizeof(sz),
1202 &cchActual);
1203 RTTEST_CHECK_RC(hTest, rc, VERR_INVALID_UTF16_ENCODING);
1204 RTStrFree(psz);
1205
1206 /* Test Latin1 -> Utf16 */
1207 const char *pszLat1 = "\x01\x20\x40\x80\x81";
1208 RTTEST_CHECK(hTest, RTLatin1CalcUtf16Len(pszLat1) == 5);
1209 rc = RTLatin1CalcUtf16LenEx(pszLat1, 3, &cchActual);
1210 RTTEST_CHECK_RC_OK(hTest, rc);
1211 if (RT_SUCCESS(rc))
1212 RTTEST_CHECK(hTest, cchActual == 3);
1213 rc = RTLatin1CalcUtf16LenEx(pszLat1, RTSTR_MAX, &cchActual);
1214 RTTEST_CHECK_RC_OK(hTest, rc);
1215 if (RT_SUCCESS(rc))
1216 RTTEST_CHECK(hTest, cchActual == 5);
1217 RTUTF16 *pwc = NULL;
1218 RTUTF16 wc[6];
1219 RTUTF16 *pwc2 = &wc[0];
1220 size_t cwActual = 0;
1221 rc = RTLatin1ToUtf16(pszLat1, &pwc);
1222 RTTEST_CHECK_RC_OK(hTest, rc);
1223 if (RT_SUCCESS(rc))
1224 RTTEST_CHECK(hTest, (pwc[0] == 1) && (pwc[1] == 0x20)
1225 && (pwc[2] == 0x40) && (pwc[3] == 0x80)
1226 && (pwc[4] == 0x81) && (pwc[5] == '\0'));
1227 RTUtf16Free(pwc);
1228 rc = RTLatin1ToUtf16Ex(pszLat1, RTSTR_MAX, &pwc, 0, &cwActual);
1229 RTTEST_CHECK_RC_OK(hTest, rc);
1230 if (RT_SUCCESS(rc))
1231 {
1232 RTTEST_CHECK(hTest, (cwActual == 5));
1233 RTTEST_CHECK(hTest, (pwc[0] == 1) && (pwc[1] == 0x20)
1234 && (pwc[2] == 0x40) && (pwc[3] == 0x80)
1235 && (pwc[4] == 0x81) && (pwc[5] == '\0'));
1236 }
1237 RTUtf16Free(pwc);
1238 rc = RTLatin1ToUtf16Ex(pszLat1, RTSTR_MAX, &pwc, 0, NULL);
1239 RTTEST_CHECK_RC_OK(hTest, rc);
1240 if (RT_SUCCESS(rc))
1241 RTTEST_CHECK(hTest, (pwc[0] == 1) && (pwc[1] == 0x20)
1242 && (pwc[2] == 0x40) && (pwc[3] == 0x80)
1243 && (pwc[4] == 0x81) && (pwc[5] == '\0'));
1244 RTUtf16Free(pwc);
1245 rc = RTLatin1ToUtf16Ex(pszLat1, RTSTR_MAX, &pwc2, RT_ELEMENTS(wc),
1246 &cwActual);
1247 RTTEST_CHECK_RC_OK(hTest, rc);
1248 if (RT_SUCCESS(rc))
1249 {
1250 RTTEST_CHECK(hTest, (cwActual == 5));
1251 RTTEST_CHECK(hTest, (wc[0] == 1) && (wc[1] == 0x20)
1252 && (wc[2] == 0x40) && (wc[3] == 0x80)
1253 && (wc[4] == 0x81) && (wc[5] == '\0'));
1254 }
1255 rc = RTLatin1ToUtf16Ex(pszLat1, 3, &pwc2, RT_ELEMENTS(wc),
1256 &cwActual);
1257 RTTEST_CHECK_RC_OK(hTest, rc);
1258 if (RT_SUCCESS(rc))
1259 {
1260 RTTEST_CHECK(hTest, (cwActual == 3));
1261 RTTEST_CHECK(hTest, (wc[0] == 1) && (wc[1] == 0x20)
1262 && (wc[2] == 0x40) && (wc[3] == '\0'));
1263 }
1264 rc = RTLatin1ToUtf16Ex(pszLat1, RTSTR_MAX, &pwc2, RT_ELEMENTS(wc) - 1,
1265 &cwActual);
1266 RTTEST_CHECK_RC(hTest, rc, VERR_BUFFER_OVERFLOW);
1267 RTTEST_CHECK(hTest, (cwActual == 5));
1268 RTTestSubDone(hTest);
1269}
1270
1271
1272static void testNoTransation(RTTEST hTest)
1273{
1274 /*
1275 * Try trigger a VERR_NO_TRANSLATION error in convert to
1276 * current CP to latin-1.
1277 */
1278 const RTUTF16 s_swzTest1[] = { 0x2358, 0x2242, 0x2357, 0x2359, 0x22f9, 0x2c4e, 0x0030, 0x0060,
1279 0x0092, 0x00c1, 0x00f2, 0x1f80, 0x0088, 0x2c38, 0x2c30, 0x0000 };
1280 char *pszTest1;
1281 int rc = RTUtf16ToUtf8(s_swzTest1, &pszTest1);
1282 RTTESTI_CHECK_RC_RETV(rc, VINF_SUCCESS);
1283
1284 RTTestSub(hTest, "VERR_NO_TRANSLATION/RTStrUtf8ToCurrentCP");
1285 char *pszOut;
1286 rc = RTStrUtf8ToCurrentCP(&pszOut, pszTest1);
1287 if (RT_SUCCESS(rc))
1288 {
1289 RTTESTI_CHECK(!strcmp(pszOut, pszTest1));
1290 RTTestIPrintf(RTTESTLVL_ALWAYS, "CurrentCP is UTF-8 or similar\n");
1291 RTStrFree(pszOut);
1292 }
1293 else
1294 RTTESTI_CHECK_RC(rc, VERR_NO_TRANSLATION);
1295
1296 RTTestSub(hTest, "VERR_NO_TRANSLATION/RTUtf16ToLatin1");
1297 rc = RTUtf16ToLatin1(s_swzTest1, &pszOut);
1298 RTTESTI_CHECK_RC(rc, VERR_NO_TRANSLATION);
1299 if (RT_SUCCESS(rc))
1300 RTStrFree(pszOut);
1301
1302 RTStrFree(pszTest1);
1303 RTTestSubDone(hTest);
1304}
1305
1306static void testGetPut(RTTEST hTest)
1307{
1308 /*
1309 * Test RTStrPutCp, RTStrGetCp and RTStrGetCpEx.
1310 */
1311 RTTestSub(hTest, "RTStrPutCp, RTStrGetCp and RTStrGetCpEx");
1312
1313 RTUNICP uc = 0;
1314 while (uc <= 0x10fffd)
1315 {
1316 /* Figure the range - skip illegal ranges. */
1317 RTUNICP ucFirst = uc;
1318 if (ucFirst - UINT32_C(0xd800) <= 0x7ff)
1319 ucFirst = 0xe000;
1320 else if (ucFirst == UINT32_C(0xfffe) || ucFirst == UINT32_C(0xffff))
1321 ucFirst = 0x10000;
1322
1323 RTUNICP ucLast = ucFirst + 1023;
1324 if (ucLast - UINT32_C(0xd800) <= 0x7ff)
1325 ucLast = 0xd7ff;
1326 else if (ucLast == UINT32_C(0xfffe) || ucLast == UINT32_C(0xffff))
1327 ucLast = 0xfffd;
1328
1329 /* Encode the range into a string, decode each code point as we go along. */
1330 char sz1[8192];
1331 char *pszDst = sz1;
1332 for (uc = ucFirst; uc <= ucLast; uc++)
1333 {
1334 char *pszBefore = pszDst;
1335 pszDst = RTStrPutCp(pszDst, uc);
1336 RTTESTI_CHECK(pszBefore - pszDst < 6);
1337
1338 RTUNICP uc2 = RTStrGetCp(pszBefore);
1339 RTTESTI_CHECK_MSG(uc2 == uc, ("uc2=%#x uc=%#x\n", uc2, uc));
1340
1341 const char *pszSrc = pszBefore;
1342 RTUNICP uc3 = 42;
1343 RTTESTI_CHECK_RC(RTStrGetCpEx(&pszSrc, &uc3), VINF_SUCCESS);
1344 RTTESTI_CHECK_MSG(uc3 == uc, ("uc3=%#x uc=%#x\n", uc3, uc));
1345 RTTESTI_CHECK_MSG(pszSrc == pszDst, ("pszSrc=%p pszDst=%p\n", pszSrc, pszDst));
1346 }
1347
1348 /* Decode and re-encode it. */
1349 const char *pszSrc = pszDst = sz1;
1350 for (uc = ucFirst; uc <= ucLast; uc++)
1351 {
1352 RTUNICP uc2 = RTStrGetCp(pszSrc);
1353 RTTESTI_CHECK_MSG(uc2 == uc, ("uc2=%#x uc=%#x\n", uc2, uc));
1354
1355 RTUNICP uc3 = 42;
1356 RTTESTI_CHECK_RC(RTStrGetCpEx(&pszSrc, &uc3), VINF_SUCCESS);
1357 RTTESTI_CHECK_MSG(uc3 == uc, ("uc3=%#x uc=%#x\n", uc3, uc));
1358
1359 pszDst = RTStrPutCp(pszDst, uc);
1360 RTTESTI_CHECK_MSG(pszSrc == pszDst, ("pszSrc=%p pszDst=%p\n", pszSrc, pszDst));
1361 pszSrc = pszDst;
1362 }
1363
1364 /* Decode and wipe it (checking compiler optimizations). */
1365 pszSrc = pszDst = sz1;
1366 for (uc = ucFirst; uc <= ucLast; uc++)
1367 {
1368 RTUNICP uc2 = RTStrGetCp(pszSrc);
1369 RTTESTI_CHECK_MSG(uc2 == uc, ("uc2=%#x uc=%#x\n", uc2, uc));
1370
1371 RTUNICP uc3 = 42;
1372 RTTESTI_CHECK_RC(RTStrGetCpEx(&pszSrc, &uc3), VINF_SUCCESS);
1373 RTTESTI_CHECK_MSG(uc3 == uc, ("uc3=%#x uc=%#x\n", uc3, uc));
1374
1375 pszDst = RTStrPutCp(pszDst, 0);
1376 }
1377
1378 /* advance */
1379 uc = ucLast + 1;
1380 }
1381
1382}
1383
1384
1385int main()
1386{
1387 /*
1388 * Init the runtime, test and say hello.
1389 */
1390 RTTEST hTest;
1391 RTEXITCODE rcExit = RTTestInitAndCreate("tstUtf8", &hTest);
1392 if (rcExit != RTEXITCODE_SUCCESS)
1393 return rcExit;
1394 RTTestBanner(hTest);
1395
1396 /*
1397 * Run the tests.
1398 */
1399 InitStrings();
1400 test1(hTest);
1401 test2(hTest);
1402 test3(hTest);
1403 TstRTStrXCmp(hTest);
1404 TstRTStrPurgeEncoding(hTest);
1405 testStrEnd(hTest);
1406 testStrStr(hTest);
1407 testUtf8Latin1(hTest);
1408 testUtf16Latin1(hTest);
1409 testNoTransation(hTest);
1410 testGetPut(hTest);
1411
1412 Benchmarks(hTest);
1413
1414 /*
1415 * Summary
1416 */
1417 return RTTestSummaryAndDestroy(hTest);
1418}
1419
Note: See TracBrowser for help on using the repository browser.

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