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