1#include <gtest/gtest.h>
2
3#include <base/system.h>
4
5#include <game/gamecore.h>
6
7TEST(Str, StrIsNum)
8{
9 EXPECT_EQ(str_isnum('/'), false);
10 EXPECT_EQ(str_isnum('0'), true);
11 EXPECT_EQ(str_isnum('1'), true);
12 EXPECT_EQ(str_isnum('2'), true);
13 EXPECT_EQ(str_isnum('8'), true);
14 EXPECT_EQ(str_isnum('9'), true);
15 EXPECT_EQ(str_isnum(':'), false);
16 EXPECT_EQ(str_isnum(' '), false);
17}
18
19TEST(Str, StrIsAllNum)
20{
21 EXPECT_EQ(str_isallnum("/"), 0);
22 EXPECT_EQ(str_isallnum("0"), 1);
23 EXPECT_EQ(str_isallnum("1"), 1);
24 EXPECT_EQ(str_isallnum("2"), 1);
25 EXPECT_EQ(str_isallnum("8"), 1);
26 EXPECT_EQ(str_isallnum("9"), 1);
27 EXPECT_EQ(str_isallnum(":"), 0);
28 EXPECT_EQ(str_isallnum(" "), 0);
29
30 EXPECT_EQ(str_isallnum("123"), 1);
31 EXPECT_EQ(str_isallnum("123/"), 0);
32 EXPECT_EQ(str_isallnum("123:"), 0);
33}
34
35TEST(Str, Dist)
36{
37 EXPECT_EQ(str_utf8_dist("aaa", "aaa"), 0);
38 EXPECT_EQ(str_utf8_dist("123", "123"), 0);
39 EXPECT_EQ(str_utf8_dist("", ""), 0);
40 EXPECT_EQ(str_utf8_dist("a", "b"), 1);
41 EXPECT_EQ(str_utf8_dist("", "aaa"), 3);
42 EXPECT_EQ(str_utf8_dist("123", ""), 3);
43 EXPECT_EQ(str_utf8_dist("ä", ""), 1);
44 EXPECT_EQ(str_utf8_dist("Hëllö", "Hello"), 2);
45 // https://en.wikipedia.org/w/index.php?title=Levenshtein_distance&oldid=828480025#Example
46 EXPECT_EQ(str_utf8_dist("kitten", "sitting"), 3);
47 EXPECT_EQ(str_utf8_dist("flaw", "lawn"), 2);
48 EXPECT_EQ(str_utf8_dist("saturday", "sunday"), 3);
49}
50
51TEST(Str, Utf8Isspace)
52{
53 EXPECT_TRUE(str_utf8_isspace(0x200b)); // Zero-width space
54 EXPECT_TRUE(str_utf8_isspace(' '));
55 EXPECT_FALSE(str_utf8_isspace('a'));
56 // Control characters.
57 for(char c = 0; c < 0x20; c++)
58 {
59 EXPECT_TRUE(str_utf8_isspace(c));
60 }
61}
62
63TEST(Str, Utf8SkipWhitespaces)
64{
65 EXPECT_STREQ(str_utf8_skip_whitespaces("abc"), "abc");
66 EXPECT_STREQ(str_utf8_skip_whitespaces("abc "), "abc ");
67 EXPECT_STREQ(str_utf8_skip_whitespaces(" abc"), "abc");
68 EXPECT_STREQ(str_utf8_skip_whitespaces("\xe2\x80\x8b abc"), "abc");
69}
70
71TEST(Str, Utf8TrimRight)
72{
73 char A1[] = "abc";
74 str_utf8_trim_right(param: A1);
75 EXPECT_STREQ(A1, "abc");
76 char A2[] = " abc";
77 str_utf8_trim_right(param: A2);
78 EXPECT_STREQ(A2, " abc");
79 char A3[] = "abc ";
80 str_utf8_trim_right(param: A3);
81 EXPECT_STREQ(A3, "abc");
82 char A4[] = "abc \xe2\x80\x8b";
83 str_utf8_trim_right(param: A4);
84 EXPECT_STREQ(A4, "abc");
85}
86
87TEST(Str, Utf8CompConfusables)
88{
89 EXPECT_TRUE(str_utf8_comp_confusable("abc", "abc") == 0);
90 EXPECT_TRUE(str_utf8_comp_confusable("rn", "m") == 0);
91 EXPECT_TRUE(str_utf8_comp_confusable("m", "rn") == 0);
92 EXPECT_TRUE(str_utf8_comp_confusable("rna", "ma") == 0);
93 EXPECT_TRUE(str_utf8_comp_confusable("ma", "rna") == 0);
94 EXPECT_FALSE(str_utf8_comp_confusable("mA", "rna") == 0);
95 EXPECT_FALSE(str_utf8_comp_confusable("ma", "rnA") == 0);
96 EXPECT_TRUE(str_utf8_comp_confusable("arn", "am") == 0);
97 EXPECT_TRUE(str_utf8_comp_confusable("am", "arn") == 0);
98 EXPECT_FALSE(str_utf8_comp_confusable("Am", "arn") == 0);
99 EXPECT_FALSE(str_utf8_comp_confusable("am", "Arn") == 0);
100 EXPECT_TRUE(str_utf8_comp_confusable("l", "ӏ") == 0); // CYRILLIC SMALL LETTER PALOCHKA
101 EXPECT_TRUE(str_utf8_comp_confusable("i", "¡") == 0); // INVERTED EXCLAMATION MARK
102 EXPECT_FALSE(str_utf8_comp_confusable("o", "x") == 0);
103 EXPECT_TRUE(str_utf8_comp_confusable("aceiou", "ąçęįǫų") == 0);
104}
105
106TEST(Str, Utf8ToSkeleton)
107{
108 int aBuf[32];
109 EXPECT_EQ(str_utf8_to_skeleton("abc", aBuf, 0), 0);
110 EXPECT_EQ(str_utf8_to_skeleton("", aBuf, std::size(aBuf)), 0);
111 EXPECT_EQ(str_utf8_to_skeleton("abc", aBuf, std::size(aBuf)), 3);
112 EXPECT_EQ(aBuf[0], 'a');
113 EXPECT_EQ(aBuf[1], 'b');
114 EXPECT_EQ(aBuf[2], 'c');
115 EXPECT_EQ(str_utf8_to_skeleton("m", aBuf, std::size(aBuf)), 2);
116 EXPECT_EQ(aBuf[0], 'r');
117 EXPECT_EQ(aBuf[1], 'n');
118 EXPECT_EQ(str_utf8_to_skeleton("rn", aBuf, std::size(aBuf)), 2);
119 EXPECT_EQ(aBuf[0], 'r');
120 EXPECT_EQ(aBuf[1], 'n');
121 EXPECT_EQ(str_utf8_to_skeleton("ӏ", aBuf, std::size(aBuf)), 1); // CYRILLIC SMALL LETTER PALOCHKA
122 EXPECT_EQ(aBuf[0], 'i');
123 EXPECT_EQ(str_utf8_to_skeleton("¡", aBuf, std::size(aBuf)), 1); // INVERTED EXCLAMATION MARK
124 EXPECT_EQ(aBuf[0], 'i');
125 EXPECT_EQ(str_utf8_to_skeleton("ąçęįǫų", aBuf, std::size(aBuf)), 6);
126 EXPECT_EQ(aBuf[0], 'a');
127 EXPECT_EQ(aBuf[1], 'c');
128 EXPECT_EQ(aBuf[2], 'e');
129 EXPECT_EQ(aBuf[3], 'i');
130 EXPECT_EQ(aBuf[4], 'o');
131 EXPECT_EQ(aBuf[5], 'u');
132}
133
134TEST(Str, Utf8ToLower)
135{
136 EXPECT_TRUE(str_utf8_tolower('A') == 'a');
137 EXPECT_TRUE(str_utf8_tolower('z') == 'z');
138 EXPECT_TRUE(str_utf8_tolower(192) == 224); // À -> à
139 EXPECT_TRUE(str_utf8_tolower(7882) == 7883); // Ị -> ị
140
141 EXPECT_TRUE(str_utf8_comp_nocase("ÖlÜ", "ölü") == 0);
142 EXPECT_TRUE(str_utf8_comp_nocase("ÜlÖ", "ölü") > 0); // ü > ö
143 EXPECT_TRUE(str_utf8_comp_nocase("ÖlÜ", "ölüa") < 0); // NULL < a
144 EXPECT_TRUE(str_utf8_comp_nocase("ölüa", "ÖlÜ") > 0); // a < NULL
145
146#if(CHAR_MIN < 0)
147 const char a[2] = {CHAR_MIN, 0};
148 const char b[2] = {0, 0};
149 EXPECT_TRUE(str_utf8_comp_nocase(a, b) > 0);
150 EXPECT_TRUE(str_utf8_comp_nocase(b, a) < 0);
151#endif
152
153 EXPECT_TRUE(str_utf8_comp_nocase_num("ÖlÜ", "ölüa", 5) == 0);
154 EXPECT_TRUE(str_utf8_comp_nocase_num("ÖlÜ", "ölüa", 6) != 0);
155 EXPECT_TRUE(str_utf8_comp_nocase_num("a", "z", 0) == 0);
156 EXPECT_TRUE(str_utf8_comp_nocase_num("a", "z", 1) != 0);
157}
158
159TEST(Str, Utf8FindNocase)
160{
161 const char *pStr = "abc";
162 const char *pEnd;
163 EXPECT_EQ(str_utf8_find_nocase(pStr, "a", &pEnd), pStr);
164 EXPECT_EQ(pEnd, pStr + str_length("a"));
165 EXPECT_EQ(str_utf8_find_nocase(pStr, "b", &pEnd), pStr + str_length("a"));
166 EXPECT_EQ(pEnd, pStr + str_length("ab"));
167 EXPECT_EQ(str_utf8_find_nocase(pStr, "c", &pEnd), pStr + str_length("ab"));
168 EXPECT_EQ(pEnd, pStr + str_length("abc"));
169 EXPECT_EQ(str_utf8_find_nocase(pStr, "d", &pEnd), nullptr);
170 EXPECT_EQ(pEnd, nullptr);
171
172 EXPECT_EQ(str_utf8_find_nocase(pStr, "A", &pEnd), pStr);
173 EXPECT_EQ(pEnd, pStr + str_length("a"));
174 EXPECT_EQ(str_utf8_find_nocase(pStr, "B", &pEnd), pStr + str_length("a"));
175 EXPECT_EQ(pEnd, pStr + str_length("ab"));
176 EXPECT_EQ(str_utf8_find_nocase(pStr, "C", &pEnd), pStr + str_length("ab"));
177 EXPECT_EQ(pEnd, pStr + str_length("abc"));
178 EXPECT_EQ(str_utf8_find_nocase(pStr, "D", &pEnd), nullptr);
179 EXPECT_EQ(pEnd, nullptr);
180
181 pStr = "ÄÖÜ";
182 EXPECT_EQ(str_utf8_find_nocase(pStr, "ä", &pEnd), pStr);
183 EXPECT_EQ(pEnd, pStr + str_length("Ä"));
184 EXPECT_EQ(str_utf8_find_nocase(pStr, "ö", &pEnd), pStr + str_length("Ä"));
185 EXPECT_EQ(pEnd, pStr + str_length("ÄÖ"));
186 EXPECT_EQ(str_utf8_find_nocase(pStr, "ü", &pEnd), pStr + str_length("ÄÖ"));
187 EXPECT_EQ(pEnd, pStr + str_length("ÄÖÜ"));
188 EXPECT_EQ(str_utf8_find_nocase(pStr, "z", &pEnd), nullptr);
189 EXPECT_EQ(pEnd, nullptr);
190
191 // Both 'I' and 'İ' map to 'i'
192 pStr = "antimatter";
193 EXPECT_EQ(str_utf8_find_nocase(pStr, "I", &pEnd), pStr + str_length("ant"));
194 EXPECT_EQ(pEnd, pStr + str_length("anti"));
195 EXPECT_EQ(str_utf8_find_nocase(pStr, "İ", &pEnd), pStr + str_length("ant"));
196 EXPECT_EQ(pEnd, pStr + str_length("anti"));
197 pStr = "ANTIMATTER";
198 EXPECT_EQ(str_utf8_find_nocase(pStr, "i", &pEnd), pStr + str_length("ANT"));
199 EXPECT_EQ(pEnd, pStr + str_length("ANTI"));
200 pStr = "ANTİMATTER";
201 EXPECT_EQ(str_utf8_find_nocase(pStr, "i", &pEnd), pStr + str_length("ANT"));
202 EXPECT_EQ(pEnd, pStr + str_length("ANTİ"));
203}
204
205TEST(Str, Utf8FixTruncation)
206{
207 char aaBuf[][32] = {
208 "",
209 "\xff",
210 "abc",
211 "abc\xff",
212 "blub\xffxyz",
213 "привет Наташа\xff",
214 "до свидания\xffОлег",
215 };
216 const char *apExpected[] = {
217 "",
218 "",
219 "abc",
220 "abc",
221 "blub\xffxyz",
222 "привет Наташа",
223 "до свидания\xffОлег",
224 };
225 for(unsigned i = 0; i < std::size(aaBuf); i++)
226 {
227 EXPECT_EQ(str_utf8_fix_truncation(aaBuf[i]), str_length(apExpected[i]));
228 EXPECT_STREQ(aaBuf[i], apExpected[i]);
229 }
230}
231
232TEST(Str, Startswith)
233{
234 EXPECT_TRUE(str_startswith("abcdef", "abc"));
235 EXPECT_FALSE(str_startswith("abc", "abcdef"));
236
237 EXPECT_TRUE(str_startswith("xyz", ""));
238 EXPECT_FALSE(str_startswith("", "xyz"));
239
240 EXPECT_FALSE(str_startswith("house", "home"));
241 EXPECT_FALSE(str_startswith("blackboard", "board"));
242
243 EXPECT_TRUE(str_startswith("поплавать", "по"));
244 EXPECT_FALSE(str_startswith("плавать", "по"));
245
246 static const char ABCDEFG[] = "abcdefg";
247 static const char ABC[] = "abc";
248 EXPECT_EQ(str_startswith(ABCDEFG, ABC) - ABCDEFG, str_length(ABC));
249}
250
251TEST(Str, StartswithNocase)
252{
253 EXPECT_TRUE(str_startswith_nocase("Abcdef", "abc"));
254 EXPECT_FALSE(str_startswith_nocase("aBc", "abcdef"));
255
256 EXPECT_TRUE(str_startswith_nocase("xYz", ""));
257 EXPECT_FALSE(str_startswith_nocase("", "xYz"));
258
259 EXPECT_FALSE(str_startswith_nocase("house", "home"));
260 EXPECT_FALSE(str_startswith_nocase("Blackboard", "board"));
261
262 EXPECT_TRUE(str_startswith_nocase("поплавать", "по"));
263 EXPECT_FALSE(str_startswith_nocase("плавать", "по"));
264
265 static const char ABCDEFG[] = "aBcdefg";
266 static const char ABC[] = "abc";
267 EXPECT_EQ(str_startswith_nocase(ABCDEFG, ABC) - ABCDEFG, str_length(ABC));
268}
269
270TEST(Str, Endswith)
271{
272 EXPECT_TRUE(str_endswith("abcdef", "def"));
273 EXPECT_FALSE(str_endswith("def", "abcdef"));
274
275 EXPECT_TRUE(str_endswith("xyz", ""));
276 EXPECT_FALSE(str_endswith("", "xyz"));
277
278 EXPECT_FALSE(str_endswith("rhyme", "mine"));
279 EXPECT_FALSE(str_endswith("blackboard", "black"));
280
281 EXPECT_TRUE(str_endswith("люди", "юди"));
282 EXPECT_FALSE(str_endswith("люди", "любовь"));
283
284 static const char ABCDEFG[] = "abcdefg";
285 static const char DEFG[] = "defg";
286 EXPECT_EQ(str_endswith(ABCDEFG, DEFG) - ABCDEFG,
287 str_length(ABCDEFG) - str_length(DEFG));
288}
289
290TEST(StrFormat, Positional)
291{
292 char aBuf[256];
293
294 // normal
295 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%s %s", "first", "second");
296 EXPECT_STREQ(aBuf, "first second");
297
298 // normal with positional arguments
299 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%1$s %2$s", "first", "second");
300 EXPECT_STREQ(aBuf, "first second");
301
302 // reverse
303 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%2$s %1$s", "first", "second");
304 EXPECT_STREQ(aBuf, "second first");
305
306 // duplicate
307 str_format(buffer: aBuf, buffer_size: sizeof(aBuf), format: "%1$s %1$s %2$d %1$s %2$d", "str", 1);
308 EXPECT_STREQ(aBuf, "str str 1 str 1");
309}
310
311TEST(Str, EndswithNocase)
312{
313 EXPECT_TRUE(str_endswith_nocase("abcdef", "deF"));
314 EXPECT_FALSE(str_endswith_nocase("def", "abcdef"));
315
316 EXPECT_TRUE(str_endswith_nocase("xyz", ""));
317 EXPECT_FALSE(str_endswith_nocase("", "xyz"));
318
319 EXPECT_FALSE(str_endswith_nocase("rhyme", "minE"));
320 EXPECT_FALSE(str_endswith_nocase("blackboard", "black"));
321
322 EXPECT_TRUE(str_endswith_nocase("люди", "юди"));
323 EXPECT_FALSE(str_endswith_nocase("люди", "любовь"));
324
325 static const char ABCDEFG[] = "abcdefG";
326 static const char DEFG[] = "defg";
327 EXPECT_EQ(str_endswith_nocase(ABCDEFG, DEFG) - ABCDEFG,
328 str_length(ABCDEFG) - str_length(DEFG));
329}
330
331TEST(Str, HexEncode)
332{
333 char aOut[64];
334 const char *pData = "ABCD";
335 str_hex(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 0);
336 EXPECT_STREQ(aOut, "");
337 str_hex(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 1);
338 EXPECT_STREQ(aOut, "41 ");
339 str_hex(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 2);
340 EXPECT_STREQ(aOut, "41 42 ");
341 str_hex(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 3);
342 EXPECT_STREQ(aOut, "41 42 43 ");
343 str_hex(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 4);
344 EXPECT_STREQ(aOut, "41 42 43 44 ");
345
346 str_hex(dst: aOut, dst_size: 1, data: pData, data_size: 4);
347 EXPECT_STREQ(aOut, "");
348 str_hex(dst: aOut, dst_size: 2, data: pData, data_size: 4);
349 EXPECT_STREQ(aOut, "");
350 str_hex(dst: aOut, dst_size: 3, data: pData, data_size: 4);
351 EXPECT_STREQ(aOut, "");
352 str_hex(dst: aOut, dst_size: 4, data: pData, data_size: 4);
353 EXPECT_STREQ(aOut, "41 ");
354 str_hex(dst: aOut, dst_size: 5, data: pData, data_size: 4);
355 EXPECT_STREQ(aOut, "41 ");
356 str_hex(dst: aOut, dst_size: 6, data: pData, data_size: 4);
357 EXPECT_STREQ(aOut, "41 ");
358 str_hex(dst: aOut, dst_size: 7, data: pData, data_size: 4);
359 EXPECT_STREQ(aOut, "41 42 ");
360 str_hex(dst: aOut, dst_size: 8, data: pData, data_size: 4);
361 EXPECT_STREQ(aOut, "41 42 ");
362}
363
364TEST(Str, HexEncodeCstyle)
365{
366 char aOut[128];
367 const char *pData = "ABCD";
368 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 0);
369 EXPECT_STREQ(aOut, "");
370 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 1);
371 EXPECT_STREQ(aOut, "0x41");
372 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 2);
373 EXPECT_STREQ(aOut, "0x41, 0x42");
374 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 3);
375 EXPECT_STREQ(aOut, "0x41, 0x42, 0x43");
376 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 4);
377 EXPECT_STREQ(aOut, "0x41, 0x42, 0x43, 0x44");
378
379 str_hex_cstyle(dst: aOut, dst_size: 1, data: pData, data_size: 4);
380 EXPECT_STREQ(aOut, "");
381 str_hex_cstyle(dst: aOut, dst_size: 2, data: pData, data_size: 4);
382 EXPECT_STREQ(aOut, "");
383 str_hex_cstyle(dst: aOut, dst_size: 3, data: pData, data_size: 4);
384 EXPECT_STREQ(aOut, "");
385 str_hex_cstyle(dst: aOut, dst_size: 4, data: pData, data_size: 4);
386 EXPECT_STREQ(aOut, "");
387 str_hex_cstyle(dst: aOut, dst_size: 5, data: pData, data_size: 4);
388 EXPECT_STREQ(aOut, "");
389 str_hex_cstyle(dst: aOut, dst_size: 6, data: pData, data_size: 4);
390 EXPECT_STREQ(aOut, "");
391 str_hex_cstyle(dst: aOut, dst_size: 7, data: pData, data_size: 4);
392 EXPECT_STREQ(aOut, "0x41");
393 str_hex_cstyle(dst: aOut, dst_size: 12, data: pData, data_size: 4);
394 EXPECT_STREQ(aOut, "0x41");
395 str_hex_cstyle(dst: aOut, dst_size: 13, data: pData, data_size: 4);
396 EXPECT_STREQ(aOut, "0x41, 0x42");
397 str_hex_cstyle(dst: aOut, dst_size: 14, data: pData, data_size: 4);
398 EXPECT_STREQ(aOut, "0x41, 0x42");
399
400 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 4, bytes_per_line: 1);
401 EXPECT_STREQ(aOut, "0x41,\n0x42,\n0x43,\n0x44");
402 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 4, bytes_per_line: 2);
403 EXPECT_STREQ(aOut, "0x41, 0x42,\n0x43, 0x44");
404 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 4, bytes_per_line: 3);
405 EXPECT_STREQ(aOut, "0x41, 0x42, 0x43,\n0x44");
406 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 4, bytes_per_line: 4);
407 EXPECT_STREQ(aOut, "0x41, 0x42, 0x43, 0x44");
408 str_hex_cstyle(dst: aOut, dst_size: sizeof(aOut), data: pData, data_size: 4, bytes_per_line: 500);
409 EXPECT_STREQ(aOut, "0x41, 0x42, 0x43, 0x44");
410}
411
412TEST(Str, HexDecode)
413{
414 char aOut[5] = {'a', 'b', 'c', 'd', 0};
415 EXPECT_EQ(str_hex_decode(aOut, 0, ""), 0);
416 EXPECT_STREQ(aOut, "abcd");
417 EXPECT_EQ(str_hex_decode(aOut, 0, " "), 2);
418 EXPECT_STREQ(aOut, "abcd");
419 EXPECT_EQ(str_hex_decode(aOut, 1, "1"), 2);
420 EXPECT_STREQ(aOut + 1, "bcd");
421 EXPECT_EQ(str_hex_decode(aOut, 1, "41"), 0);
422 EXPECT_STREQ(aOut, "Abcd");
423 EXPECT_EQ(str_hex_decode(aOut, 1, "4x"), 1);
424 EXPECT_STREQ(aOut + 1, "bcd");
425 EXPECT_EQ(str_hex_decode(aOut, 1, "x1"), 1);
426 EXPECT_STREQ(aOut + 1, "bcd");
427 EXPECT_EQ(str_hex_decode(aOut, 1, "411"), 2);
428 EXPECT_STREQ(aOut + 1, "bcd");
429 EXPECT_EQ(str_hex_decode(aOut, 4, "41424344"), 0);
430 EXPECT_STREQ(aOut, "ABCD");
431}
432
433void StrBase64Str(char *pBuffer, int BufferSize, const char *pString)
434{
435 str_base64(dst: pBuffer, dst_size: BufferSize, data: pString, data_size: str_length(str: pString));
436}
437
438TEST(Str, Base64)
439{
440 char aBuf[128];
441 str_base64(dst: aBuf, dst_size: sizeof(aBuf), data: "\0", data_size: 1);
442 EXPECT_STREQ(aBuf, "AA==");
443 str_base64(dst: aBuf, dst_size: sizeof(aBuf), data: "\0\0", data_size: 2);
444 EXPECT_STREQ(aBuf, "AAA=");
445 str_base64(dst: aBuf, dst_size: sizeof(aBuf), data: "\0\0\0", data_size: 3);
446 EXPECT_STREQ(aBuf, "AAAA");
447
448 StrBase64Str(pBuffer: aBuf, BufferSize: sizeof(aBuf), pString: "");
449 EXPECT_STREQ(aBuf, "");
450
451 // https://en.wikipedia.org/w/index.php?title=Base64&oldid=1033503483#Output_padding
452 StrBase64Str(pBuffer: aBuf, BufferSize: sizeof(aBuf), pString: "pleasure.");
453 EXPECT_STREQ(aBuf, "cGxlYXN1cmUu");
454 StrBase64Str(pBuffer: aBuf, BufferSize: sizeof(aBuf), pString: "leasure.");
455 EXPECT_STREQ(aBuf, "bGVhc3VyZS4=");
456 StrBase64Str(pBuffer: aBuf, BufferSize: sizeof(aBuf), pString: "easure.");
457 EXPECT_STREQ(aBuf, "ZWFzdXJlLg==");
458 StrBase64Str(pBuffer: aBuf, BufferSize: sizeof(aBuf), pString: "asure.");
459 EXPECT_STREQ(aBuf, "YXN1cmUu");
460 StrBase64Str(pBuffer: aBuf, BufferSize: sizeof(aBuf), pString: "sure.");
461 EXPECT_STREQ(aBuf, "c3VyZS4=");
462}
463
464TEST(Str, Base64Decode)
465{
466 char aOut[17];
467 str_copy(dst: aOut, src: "XXXXXXXXXXXXXXXX", dst_size: sizeof(aOut));
468 EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), ""), 0);
469 EXPECT_STREQ(aOut, "XXXXXXXXXXXXXXXX");
470
471 // https://en.wikipedia.org/w/index.php?title=Base64&oldid=1033503483#Output_padding
472 str_copy(dst: aOut, src: "XXXXXXXXXXXXXXXX", dst_size: sizeof(aOut));
473 EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "cGxlYXN1cmUu"), 9);
474 EXPECT_STREQ(aOut, "pleasure.XXXXXXX");
475 str_copy(dst: aOut, src: "XXXXXXXXXXXXXXXX", dst_size: sizeof(aOut));
476 EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "bGVhc3VyZS4="), 8);
477 EXPECT_STREQ(aOut, "leasure.XXXXXXXX");
478 str_copy(dst: aOut, src: "XXXXXXXXXXXXXXXX", dst_size: sizeof(aOut));
479 EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "ZWFzdXJlLg=="), 7);
480 EXPECT_STREQ(aOut, "easure.XXXXXXXXX");
481 str_copy(dst: aOut, src: "XXXXXXXXXXXXXXXX", dst_size: sizeof(aOut));
482 EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "YXN1cmUu"), 6);
483 EXPECT_STREQ(aOut, "asure.XXXXXXXXXX");
484 str_copy(dst: aOut, src: "XXXXXXXXXXXXXXXX", dst_size: sizeof(aOut));
485 EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "c3VyZS4="), 5);
486 EXPECT_STREQ(aOut, "sure.XXXXXXXXXXX");
487 str_copy(dst: aOut, src: "XXXXXXXXXXXXXXXX", dst_size: sizeof(aOut));
488 EXPECT_EQ(str_base64_decode(aOut, sizeof(aOut), "////"), 3);
489 EXPECT_STREQ(aOut, "\xff\xff\xffXXXXXXXXXXXXX");
490}
491
492TEST(Str, Base64DecodeError)
493{
494 char aBuf[128];
495 // Wrong padding.
496 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "A"), 0);
497 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AA"), 0);
498 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AAA"), 0);
499 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "A==="), 0);
500 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "=AAA"), 0);
501 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "===="), 0);
502 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AAA=AAAA"), 0);
503 // Invalid characters.
504 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "----"), 0);
505 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AAAA "), 0);
506 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "AAA "), 0);
507 // Invalid padding values.
508 EXPECT_LT(str_base64_decode(aBuf, sizeof(aBuf), "//=="), 0);
509}
510
511TEST(Str, Tokenize)
512{
513 char aTest[] = "GER,RUS,ZAF,BRA,CAN";
514 const char *apOut[] = {"GER", "RUS", "ZAF", "BRA", "CAN"};
515 char aBuf[4];
516
517 int n = 0;
518 for(const char *pTok = aTest; (pTok = str_next_token(str: pTok, delim: ",", buffer: aBuf, buffer_size: sizeof(aBuf)));)
519 EXPECT_STREQ(apOut[n++], aBuf);
520
521 char aTest2[] = "";
522 EXPECT_EQ(str_next_token(aTest2, ",", aBuf, sizeof(aBuf)), nullptr);
523
524 char aTest3[] = "+b";
525 str_next_token(str: aTest3, delim: "+", buffer: aBuf, buffer_size: sizeof(aBuf));
526 EXPECT_STREQ(aBuf, "b");
527}
528
529TEST(Str, InList)
530{
531 char aTest[] = "GER,RUS,ZAF,BRA,CAN";
532 EXPECT_TRUE(str_in_list(aTest, ",", "GER"));
533 EXPECT_TRUE(str_in_list(aTest, ",", "RUS"));
534 EXPECT_TRUE(str_in_list(aTest, ",", "ZAF"));
535 EXPECT_TRUE(str_in_list(aTest, ",", "BRA"));
536 EXPECT_TRUE(str_in_list(aTest, ",", "CAN"));
537
538 EXPECT_FALSE(str_in_list(aTest, ",", "CHN"));
539 EXPECT_FALSE(str_in_list(aTest, ",", "R,R"));
540
541 EXPECT_FALSE(str_in_list("abc,xyz", ",", "abcdef"));
542 EXPECT_FALSE(str_in_list("", ",", ""));
543 EXPECT_FALSE(str_in_list("", ",", "xyz"));
544
545 EXPECT_TRUE(str_in_list("FOO,,BAR", ",", ""));
546 EXPECT_TRUE(str_in_list("abc,,def", ",", "def"));
547}
548
549TEST(Str, Format)
550{
551 char aBuf[4];
552 EXPECT_EQ(str_format(aBuf, 4, "%d:", 9), 2);
553 EXPECT_STREQ(aBuf, "9:");
554 EXPECT_EQ(str_format(aBuf, 4, "%d: ", 9), 3);
555 EXPECT_STREQ(aBuf, "9: ");
556 EXPECT_EQ(str_format(aBuf, 4, "%d: ", 99), 3);
557 EXPECT_STREQ(aBuf, "99:");
558}
559
560TEST(Str, FormatTruncate)
561{
562 const char *pStr = "DDNet最好了";
563 char aBuf[64];
564 str_format(buffer: aBuf, buffer_size: 7, format: "%s", pStr);
565 EXPECT_STREQ(aBuf, "DDNet");
566 str_format(buffer: aBuf, buffer_size: 8, format: "%s", pStr);
567 EXPECT_STREQ(aBuf, "DDNet");
568 str_format(buffer: aBuf, buffer_size: 9, format: "%s", pStr);
569 EXPECT_STREQ(aBuf, "DDNet最");
570 str_format(buffer: aBuf, buffer_size: 10, format: "%s", pStr);
571 EXPECT_STREQ(aBuf, "DDNet最");
572 str_format(buffer: aBuf, buffer_size: 11, format: "%s", pStr);
573 EXPECT_STREQ(aBuf, "DDNet最");
574 str_format(buffer: aBuf, buffer_size: 12, format: "%s", pStr);
575 EXPECT_STREQ(aBuf, "DDNet最好");
576 str_format(buffer: aBuf, buffer_size: 13, format: "%s", pStr);
577 EXPECT_STREQ(aBuf, "DDNet最好");
578 str_format(buffer: aBuf, buffer_size: 14, format: "%s", pStr);
579 EXPECT_STREQ(aBuf, "DDNet最好");
580 str_format(buffer: aBuf, buffer_size: 15, format: "%s", pStr);
581 EXPECT_STREQ(aBuf, "DDNet最好了");
582 str_format(buffer: aBuf, buffer_size: 16, format: "%s", pStr);
583 EXPECT_STREQ(aBuf, "DDNet最好了");
584}
585
586TEST(Str, TrimWords)
587{
588 const char *pStr1 = "aa bb ccc dddd eeeee";
589 EXPECT_STREQ(str_trim_words(pStr1, 0), "aa bb ccc dddd eeeee");
590 EXPECT_STREQ(str_trim_words(pStr1, 1), "bb ccc dddd eeeee");
591 EXPECT_STREQ(str_trim_words(pStr1, 2), "ccc dddd eeeee");
592 EXPECT_STREQ(str_trim_words(pStr1, 3), "dddd eeeee");
593 EXPECT_STREQ(str_trim_words(pStr1, 4), "eeeee");
594 EXPECT_STREQ(str_trim_words(pStr1, 5), "");
595 EXPECT_STREQ(str_trim_words(pStr1, 100), "");
596 const char *pStr2 = " aaa bb ";
597 EXPECT_STREQ(str_trim_words(pStr2, 0), "aaa bb ");
598 EXPECT_STREQ(str_trim_words(pStr2, 1), "bb ");
599 EXPECT_STREQ(str_trim_words(pStr2, 2), "");
600 EXPECT_STREQ(str_trim_words(pStr2, 100), "");
601 const char *pStr3 = "\n\naa bb\t\tccc\r\n\r\ndddd";
602 EXPECT_STREQ(str_trim_words(pStr3, 0), "aa bb\t\tccc\r\n\r\ndddd");
603 EXPECT_STREQ(str_trim_words(pStr3, 1), "bb\t\tccc\r\n\r\ndddd");
604 EXPECT_STREQ(str_trim_words(pStr3, 2), "ccc\r\n\r\ndddd");
605 EXPECT_STREQ(str_trim_words(pStr3, 3), "dddd");
606 EXPECT_STREQ(str_trim_words(pStr3, 4), "");
607 EXPECT_STREQ(str_trim_words(pStr3, 100), "");
608}
609
610TEST(Str, CopyNum)
611{
612 const char *pFoo = "Foobaré";
613 char aBuf[64];
614 str_utf8_truncate(dst: aBuf, dst_size: 3, src: pFoo, truncation_len: 1);
615 EXPECT_STREQ(aBuf, "F");
616 str_utf8_truncate(dst: aBuf, dst_size: 3, src: pFoo, truncation_len: 2);
617 EXPECT_STREQ(aBuf, "Fo");
618 str_utf8_truncate(dst: aBuf, dst_size: 3, src: pFoo, truncation_len: 3);
619 EXPECT_STREQ(aBuf, "Fo");
620 str_utf8_truncate(dst: aBuf, dst_size: sizeof(aBuf), src: pFoo, truncation_len: 6);
621 EXPECT_STREQ(aBuf, "Foobar");
622 str_utf8_truncate(dst: aBuf, dst_size: sizeof(aBuf), src: pFoo, truncation_len: 7);
623 EXPECT_STREQ(aBuf, "Foobaré");
624 str_utf8_truncate(dst: aBuf, dst_size: sizeof(aBuf), src: pFoo, truncation_len: 0);
625 EXPECT_STREQ(aBuf, "");
626
627 char aBuf2[8];
628 str_utf8_truncate(dst: aBuf2, dst_size: sizeof(aBuf2), src: pFoo, truncation_len: 7);
629 EXPECT_STREQ(aBuf2, "Foobar");
630 char aBuf3[9];
631 str_utf8_truncate(dst: aBuf3, dst_size: sizeof(aBuf3), src: pFoo, truncation_len: 7);
632 EXPECT_STREQ(aBuf3, "Foobaré");
633}
634
635TEST(Str, Copy)
636{
637 const char *pStr = "DDNet最好了";
638 char aBuf[64];
639 str_copy(dst: aBuf, src: pStr, dst_size: 7);
640 EXPECT_STREQ(aBuf, "DDNet");
641 str_copy(dst: aBuf, src: pStr, dst_size: 8);
642 EXPECT_STREQ(aBuf, "DDNet");
643 str_copy(dst: aBuf, src: pStr, dst_size: 9);
644 EXPECT_STREQ(aBuf, "DDNet最");
645 str_copy(dst: aBuf, src: pStr, dst_size: 10);
646 EXPECT_STREQ(aBuf, "DDNet最");
647 str_copy(dst: aBuf, src: pStr, dst_size: 11);
648 EXPECT_STREQ(aBuf, "DDNet最");
649 str_copy(dst: aBuf, src: pStr, dst_size: 12);
650 EXPECT_STREQ(aBuf, "DDNet最好");
651 str_copy(dst: aBuf, src: pStr, dst_size: 13);
652 EXPECT_STREQ(aBuf, "DDNet最好");
653 str_copy(dst: aBuf, src: pStr, dst_size: 14);
654 EXPECT_STREQ(aBuf, "DDNet最好");
655 str_copy(dst: aBuf, src: pStr, dst_size: 15);
656 EXPECT_STREQ(aBuf, "DDNet最好了");
657 str_copy(dst: aBuf, src: pStr, dst_size: 16);
658 EXPECT_STREQ(aBuf, "DDNet最好了");
659 str_copy(dst&: aBuf, src: pStr);
660 EXPECT_STREQ(aBuf, "DDNet最好了");
661}
662
663TEST(Str, Append)
664{
665 char aBuf[64];
666 aBuf[0] = '\0';
667 str_append(dst: aBuf, src: "DDNet最好了", dst_size: 7);
668 EXPECT_STREQ(aBuf, "DDNet");
669 str_append(dst: aBuf, src: "最", dst_size: 8);
670 EXPECT_STREQ(aBuf, "DDNet");
671 str_append(dst: aBuf, src: "最", dst_size: 9);
672 EXPECT_STREQ(aBuf, "DDNet最");
673 str_append(dst: aBuf, src: "好", dst_size: 10);
674 EXPECT_STREQ(aBuf, "DDNet最");
675 str_append(dst: aBuf, src: "好", dst_size: 11);
676 EXPECT_STREQ(aBuf, "DDNet最");
677 str_append(dst: aBuf, src: "好", dst_size: 12);
678 EXPECT_STREQ(aBuf, "DDNet最好");
679 str_append(dst: aBuf, src: "了", dst_size: 13);
680 EXPECT_STREQ(aBuf, "DDNet最好");
681 str_append(dst: aBuf, src: "了", dst_size: 14);
682 EXPECT_STREQ(aBuf, "DDNet最好");
683 str_append(dst: aBuf, src: "了", dst_size: 15);
684 EXPECT_STREQ(aBuf, "DDNet最好了");
685 str_append(dst: aBuf, src: "了", dst_size: 16);
686 EXPECT_STREQ(aBuf, "DDNet最好了");
687 aBuf[0] = '\0';
688 str_append(dst&: aBuf, src: "DDNet最好了");
689 EXPECT_STREQ(aBuf, "DDNet最好了");
690}
691
692TEST(Str, Utf8Stats)
693{
694 size_t Size, Count;
695
696 str_utf8_stats(str: "abc", max_size: 4, max_count: 3, size: &Size, count: &Count);
697 EXPECT_EQ(Size, 3);
698 EXPECT_EQ(Count, 3);
699
700 str_utf8_stats(str: "abc", max_size: 2, max_count: 3, size: &Size, count: &Count);
701 EXPECT_EQ(Size, 1);
702 EXPECT_EQ(Count, 1);
703
704 str_utf8_stats(str: "", max_size: 1, max_count: 0, size: &Size, count: &Count);
705 EXPECT_EQ(Size, 0);
706 EXPECT_EQ(Count, 0);
707
708 str_utf8_stats(str: "abcde", max_size: 6, max_count: 5, size: &Size, count: &Count);
709 EXPECT_EQ(Size, 5);
710 EXPECT_EQ(Count, 5);
711
712 str_utf8_stats(str: "любовь", max_size: 13, max_count: 6, size: &Size, count: &Count);
713 EXPECT_EQ(Size, 12);
714 EXPECT_EQ(Count, 6);
715
716 str_utf8_stats(str: "abc愛", max_size: 7, max_count: 4, size: &Size, count: &Count);
717 EXPECT_EQ(Size, 6);
718 EXPECT_EQ(Count, 4);
719
720 str_utf8_stats(str: "abc愛", max_size: 6, max_count: 4, size: &Size, count: &Count);
721 EXPECT_EQ(Size, 3);
722 EXPECT_EQ(Count, 3);
723
724 str_utf8_stats(str: "любовь", max_size: 13, max_count: 3, size: &Size, count: &Count);
725 EXPECT_EQ(Size, 6);
726 EXPECT_EQ(Count, 3);
727}
728
729TEST(Str, Utf8OffsetBytesToChars)
730{
731 EXPECT_EQ(str_utf8_offset_bytes_to_chars("", 0), 0);
732 EXPECT_EQ(str_utf8_offset_bytes_to_chars("", 100), 0);
733
734 EXPECT_EQ(str_utf8_offset_bytes_to_chars("abc", 0), 0);
735 EXPECT_EQ(str_utf8_offset_bytes_to_chars("abc", 1), 1);
736 EXPECT_EQ(str_utf8_offset_bytes_to_chars("abc", 2), 2);
737 EXPECT_EQ(str_utf8_offset_bytes_to_chars("abc", 3), 3);
738 EXPECT_EQ(str_utf8_offset_bytes_to_chars("abc", 100), 3);
739
740 EXPECT_EQ(str_utf8_offset_bytes_to_chars("любовь", 0), 0);
741 EXPECT_EQ(str_utf8_offset_bytes_to_chars("любовь", 2), 1);
742 EXPECT_EQ(str_utf8_offset_bytes_to_chars("любовь", 4), 2);
743 EXPECT_EQ(str_utf8_offset_bytes_to_chars("любовь", 6), 3);
744 EXPECT_EQ(str_utf8_offset_bytes_to_chars("любовь", 8), 4);
745 EXPECT_EQ(str_utf8_offset_bytes_to_chars("любовь", 10), 5);
746 EXPECT_EQ(str_utf8_offset_bytes_to_chars("любовь", 12), 6);
747 EXPECT_EQ(str_utf8_offset_bytes_to_chars("любовь", 100), 6);
748
749 EXPECT_EQ(str_utf8_offset_bytes_to_chars("DDNet最好了", 5), 5);
750 EXPECT_EQ(str_utf8_offset_bytes_to_chars("DDNet最好了", 8), 6);
751 EXPECT_EQ(str_utf8_offset_bytes_to_chars("DDNet最好了", 11), 7);
752 EXPECT_EQ(str_utf8_offset_bytes_to_chars("DDNet最好了", 14), 8);
753 EXPECT_EQ(str_utf8_offset_bytes_to_chars("DDNet最好了", 100), 8);
754}
755
756TEST(Str, Utf8OffsetCharsToBytes)
757{
758 EXPECT_EQ(str_utf8_offset_chars_to_bytes("", 0), 0);
759 EXPECT_EQ(str_utf8_offset_chars_to_bytes("", 100), 0);
760
761 EXPECT_EQ(str_utf8_offset_chars_to_bytes("abc", 0), 0);
762 EXPECT_EQ(str_utf8_offset_chars_to_bytes("abc", 1), 1);
763 EXPECT_EQ(str_utf8_offset_chars_to_bytes("abc", 2), 2);
764 EXPECT_EQ(str_utf8_offset_chars_to_bytes("abc", 3), 3);
765 EXPECT_EQ(str_utf8_offset_chars_to_bytes("abc", 100), 3);
766
767 EXPECT_EQ(str_utf8_offset_chars_to_bytes("любовь", 0), 0);
768 EXPECT_EQ(str_utf8_offset_chars_to_bytes("любовь", 1), 2);
769 EXPECT_EQ(str_utf8_offset_chars_to_bytes("любовь", 2), 4);
770 EXPECT_EQ(str_utf8_offset_chars_to_bytes("любовь", 3), 6);
771 EXPECT_EQ(str_utf8_offset_chars_to_bytes("любовь", 4), 8);
772 EXPECT_EQ(str_utf8_offset_chars_to_bytes("любовь", 5), 10);
773 EXPECT_EQ(str_utf8_offset_chars_to_bytes("любовь", 6), 12);
774 EXPECT_EQ(str_utf8_offset_chars_to_bytes("любовь", 100), 12);
775
776 EXPECT_EQ(str_utf8_offset_chars_to_bytes("DDNet最好了", 5), 5);
777 EXPECT_EQ(str_utf8_offset_chars_to_bytes("DDNet最好了", 6), 8);
778 EXPECT_EQ(str_utf8_offset_chars_to_bytes("DDNet最好了", 7), 11);
779 EXPECT_EQ(str_utf8_offset_chars_to_bytes("DDNet最好了", 8), 14);
780 EXPECT_EQ(str_utf8_offset_chars_to_bytes("DDNet最好了", 100), 14);
781}
782
783TEST(Str, Time)
784{
785 char aBuf[32] = "foobar";
786
787 EXPECT_EQ(str_time(123456, TIME_DAYS, aBuf, 0), -1);
788 EXPECT_STREQ(aBuf, "foobar");
789
790 EXPECT_EQ(str_time(123456, TIME_SECS_CENTISECS + 1, aBuf, sizeof(aBuf)), -1);
791 EXPECT_STREQ(aBuf, "");
792
793 EXPECT_EQ(str_time(-123456, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 5);
794 EXPECT_STREQ(aBuf, "00.00");
795
796 EXPECT_EQ(str_time(INT64_MAX, TIME_DAYS, aBuf, sizeof(aBuf)), 23);
797 EXPECT_STREQ(aBuf, "1067519911673d 00:09:18");
798
799 EXPECT_EQ(str_time(123456, TIME_DAYS, aBuf, sizeof(aBuf)), 5);
800 EXPECT_STREQ(aBuf, "20:34");
801 EXPECT_EQ(str_time(1234567, TIME_DAYS, aBuf, sizeof(aBuf)), 8);
802 EXPECT_STREQ(aBuf, "03:25:45");
803 EXPECT_EQ(str_time(12345678, TIME_DAYS, aBuf, sizeof(aBuf)), 11);
804 EXPECT_STREQ(aBuf, "1d 10:17:36");
805
806 EXPECT_EQ(str_time(123456, TIME_HOURS, aBuf, sizeof(aBuf)), 5);
807 EXPECT_STREQ(aBuf, "20:34");
808 EXPECT_EQ(str_time(1234567, TIME_HOURS, aBuf, sizeof(aBuf)), 8);
809 EXPECT_STREQ(aBuf, "03:25:45");
810 EXPECT_EQ(str_time(12345678, TIME_HOURS, aBuf, sizeof(aBuf)), 8);
811 EXPECT_STREQ(aBuf, "34:17:36");
812
813 EXPECT_EQ(str_time(123456, TIME_MINS, aBuf, sizeof(aBuf)), 5);
814 EXPECT_STREQ(aBuf, "20:34");
815 EXPECT_EQ(str_time(1234567, TIME_MINS, aBuf, sizeof(aBuf)), 6);
816 EXPECT_STREQ(aBuf, "205:45");
817 EXPECT_EQ(str_time(12345678, TIME_MINS, aBuf, sizeof(aBuf)), 7);
818 EXPECT_STREQ(aBuf, "2057:36");
819
820 EXPECT_EQ(str_time(123456, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 8);
821 EXPECT_STREQ(aBuf, "20:34.56");
822 EXPECT_EQ(str_time(1234567, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 11);
823 EXPECT_STREQ(aBuf, "03:25:45.67");
824 EXPECT_EQ(str_time(12345678, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 11);
825 EXPECT_STREQ(aBuf, "34:17:36.78");
826
827 EXPECT_EQ(str_time(123456, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 8);
828 EXPECT_STREQ(aBuf, "20:34.56");
829 EXPECT_EQ(str_time(1234567, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 9);
830 EXPECT_STREQ(aBuf, "205:45.67");
831 EXPECT_EQ(str_time(12345678, TIME_MINS_CENTISECS, aBuf, sizeof(aBuf)), 10);
832 EXPECT_STREQ(aBuf, "2057:36.78");
833
834 EXPECT_EQ(str_time(123456, TIME_SECS_CENTISECS, aBuf, sizeof(aBuf)), 5);
835 EXPECT_STREQ(aBuf, "34.56");
836 EXPECT_EQ(str_time(1234567, TIME_SECS_CENTISECS, aBuf, sizeof(aBuf)), 5);
837 EXPECT_STREQ(aBuf, "45.67");
838 EXPECT_EQ(str_time(12345678, TIME_SECS_CENTISECS, aBuf, sizeof(aBuf)), 5);
839 EXPECT_STREQ(aBuf, "36.78");
840}
841
842TEST(Str, TimeFloat)
843{
844 char aBuf[64];
845 EXPECT_EQ(str_time_float(123456.78, TIME_DAYS, aBuf, sizeof(aBuf)), 11);
846 EXPECT_STREQ(aBuf, "1d 10:17:36");
847
848 EXPECT_EQ(str_time_float(12.16, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)), 5);
849 EXPECT_STREQ(aBuf, "12.16");
850
851 EXPECT_EQ(str_time_float(22.995, TIME_MINS, aBuf, sizeof(aBuf)), 5);
852 EXPECT_STREQ(aBuf, "00:22");
853}
854
855TEST(Str, HasCc)
856{
857 EXPECT_FALSE(str_has_cc(""));
858 EXPECT_FALSE(str_has_cc("a"));
859 EXPECT_FALSE(str_has_cc("Merhaba dünya!"));
860
861 EXPECT_TRUE(str_has_cc("\n"));
862 EXPECT_TRUE(str_has_cc("\r"));
863 EXPECT_TRUE(str_has_cc("\t"));
864 EXPECT_TRUE(str_has_cc("a\n"));
865 EXPECT_TRUE(str_has_cc("a\rb"));
866 EXPECT_TRUE(str_has_cc("\tb"));
867 EXPECT_TRUE(str_has_cc("\n\n"));
868 EXPECT_TRUE(str_has_cc("\x1C"));
869 EXPECT_TRUE(str_has_cc("\x1D"));
870 EXPECT_TRUE(str_has_cc("\x1E"));
871 EXPECT_TRUE(str_has_cc("\x1F"));
872}
873
874TEST(Str, SanitizeCc)
875{
876 char aBuf[64];
877 str_copy(dst&: aBuf, src: "");
878 str_sanitize_cc(str: aBuf);
879 EXPECT_STREQ(aBuf, "");
880 str_copy(dst&: aBuf, src: "a");
881 str_sanitize_cc(str: aBuf);
882 EXPECT_STREQ(aBuf, "a");
883 str_copy(dst&: aBuf, src: "Merhaba dünya!");
884 str_sanitize_cc(str: aBuf);
885 EXPECT_STREQ(aBuf, "Merhaba dünya!");
886
887 str_copy(dst&: aBuf, src: "\n");
888 str_sanitize_cc(str: aBuf);
889 EXPECT_STREQ(aBuf, " ");
890 str_copy(dst&: aBuf, src: "\r");
891 str_sanitize_cc(str: aBuf);
892 EXPECT_STREQ(aBuf, " ");
893 str_copy(dst&: aBuf, src: "\t");
894 str_sanitize_cc(str: aBuf);
895 EXPECT_STREQ(aBuf, " ");
896 str_copy(dst&: aBuf, src: "a\n");
897 str_sanitize_cc(str: aBuf);
898 EXPECT_STREQ(aBuf, "a ");
899 str_copy(dst&: aBuf, src: "a\rb");
900 str_sanitize_cc(str: aBuf);
901 EXPECT_STREQ(aBuf, "a b");
902 str_copy(dst&: aBuf, src: "\tb");
903 str_sanitize_cc(str: aBuf);
904 EXPECT_STREQ(aBuf, " b");
905 str_copy(dst&: aBuf, src: "\n\n");
906 str_sanitize_cc(str: aBuf);
907 EXPECT_STREQ(aBuf, " ");
908 str_copy(dst&: aBuf, src: "\x1C");
909 str_sanitize_cc(str: aBuf);
910 EXPECT_STREQ(aBuf, " ");
911 str_copy(dst&: aBuf, src: "\x1D");
912 str_sanitize_cc(str: aBuf);
913 EXPECT_STREQ(aBuf, " ");
914 str_copy(dst&: aBuf, src: "\x1E");
915 str_sanitize_cc(str: aBuf);
916 EXPECT_STREQ(aBuf, " ");
917 str_copy(dst&: aBuf, src: "\x1F");
918 str_sanitize_cc(str: aBuf);
919 EXPECT_STREQ(aBuf, " ");
920}
921
922TEST(Str, Sanitize)
923{
924 char aBuf[64];
925 str_copy(dst&: aBuf, src: "");
926 str_sanitize(str: aBuf);
927 EXPECT_STREQ(aBuf, "");
928 str_copy(dst&: aBuf, src: "a");
929 str_sanitize(str: aBuf);
930 EXPECT_STREQ(aBuf, "a");
931 str_copy(dst&: aBuf, src: "Merhaba dünya!");
932 str_sanitize(str: aBuf);
933 EXPECT_STREQ(aBuf, "Merhaba dünya!");
934 str_copy(dst&: aBuf, src: "\n");
935 str_sanitize(str: aBuf);
936 EXPECT_STREQ(aBuf, "\n");
937 str_copy(dst&: aBuf, src: "\r");
938 str_sanitize(str: aBuf);
939 EXPECT_STREQ(aBuf, "\r");
940 str_copy(dst&: aBuf, src: "\t");
941 str_sanitize(str: aBuf);
942 EXPECT_STREQ(aBuf, "\t");
943 str_copy(dst&: aBuf, src: "a\n");
944 str_sanitize(str: aBuf);
945 EXPECT_STREQ(aBuf, "a\n");
946 str_copy(dst&: aBuf, src: "a\rb");
947 str_sanitize(str: aBuf);
948 EXPECT_STREQ(aBuf, "a\rb");
949 str_copy(dst&: aBuf, src: "\tb");
950 str_sanitize(str: aBuf);
951 EXPECT_STREQ(aBuf, "\tb");
952 str_copy(dst&: aBuf, src: "\n\n");
953 str_sanitize(str: aBuf);
954 EXPECT_STREQ(aBuf, "\n\n");
955
956 str_copy(dst&: aBuf, src: "\x1C");
957 str_sanitize(str: aBuf);
958 EXPECT_STREQ(aBuf, " ");
959 str_copy(dst&: aBuf, src: "\x1D");
960 str_sanitize(str: aBuf);
961 EXPECT_STREQ(aBuf, " ");
962 str_copy(dst&: aBuf, src: "\x1E");
963 str_sanitize(str: aBuf);
964 EXPECT_STREQ(aBuf, " ");
965 str_copy(dst&: aBuf, src: "\x1F");
966 str_sanitize(str: aBuf);
967 EXPECT_STREQ(aBuf, " ");
968}
969
970TEST(Str, CleanWhitespaces)
971{
972 char aBuf[64];
973 str_copy(dst&: aBuf, src: "aa bb ccc dddd eeeee");
974 str_clean_whitespaces(str: aBuf);
975 EXPECT_STREQ(aBuf, "aa bb ccc dddd eeeee");
976 str_copy(dst&: aBuf, src: " ");
977 str_clean_whitespaces(str: aBuf);
978 EXPECT_STREQ(aBuf, "");
979 str_copy(dst&: aBuf, src: " aa");
980 str_clean_whitespaces(str: aBuf);
981 EXPECT_STREQ(aBuf, "aa");
982 str_copy(dst&: aBuf, src: "aa ");
983 str_clean_whitespaces(str: aBuf);
984 EXPECT_STREQ(aBuf, "aa");
985 str_copy(dst&: aBuf, src: " aa bb ccc dddd eeeee ");
986 str_clean_whitespaces(str: aBuf);
987 EXPECT_STREQ(aBuf, "aa bb ccc dddd eeeee");
988}
989
990TEST(Str, SkipToWhitespace)
991{
992 char aBuf[64];
993 str_copy(dst&: aBuf, src: "");
994 EXPECT_EQ(str_skip_to_whitespace(aBuf), aBuf);
995 EXPECT_EQ(str_skip_to_whitespace_const(aBuf), aBuf);
996 str_copy(dst&: aBuf, src: " a");
997 EXPECT_EQ(str_skip_to_whitespace(aBuf), aBuf);
998 EXPECT_EQ(str_skip_to_whitespace_const(aBuf), aBuf);
999 str_copy(dst&: aBuf, src: "aaaa b");
1000 EXPECT_EQ(str_skip_to_whitespace(aBuf), aBuf + 4);
1001 EXPECT_EQ(str_skip_to_whitespace_const(aBuf), aBuf + 4);
1002 str_copy(dst&: aBuf, src: "aaaa\n\nb");
1003 EXPECT_EQ(str_skip_to_whitespace(aBuf), aBuf + 4);
1004 EXPECT_EQ(str_skip_to_whitespace_const(aBuf), aBuf + 4);
1005 str_copy(dst&: aBuf, src: "aaaa\r\rb");
1006 EXPECT_EQ(str_skip_to_whitespace(aBuf), aBuf + 4);
1007 EXPECT_EQ(str_skip_to_whitespace_const(aBuf), aBuf + 4);
1008 str_copy(dst&: aBuf, src: "aaaa\t\tb");
1009 EXPECT_EQ(str_skip_to_whitespace(aBuf), aBuf + 4);
1010 EXPECT_EQ(str_skip_to_whitespace_const(aBuf), aBuf + 4);
1011}
1012
1013TEST(Str, SkipWhitespaces)
1014{
1015 char aBuf[64];
1016 str_copy(dst&: aBuf, src: "");
1017 EXPECT_EQ(str_skip_whitespaces(aBuf), aBuf);
1018 EXPECT_EQ(str_skip_whitespaces_const(aBuf), aBuf);
1019 str_copy(dst&: aBuf, src: "aaaa");
1020 EXPECT_EQ(str_skip_whitespaces(aBuf), aBuf);
1021 EXPECT_EQ(str_skip_whitespaces_const(aBuf), aBuf);
1022 str_copy(dst&: aBuf, src: " \n\r\taaaa");
1023 EXPECT_EQ(str_skip_whitespaces(aBuf), aBuf + 4);
1024 EXPECT_EQ(str_skip_whitespaces_const(aBuf), aBuf + 4);
1025}
1026
1027TEST(Str, CompFilename)
1028{
1029 EXPECT_EQ(str_comp_filenames("a", "a"), 0);
1030 EXPECT_LT(str_comp_filenames("a", "b"), 0);
1031 EXPECT_GT(str_comp_filenames("b", "a"), 0);
1032 EXPECT_EQ(str_comp_filenames("A", "a"), 0);
1033 EXPECT_LT(str_comp_filenames("A", "b"), 0);
1034 EXPECT_GT(str_comp_filenames("b", "A"), 0);
1035 EXPECT_LT(str_comp_filenames("a", "B"), 0);
1036 EXPECT_GT(str_comp_filenames("B", "a"), 0);
1037 EXPECT_EQ(str_comp_filenames("1A", "1a"), 0);
1038 EXPECT_LT(str_comp_filenames("1a", "1B"), 0);
1039 EXPECT_GT(str_comp_filenames("1B", "1a"), 0);
1040 EXPECT_LT(str_comp_filenames("1a", "1b"), 0);
1041 EXPECT_GT(str_comp_filenames("1b", "1a"), 0);
1042 EXPECT_GT(str_comp_filenames("12a", "1B"), 0);
1043 EXPECT_LT(str_comp_filenames("1B", "12a"), 0);
1044 EXPECT_GT(str_comp_filenames("10a", "1B"), 0);
1045 EXPECT_LT(str_comp_filenames("1B", "10a"), 0);
1046 EXPECT_GT(str_comp_filenames("10a", "00B"), 0);
1047 EXPECT_LT(str_comp_filenames("00B", "10a"), 0);
1048 EXPECT_GT(str_comp_filenames("10a", "09B"), 0);
1049 EXPECT_LT(str_comp_filenames("09B", "10a"), 0);
1050 EXPECT_LT(str_comp_filenames("abc", "abcd"), 0);
1051 EXPECT_GT(str_comp_filenames("abcd", "abc"), 0);
1052 EXPECT_LT(str_comp_filenames("abc2", "abcd1"), 0);
1053 EXPECT_GT(str_comp_filenames("abcd1", "abc2"), 0);
1054 EXPECT_LT(str_comp_filenames("abc50", "abcd"), 0);
1055 EXPECT_GT(str_comp_filenames("abcd", "abc50"), 0);
1056 EXPECT_EQ(str_comp_filenames("file0", "file0"), 0);
1057 EXPECT_LT(str_comp_filenames("file0", "file1"), 0);
1058 EXPECT_GT(str_comp_filenames("file1", "file0"), 0);
1059 EXPECT_LT(str_comp_filenames("file1", "file09"), 0);
1060 EXPECT_GT(str_comp_filenames("file09", "file1"), 0);
1061 EXPECT_LT(str_comp_filenames("file1", "file009"), 0);
1062 EXPECT_GT(str_comp_filenames("file009", "file1"), 0);
1063 EXPECT_GT(str_comp_filenames("file10", "file00"), 0);
1064 EXPECT_LT(str_comp_filenames("file00", "file10"), 0);
1065 EXPECT_GT(str_comp_filenames("file10", "file09"), 0);
1066 EXPECT_LT(str_comp_filenames("file09", "file10"), 0);
1067 EXPECT_LT(str_comp_filenames("file13", "file37"), 0);
1068 EXPECT_GT(str_comp_filenames("file37", "file13"), 0);
1069 EXPECT_LT(str_comp_filenames("file1.ext", "file09.ext"), 0);
1070 EXPECT_GT(str_comp_filenames("file09.ext", "file1.ext"), 0);
1071 EXPECT_LT(str_comp_filenames("file1.ext", "file009.ext"), 0);
1072 EXPECT_GT(str_comp_filenames("file009.ext", "file1.ext"), 0);
1073 EXPECT_EQ(str_comp_filenames("file0.ext", "file0.ext"), 0);
1074 EXPECT_LT(str_comp_filenames("file13.ext", "file37.ext"), 0);
1075 EXPECT_GT(str_comp_filenames("file37.ext", "file13.ext"), 0);
1076 EXPECT_LT(str_comp_filenames("FILE13.EXT", "file37.ext"), 0);
1077 EXPECT_GT(str_comp_filenames("file37.ext", "FILE13.EXT"), 0);
1078 EXPECT_GT(str_comp_filenames("file10.ext", "file00.ext"), 0);
1079 EXPECT_LT(str_comp_filenames("file00.ext", "file10.ext"), 0);
1080 EXPECT_GT(str_comp_filenames("file10.ext", "file09.ext"), 0);
1081 EXPECT_LT(str_comp_filenames("file09.ext", "file10.ext"), 0);
1082 EXPECT_LT(str_comp_filenames("file42", "file1337"), 0);
1083 EXPECT_GT(str_comp_filenames("file1337", "file42"), 0);
1084 EXPECT_LT(str_comp_filenames("file42.ext", "file1337.ext"), 0);
1085 EXPECT_GT(str_comp_filenames("file1337.ext", "file42.ext"), 0);
1086 EXPECT_GT(str_comp_filenames("file4414520", "file2055"), 0);
1087 EXPECT_LT(str_comp_filenames("file4414520", "file205523151812419"), 0);
1088}
1089
1090TEST(Str, RightChar)
1091{
1092 const char *pStr = "a bb ccc dddd eeeee";
1093 EXPECT_EQ(str_rchr(pStr, 'a'), pStr);
1094 EXPECT_EQ(str_rchr(pStr, 'b'), pStr + 3);
1095 EXPECT_EQ(str_rchr(pStr, 'c'), pStr + 7);
1096 EXPECT_EQ(str_rchr(pStr, 'd'), pStr + 12);
1097 EXPECT_EQ(str_rchr(pStr, ' '), pStr + 19);
1098 EXPECT_EQ(str_rchr(pStr, 'e'), pStr + 24);
1099 EXPECT_EQ(str_rchr(pStr, '\0'), pStr + str_length(pStr));
1100 EXPECT_EQ(str_rchr(pStr, 'y'), nullptr);
1101}
1102
1103TEST(Str, CountChar)
1104{
1105 const char *pStr = "a bb ccc dddd eeeee";
1106 EXPECT_EQ(str_countchr(pStr, 'a'), 1);
1107 EXPECT_EQ(str_countchr(pStr, 'b'), 2);
1108 EXPECT_EQ(str_countchr(pStr, 'c'), 3);
1109 EXPECT_EQ(str_countchr(pStr, 'd'), 4);
1110 EXPECT_EQ(str_countchr(pStr, 'e'), 5);
1111 EXPECT_EQ(str_countchr(pStr, ' '), 10);
1112 EXPECT_EQ(str_countchr(pStr, '\0'), 0);
1113 EXPECT_EQ(str_countchr(pStr, 'y'), 0);
1114}
1115
1116TEST(Str, StrToInts)
1117{
1118 int aInts[8];
1119
1120 StrToInts(pInts: aInts, NumInts: 1, pStr: "a");
1121 EXPECT_EQ(aInts[0], 0xE1808000);
1122
1123 StrToInts(pInts: aInts, NumInts: 1, pStr: "ab");
1124 EXPECT_EQ(aInts[0], 0xE1E28000);
1125
1126 StrToInts(pInts: aInts, NumInts: 1, pStr: "abc");
1127 EXPECT_EQ(aInts[0], 0xE1E2E300);
1128
1129 StrToInts(pInts: aInts, NumInts: 2, pStr: "abcd");
1130 EXPECT_EQ(aInts[0], 0xE1E2E3E4);
1131 EXPECT_EQ(aInts[1], 0x80808000);
1132
1133 StrToInts(pInts: aInts, NumInts: 2, pStr: "abcde");
1134 EXPECT_EQ(aInts[0], 0xE1E2E3E4);
1135 EXPECT_EQ(aInts[1], 0xE5808000);
1136
1137 StrToInts(pInts: aInts, NumInts: 2, pStr: "abcdef");
1138 EXPECT_EQ(aInts[0], 0xE1E2E3E4);
1139 EXPECT_EQ(aInts[1], 0xE5E68000);
1140
1141 StrToInts(pInts: aInts, NumInts: 2, pStr: "abcdefg");
1142 EXPECT_EQ(aInts[0], 0xE1E2E3E4);
1143 EXPECT_EQ(aInts[1], 0xE5E6E700);
1144
1145 StrToInts(pInts: aInts, NumInts: 2, pStr: "öüä");
1146 EXPECT_EQ(aInts[0], 0x4336433C);
1147 EXPECT_EQ(aInts[1], 0x43248000);
1148
1149 StrToInts(pInts: aInts, NumInts: 3, pStr: "aβい🐘");
1150 EXPECT_EQ(aInts[0], 0xE14E3263);
1151 EXPECT_EQ(aInts[1], 0x0104701F);
1152 EXPECT_EQ(aInts[2], 0x10188000);
1153
1154 // long padding
1155 StrToInts(pInts: aInts, NumInts: 4, pStr: "abc");
1156 EXPECT_EQ(aInts[0], 0xE1E2E380);
1157 EXPECT_EQ(aInts[1], 0x80808080);
1158 EXPECT_EQ(aInts[2], 0x80808080);
1159 EXPECT_EQ(aInts[3], 0x80808000);
1160}
1161
1162TEST(Str, IntsToStr)
1163{
1164 int aInts[8];
1165 char aStr[sizeof(aInts)];
1166
1167 aInts[0] = 0xE1808000;
1168 EXPECT_TRUE(IntsToStr(aInts, 1, aStr, std::size(aStr)));
1169 EXPECT_STREQ(aStr, "a");
1170
1171 aInts[0] = 0xE1E28000;
1172 EXPECT_TRUE(IntsToStr(aInts, 1, aStr, std::size(aStr)));
1173 EXPECT_STREQ(aStr, "ab");
1174
1175 aInts[0] = 0xE1E2E300;
1176 EXPECT_TRUE(IntsToStr(aInts, 1, aStr, std::size(aStr)));
1177 EXPECT_STREQ(aStr, "abc");
1178
1179 aInts[0] = 0xE1E2E3E4;
1180 aInts[1] = 0x80808000;
1181 EXPECT_TRUE(IntsToStr(aInts, 2, aStr, std::size(aStr)));
1182 EXPECT_STREQ(aStr, "abcd");
1183
1184 aInts[0] = 0xE1E2E3E4;
1185 aInts[1] = 0xE5808000;
1186 EXPECT_TRUE(IntsToStr(aInts, 2, aStr, std::size(aStr)));
1187 EXPECT_STREQ(aStr, "abcde");
1188
1189 aInts[0] = 0xE1E2E3E4;
1190 aInts[1] = 0xE5E68000;
1191 EXPECT_TRUE(IntsToStr(aInts, 2, aStr, std::size(aStr)));
1192 EXPECT_STREQ(aStr, "abcdef");
1193
1194 aInts[0] = 0xE1E2E3E4;
1195 aInts[1] = 0xE5E6E700;
1196 EXPECT_TRUE(IntsToStr(aInts, 2, aStr, std::size(aStr)));
1197 EXPECT_STREQ(aStr, "abcdefg");
1198
1199 aInts[0] = 0x4336433C;
1200 aInts[1] = 0x43248000;
1201 EXPECT_TRUE(IntsToStr(aInts, 2, aStr, std::size(aStr)));
1202 EXPECT_STREQ(aStr, "öüä");
1203
1204 aInts[0] = 0xE14E3263;
1205 aInts[1] = 0x0104701F;
1206 aInts[2] = 0x10188000;
1207 EXPECT_TRUE(IntsToStr(aInts, 3, aStr, std::size(aStr)));
1208 EXPECT_STREQ(aStr, "aβい🐘");
1209
1210 // long padding
1211 aInts[0] = 0xE1E2E380;
1212 aInts[1] = 0x80808080;
1213 aInts[2] = 0x80808080;
1214 aInts[3] = 0x80808000;
1215 EXPECT_TRUE(IntsToStr(aInts, 4, aStr, std::size(aStr)));
1216 EXPECT_STREQ(aStr, "abc");
1217
1218 // early null character (0x80)
1219 aInts[0] = 0xE1E2E380;
1220 aInts[1] = 0xE1E2E3E4;
1221 aInts[2] = 0xE1E2E3E4;
1222 aInts[3] = 0xE1E2E300;
1223 EXPECT_TRUE(IntsToStr(aInts, 4, aStr, std::size(aStr)));
1224 EXPECT_STREQ(aStr, "abc");
1225
1226 // invalid UTF-8
1227 aInts[0] = 0xE17FE200;
1228 EXPECT_FALSE(IntsToStr(aInts, 1, aStr, std::size(aStr)));
1229 EXPECT_STREQ(aStr, "");
1230
1231 // invalid UTF-8 (0x00 in string data, which is translated to '\x80')
1232 aInts[0] = 0xE100E200;
1233 EXPECT_FALSE(IntsToStr(aInts, 1, aStr, std::size(aStr)));
1234 EXPECT_STREQ(aStr, "");
1235
1236 // invalid UTF-8
1237 aInts[0] = 0xE1E2E36F;
1238 aInts[1] = 0x3F40E4E5;
1239 aInts[2] = 0xE67FE700;
1240 EXPECT_FALSE(IntsToStr(aInts, 3, aStr, std::size(aStr)));
1241 EXPECT_STREQ(aStr, "");
1242
1243 // invalid UTF-8 and missing null-terminator
1244 aInts[0] = 0x7F7F7F7F;
1245 EXPECT_FALSE(IntsToStr(aInts, 1, aStr, std::size(aStr)));
1246 EXPECT_STREQ(aStr, "");
1247
1248 // missing null-terminator at the end is ignored
1249 aInts[0] = 0xE1E2E3E4;
1250 EXPECT_TRUE(IntsToStr(aInts, 1, aStr, std::size(aStr)));
1251 EXPECT_STREQ(aStr, "abc");
1252
1253 // basic fuzzing: no input integer should result in invalid UTF-8 in the string
1254 for(int i = 0; i <= 0xFFFFFF; i += 7) // checking all values takes a bit too long
1255 {
1256 mem_zero(block: aStr, size: std::size(aStr));
1257 aInts[0] = 0xE1 << 24 | i;
1258 aInts[1] = i << 8 | 0xE2;
1259 aInts[2] = 0xE3 << 24 | i;
1260 const bool ConversionResult = IntsToStr(pInts: aInts, NumInts: 3, pStr: aStr, StrSize: std::size(aStr));
1261 // ensure null-termination before calling str_utf8_check
1262 ASSERT_TRUE(mem_has_null(aStr, std::size(aStr)));
1263 ASSERT_TRUE(str_utf8_check(aStr));
1264 ASSERT_TRUE(ConversionResult || aStr[0] == '\0');
1265 }
1266}
1267
1268#if defined(CONF_FAMILY_WINDOWS)
1269TEST(Str, WindowsUtf8WideConversion)
1270{
1271 const char *apUtf8Strings[] = {
1272 "",
1273 "abc",
1274 "a bb ccc dddd eeeee",
1275 "öüä",
1276 "привет Наташа",
1277 "ąçęįǫų",
1278 "DDNet最好了",
1279 "aβい🐘"};
1280 const wchar_t *apWideStrings[] = {
1281 L"",
1282 L"abc",
1283 L"a bb ccc dddd eeeee",
1284 L"öüä",
1285 L"привет Наташа",
1286 L"ąçęįǫų",
1287 L"DDNet最好了",
1288 L"aβい🐘"};
1289 static_assert(std::size(apUtf8Strings) == std::size(apWideStrings));
1290 for(size_t i = 0; i < std::size(apUtf8Strings); i++)
1291 {
1292 const std::optional<std::string> ConvertedUtf8 = windows_wide_to_utf8(apWideStrings[i]);
1293 const std::wstring ConvertedWide = windows_utf8_to_wide(apUtf8Strings[i]);
1294 ASSERT_TRUE(ConvertedUtf8.has_value());
1295 EXPECT_STREQ(ConvertedUtf8.value().c_str(), apUtf8Strings[i]);
1296 EXPECT_STREQ(ConvertedWide.c_str(), apWideStrings[i]);
1297 }
1298}
1299#endif
1300