Blender V4.3
BLI_string_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "testing/testing.h"
6
7#include <array>
8#include <initializer_list>
9#include <ostream> /* NOLINT */
10#include <string>
11#include <utility>
12#include <vector>
13
14#include "MEM_guardedalloc.h"
15
16#include "BLI_string.h"
17#include "BLI_string_utf8.h"
18#include "BLI_string_utils.hh"
19#include "BLI_utildefines.h"
20
21using std::initializer_list;
22using std::pair;
23using std::string;
24using std::vector;
25
26/* -------------------------------------------------------------------- */
30TEST(string, StrCopyUTF8_ASCII)
31{
32#define STRNCPY_UTF8_ASCII(...) \
33 { \
34 const char src[] = {__VA_ARGS__, 0}; \
35 char dst[sizeof(src)]; \
36 memset(dst, 0xff, sizeof(dst)); \
37 STRNCPY_UTF8(dst, src); \
38 EXPECT_EQ(strlen(dst), sizeof(dst) - 1); \
39 EXPECT_STREQ(dst, src); \
40 }
41
43 STRNCPY_UTF8_ASCII('a', 'b', 'c');
44
45#undef STRNCPY_UTF8_ASCII
46}
47
48TEST(string, StrCopyUTF8_ASCII_Truncate)
49{
50#define STRNCPY_UTF8_ASCII_TRUNCATE(maxncpy, ...) \
51 { \
52 char src[] = {__VA_ARGS__}; \
53 char dst[sizeof(src)]; \
54 memset(dst, 0xff, sizeof(dst)); \
55 BLI_strncpy_utf8(dst, src, maxncpy); \
56 int len_expect = std::min<int>(sizeof(src), maxncpy) - 1; \
57 src[len_expect] = '\0'; /* To be able to use `EXPECT_STREQ`. */ \
58 EXPECT_EQ(strlen(dst), len_expect); \
59 EXPECT_STREQ(dst, src); \
60 }
61
63 STRNCPY_UTF8_ASCII_TRUNCATE(3, 'A', 'A', 'A', 'A');
64
65#undef STRNCPY_UTF8_ASCII_TRUNCATE
66}
67
68TEST(string, StrCopyUTF8_TruncateEncoding)
69{
70 /* Ensure copying one byte less than the code-point results in it being ignored entirely. */
71#define STRNCPY_UTF8_TRUNCATE(byte_size, ...) \
72 { \
73 const char src[] = {__VA_ARGS__, 0}; \
74 EXPECT_EQ(BLI_str_utf8_size_or_error(src), byte_size); \
75 char dst[sizeof(src)]; \
76 memset(dst, 0xff, sizeof(dst)); \
77 STRNCPY_UTF8(dst, src); \
78 EXPECT_EQ(strlen(dst), sizeof(dst) - 1); \
79 EXPECT_STREQ(dst, src); \
80 BLI_strncpy_utf8(dst, src, sizeof(dst) - 1); \
81 EXPECT_STREQ(dst, ""); \
82 }
83
84 STRNCPY_UTF8_TRUNCATE(6, 252, 1, 1, 1, 1, 1);
85 STRNCPY_UTF8_TRUNCATE(5, 248, 1, 1, 1, 1);
86 STRNCPY_UTF8_TRUNCATE(4, 240, 1, 1, 1);
87 STRNCPY_UTF8_TRUNCATE(3, 224, 1, 1);
88 STRNCPY_UTF8_TRUNCATE(2, 192, 1);
90
91#undef STRNCPY_UTF8_TRUNCATE
92}
93
94TEST(string, StrCopyUTF8_TerminateEncodingEarly)
95{
96 /* A UTF8 sequence that has a null byte before the sequence ends.
97 * Ensure the UTF8 sequence does not step over the null byte. */
98#define STRNCPY_UTF8_TERMINATE_EARLY(byte_size, ...) \
99 { \
100 char src[] = {__VA_ARGS__, 0}; \
101 EXPECT_EQ(BLI_str_utf8_size_or_error(src), byte_size); \
102 char dst[sizeof(src)]; \
103 memset(dst, 0xff, sizeof(dst)); \
104 STRNCPY_UTF8(dst, src); \
105 EXPECT_EQ(strlen(dst), sizeof(dst) - 1); \
106 EXPECT_STREQ(dst, src); \
107 for (int i = sizeof(dst) - 1; i > 1; i--) { \
108 src[i] = '\0'; \
109 memset(dst, 0xff, sizeof(dst)); \
110 const int dst_copied = STRNCPY_UTF8_RLEN(dst, src); \
111 EXPECT_STREQ(dst, src); \
112 EXPECT_EQ(strlen(dst), i); \
113 EXPECT_EQ(dst_copied, i); \
114 } \
115 }
116
117 STRNCPY_UTF8_TERMINATE_EARLY(6, 252, 1, 1, 1, 1, 1);
118 STRNCPY_UTF8_TERMINATE_EARLY(5, 248, 1, 1, 1, 1);
119 STRNCPY_UTF8_TERMINATE_EARLY(4, 240, 1, 1, 1);
120 STRNCPY_UTF8_TERMINATE_EARLY(3, 224, 1, 1);
123
124#undef STRNCPY_UTF8_TERMINATE_EARLY
125}
126
129/* -------------------------------------------------------------------- */
133TEST(string, StrCat)
134{
135#define STR_N_CAT(dst_init, dst_size, src, result_expect) \
136 { \
137 char dst[dst_size + 1] = dst_init; \
138 dst[dst_size] = 0xff; \
139 BLI_strncat(dst, src, dst_size); \
140 EXPECT_STREQ(dst, result_expect); \
141 EXPECT_EQ(dst[dst_size], 0xff); \
142 }
143
144 STR_N_CAT("", 1, "", "");
145 STR_N_CAT("", 1, "Y", "");
146 STR_N_CAT("", 2, "Y", "Y");
147 STR_N_CAT("", 2, "YZ", "Y");
148 STR_N_CAT("X", 2, "YZ", "X");
149 STR_N_CAT("ABC", 4, "XYZ", "ABC");
150 STR_N_CAT("ABC", 7, "XYZ", "ABCXYZ");
151#undef STR_N_CAT
152}
153
156/* -------------------------------------------------------------------- */
160TEST(string, StrReplaceRange)
161{
162#define STR_REPLACE_RANGE(src, size, beg, end, dst, result_expect) \
163 { \
164 char string[size] = src; \
165 BLI_string_replace_range(string, sizeof(string), beg, end, dst); \
166 EXPECT_STREQ(string, result_expect); \
167 }
168
169 STR_REPLACE_RANGE("a ", 5, 2, 2, "b!", "a b!");
170 STR_REPLACE_RANGE("a ", 4, 2, 2, "b!", "a b");
171 STR_REPLACE_RANGE("a ", 5, 1, 2, "b!", "ab!");
172 STR_REPLACE_RANGE("XYZ", 5, 1, 1, "A", "XAYZ");
173 STR_REPLACE_RANGE("XYZ", 5, 1, 1, "AB", "XABY");
174 STR_REPLACE_RANGE("XYZ", 5, 1, 1, "ABC", "XABC");
175
176 /* Add at the end when there is no room (no-op). */
177 STR_REPLACE_RANGE("XYZA", 5, 4, 4, "?", "XYZA");
178 /* Add at the start, replace all contents. */
179 STR_REPLACE_RANGE("XYZ", 4, 0, 0, "ABC", "ABC");
180 STR_REPLACE_RANGE("XYZ", 7, 0, 0, "ABC", "ABCXYZ");
181 /* Only remove. */
182 STR_REPLACE_RANGE("XYZ", 4, 1, 3, "", "X");
183 STR_REPLACE_RANGE("XYZ", 4, 0, 2, "", "Z");
184 STR_REPLACE_RANGE("XYZ", 4, 0, 3, "", "");
185 /* Only Add. */
186 STR_REPLACE_RANGE("", 4, 0, 0, "XYZ", "XYZ");
187 STR_REPLACE_RANGE("", 4, 0, 0, "XYZ?", "XYZ");
188 /* Do nothing. */
189 STR_REPLACE_RANGE("", 1, 0, 0, "?", "");
190 STR_REPLACE_RANGE("", 1, 0, 0, "", "");
191
192#undef STR_REPLACE_RANGE
193}
194
197/* -------------------------------------------------------------------- */
201/* BLI_str_partition */
202TEST(string, StrPartition)
203{
204 const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
205 const char *sep, *suf;
206 size_t pre_len;
207
208 {
209 const char *str = "mat.e-r_ial";
210
211 /* "mat.e-r_ial" -> "mat", '.', "e-r_ial", 3 */
212 pre_len = BLI_str_partition(str, delim, &sep, &suf);
213 EXPECT_EQ(pre_len, 3);
214 EXPECT_EQ(&str[3], sep);
215 EXPECT_STREQ("e-r_ial", suf);
216 }
217
218 /* Corner cases. */
219 {
220 const char *str = ".mate-rial--";
221
222 /* ".mate-rial--" -> "", '.', "mate-rial--", 0 */
223 pre_len = BLI_str_partition(str, delim, &sep, &suf);
224 EXPECT_EQ(pre_len, 0);
225 EXPECT_EQ(&str[0], sep);
226 EXPECT_STREQ("mate-rial--", suf);
227 }
228
229 {
230 const char *str = ".__.--_";
231
232 /* ".__.--_" -> "", '.', "__.--_", 0 */
233 pre_len = BLI_str_partition(str, delim, &sep, &suf);
234 EXPECT_EQ(pre_len, 0);
235 EXPECT_EQ(&str[0], sep);
236 EXPECT_STREQ("__.--_", suf);
237 }
238
239 {
240 const char *str = "";
241
242 /* "" -> "", nullptr, nullptr, 0 */
243 pre_len = BLI_str_partition(str, delim, &sep, &suf);
244 EXPECT_EQ(pre_len, 0);
245 EXPECT_EQ(sep, (void *)nullptr);
246 EXPECT_EQ(suf, (void *)nullptr);
247 }
248
249 {
250 const char *str = "material";
251
252 /* "material" -> "material", nullptr, nullptr, 8 */
253 pre_len = BLI_str_partition(str, delim, &sep, &suf);
254 EXPECT_EQ(pre_len, 8);
255 EXPECT_EQ(sep, (void *)nullptr);
256 EXPECT_EQ(suf, (void *)nullptr);
257 }
258}
259
260/* BLI_str_rpartition */
261TEST(string, StrRPartition)
262{
263 const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
264 const char *sep, *suf;
265 size_t pre_len;
266
267 {
268 const char *str = "mat.e-r_ial";
269
270 /* "mat.e-r_ial" -> "mat.e-r", '_', "ial", 7 */
271 pre_len = BLI_str_rpartition(str, delim, &sep, &suf);
272 EXPECT_EQ(pre_len, 7);
273 EXPECT_EQ(&str[7], sep);
274 EXPECT_STREQ("ial", suf);
275 }
276
277 /* Corner cases. */
278 {
279 const char *str = ".mate-rial--";
280
281 /* ".mate-rial--" -> ".mate-rial-", '-', "", 11 */
282 pre_len = BLI_str_rpartition(str, delim, &sep, &suf);
283 EXPECT_EQ(pre_len, 11);
284 EXPECT_EQ(&str[11], sep);
285 EXPECT_STREQ("", suf);
286 }
287
288 {
289 const char *str = ".__.--_";
290
291 /* ".__.--_" -> ".__.--", '_', "", 6 */
292 pre_len = BLI_str_rpartition(str, delim, &sep, &suf);
293 EXPECT_EQ(pre_len, 6);
294 EXPECT_EQ(&str[6], sep);
295 EXPECT_STREQ("", suf);
296 }
297
298 {
299 const char *str = "";
300
301 /* "" -> "", nullptr, nullptr, 0 */
302 pre_len = BLI_str_rpartition(str, delim, &sep, &suf);
303 EXPECT_EQ(pre_len, 0);
304 EXPECT_EQ(sep, (void *)nullptr);
305 EXPECT_EQ(suf, (void *)nullptr);
306 }
307
308 {
309 const char *str = "material";
310
311 /* "material" -> "material", nullptr, nullptr, 8 */
312 pre_len = BLI_str_rpartition(str, delim, &sep, &suf);
313 EXPECT_EQ(pre_len, 8);
314 EXPECT_EQ(sep, (void *)nullptr);
315 EXPECT_EQ(suf, (void *)nullptr);
316 }
317}
318
319/* BLI_str_partition_ex */
320TEST(string, StrPartitionEx)
321{
322 const char delim[] = {'-', '.', '_', '~', '\\', '\0'};
323 const char *sep, *suf;
324 size_t pre_len;
325
326 /* Only considering 'from_right' cases here. */
327
328 {
329 const char *str = "mat.e-r_ia.l";
330
331 /* "mat.e-r_ia.l" over "mat.e-r" -> "mat.e", '.', "r_ia.l", 3 */
332 pre_len = BLI_str_partition_ex(str, str + 6, delim, &sep, &suf, true);
333 EXPECT_EQ(pre_len, 5);
334 EXPECT_EQ(&str[5], sep);
335 EXPECT_STREQ("r_ia.l", suf);
336 }
337
338 /* Corner cases. */
339 {
340 const char *str = "mate.rial";
341
342 /* "mate.rial" over "mate" -> "mate.rial", nullptr, nullptr, 4 */
343 pre_len = BLI_str_partition_ex(str, str + 4, delim, &sep, &suf, true);
344 EXPECT_EQ(pre_len, 4);
345 EXPECT_EQ(sep, (void *)nullptr);
346 EXPECT_EQ(suf, (void *)nullptr);
347 }
348}
349
350/* BLI_str_partition_utf8 */
351TEST(string, StrPartitionUtf8)
352{
353 const uint delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
354 const char *sep, *suf;
355 size_t pre_len;
356
357 {
358 const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial";
359
360 /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
361 pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf);
362 EXPECT_EQ(pre_len, 2);
363 EXPECT_EQ(&str[2], sep);
364 EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
365 }
366
367 /* Corner cases. */
368 {
369 const char *str = "\xe2\x98\xafmate-rial-\xc3\xb1";
370
371 /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "", '\xe2\x98\xaf', "mate-rial-\xc3\xb1", 0 */
372 pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf);
373 EXPECT_EQ(pre_len, 0);
374 EXPECT_EQ(&str[0], sep);
375 EXPECT_STREQ("mate-rial-\xc3\xb1", suf);
376 }
377
378 {
379 const char *str = "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1";
380
381 /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "", '\xe2\x98\xaf', ".\xc3\xb1_.--\xc3\xb1", 0 */
382 pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf);
383 EXPECT_EQ(pre_len, 0);
384 EXPECT_EQ(&str[0], sep);
385 EXPECT_STREQ(".\xc3\xb1_.--\xc3\xb1", suf);
386 }
387
388 {
389 const char *str = "";
390
391 /* "" -> "", nullptr, nullptr, 0 */
392 pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf);
393 EXPECT_EQ(pre_len, 0);
394 EXPECT_EQ(sep, (void *)nullptr);
395 EXPECT_EQ(suf, (void *)nullptr);
396 }
397
398 {
399 const char *str = "material";
400
401 /* "material" -> "material", nullptr, nullptr, 8 */
402 pre_len = BLI_str_partition_utf8(str, delim, &sep, &suf);
403 EXPECT_EQ(pre_len, 8);
404 EXPECT_EQ(sep, (void *)nullptr);
405 EXPECT_EQ(suf, (void *)nullptr);
406 }
407}
408
409/* BLI_str_rpartition_utf8 */
410TEST(string, StrRPartitionUtf8)
411{
412 const uint delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
413 const char *sep, *suf;
414 size_t pre_len;
415
416 {
417 const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial";
418
419 /* "ma\xc3\xb1te-r\xe2\x98\xafial" -> "mat\xc3\xb1te-r", '\xe2\x98\xaf', "ial", 8 */
420 pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
421 EXPECT_EQ(pre_len, 8);
422 EXPECT_EQ(&str[8], sep);
423 EXPECT_STREQ("ial", suf);
424 }
425
426 /* Corner cases. */
427 {
428 const char *str = "\xe2\x98\xafmate-rial-\xc3\xb1";
429
430 /* "\xe2\x98\xafmate-rial-\xc3\xb1" -> "\xe2\x98\xafmate-rial-", '\xc3\xb1', "", 13 */
431 pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
432 EXPECT_EQ(pre_len, 13);
433 EXPECT_EQ(&str[13], sep);
434 EXPECT_STREQ("", suf);
435 }
436
437 {
438 const char *str = "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1";
439
440 /* "\xe2\x98\xaf.\xc3\xb1_.--\xc3\xb1" -> "\xe2\x98\xaf.\xc3\xb1_.--", '\xc3\xb1', "", 10 */
441 pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
442 EXPECT_EQ(pre_len, 10);
443 EXPECT_EQ(&str[10], sep);
444 EXPECT_STREQ("", suf);
445 }
446
447 {
448 const char *str = "";
449
450 /* "" -> "", nullptr, nullptr, 0 */
451 pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
452 EXPECT_EQ(pre_len, 0);
453 EXPECT_EQ(sep, (void *)nullptr);
454 EXPECT_EQ(suf, (void *)nullptr);
455 }
456
457 {
458 const char *str = "material";
459
460 /* "material" -> "material", nullptr, nullptr, 8 */
461 pre_len = BLI_str_rpartition_utf8(str, delim, &sep, &suf);
462 EXPECT_EQ(pre_len, 8);
463 EXPECT_EQ(sep, (void *)nullptr);
464 EXPECT_EQ(suf, (void *)nullptr);
465 }
466}
467
468/* BLI_str_partition_ex_utf8 */
469TEST(string, StrPartitionExUtf8)
470{
471 const uint delim[] = {'-', '.', '_', 0x00F1 /* n tilde */, 0x262F /* ying-yang */, '\0'};
472 const char *sep, *suf;
473 size_t pre_len;
474
475 /* Only considering 'from_right' cases here. */
476
477 {
478 const char *str = "ma\xc3\xb1te-r\xe2\x98\xafial";
479
480 /* "ma\xc3\xb1te-r\xe2\x98\xafial" over
481 * "ma\xc3\xb1te" -> "ma", '\xc3\xb1', "te-r\xe2\x98\xafial", 2 */
482 pre_len = BLI_str_partition_ex_utf8(str, str + 6, delim, &sep, &suf, true);
483 EXPECT_EQ(pre_len, 2);
484 EXPECT_EQ(&str[2], sep);
485 EXPECT_STREQ("te-r\xe2\x98\xafial", suf);
486 }
487
488 /* Corner cases. */
489 {
490 const char *str = "mate\xe2\x98\xafrial";
491
492 /* "mate\xe2\x98\xafrial" over "mate" -> "mate\xe2\x98\xafrial", nullptr, nullptr, 4 */
493 pre_len = BLI_str_partition_ex_utf8(str, str + 4, delim, &sep, &suf, true);
494 EXPECT_EQ(pre_len, 4);
495 EXPECT_EQ(sep, (void *)nullptr);
496 EXPECT_EQ(suf, (void *)nullptr);
497 }
498}
499
502/* -------------------------------------------------------------------- */
506/* BLI_str_format_int_grouped */
507TEST(string, StrFormatIntGrouped)
508{
509 char number_str[BLI_STR_FORMAT_INT32_GROUPED_SIZE];
510 int number;
511
512 BLI_str_format_int_grouped(number_str, number = 0);
513 EXPECT_STREQ("0", number_str);
514
515 BLI_str_format_int_grouped(number_str, number = 1);
516 EXPECT_STREQ("1", number_str);
517
518 BLI_str_format_int_grouped(number_str, number = -1);
519 EXPECT_STREQ("-1", number_str);
520
521 BLI_str_format_int_grouped(number_str, number = 1000);
522 EXPECT_STREQ("1,000", number_str);
523
524 BLI_str_format_int_grouped(number_str, number = -1000);
525 EXPECT_STREQ("-1,000", number_str);
526
527 BLI_str_format_int_grouped(number_str, number = 999);
528 EXPECT_STREQ("999", number_str);
529
530 BLI_str_format_int_grouped(number_str, number = -999);
531 EXPECT_STREQ("-999", number_str);
532
533 BLI_str_format_int_grouped(number_str, number = 2147483647);
534 EXPECT_STREQ("2,147,483,647", number_str);
535
536 BLI_str_format_int_grouped(number_str, number = -2147483648);
537 EXPECT_STREQ("-2,147,483,648", number_str);
538 /* Ensure the limit is correct. */
539 EXPECT_EQ(sizeof(number_str), strlen(number_str) + 1);
540}
541
542/* BLI_str_format_uint64_grouped */
543TEST(string, StrFormatUint64Grouped)
544{
545 char number_str[BLI_STR_FORMAT_UINT64_GROUPED_SIZE];
546 uint64_t number;
547
548 BLI_str_format_uint64_grouped(number_str, number = 0);
549 EXPECT_STREQ("0", number_str);
550
551 BLI_str_format_uint64_grouped(number_str, number = 1);
552 EXPECT_STREQ("1", number_str);
553
554 BLI_str_format_uint64_grouped(number_str, number = 999);
555 EXPECT_STREQ("999", number_str);
556
557 BLI_str_format_uint64_grouped(number_str, number = 1000);
558 EXPECT_STREQ("1,000", number_str);
559
560 BLI_str_format_uint64_grouped(number_str, number = 18446744073709551615u);
561 EXPECT_STREQ("18,446,744,073,709,551,615", number_str);
562 /* Ensure the limit is correct. */
563 EXPECT_EQ(sizeof(number_str), strlen(number_str) + 1);
564}
565
568/* -------------------------------------------------------------------- */
572/* BLI_str_format_byte_unit */
573TEST(string, StrFormatByteUnits)
574{
576 long long int size;
577
578 /* Base 10 */
579 BLI_str_format_byte_unit(size_str, size = 0, true);
580 EXPECT_STREQ("0 B", size_str);
581 BLI_str_format_byte_unit(size_str, size = -0, true);
582 EXPECT_STREQ("0 B", size_str);
583
584 BLI_str_format_byte_unit(size_str, size = 1, true);
585 EXPECT_STREQ("1 B", size_str);
586 BLI_str_format_byte_unit(size_str, size = -1, true);
587 EXPECT_STREQ("-1 B", size_str);
588
589 BLI_str_format_byte_unit(size_str, size = 1000, true);
590 EXPECT_STREQ("1 KB", size_str);
591 BLI_str_format_byte_unit(size_str, size = -1000, true);
592 EXPECT_STREQ("-1 KB", size_str);
593
594 BLI_str_format_byte_unit(size_str, size = 1024, true);
595 EXPECT_STREQ("1 KB", size_str);
596 BLI_str_format_byte_unit(size_str, size = -1024, true);
597 EXPECT_STREQ("-1 KB", size_str);
598
599 /* LLONG_MAX - largest possible value */
600 BLI_str_format_byte_unit(size_str, size = 9223372036854775807, true);
601 EXPECT_STREQ("9223.372 PB", size_str);
602 BLI_str_format_byte_unit(size_str, size = -9223372036854775807, true);
603 EXPECT_STREQ("-9223.372 PB", size_str);
604
605 /* Base 2 */
606 BLI_str_format_byte_unit(size_str, size = 0, false);
607 EXPECT_STREQ("0 B", size_str);
608 BLI_str_format_byte_unit(size_str, size = -0, false);
609 EXPECT_STREQ("0 B", size_str);
610
611 BLI_str_format_byte_unit(size_str, size = 1, false);
612 EXPECT_STREQ("1 B", size_str);
613 BLI_str_format_byte_unit(size_str, size = -1, false);
614 EXPECT_STREQ("-1 B", size_str);
615
616 BLI_str_format_byte_unit(size_str, size = 1000, false);
617 EXPECT_STREQ("1000 B", size_str);
618 BLI_str_format_byte_unit(size_str, size = -1000, false);
619 EXPECT_STREQ("-1000 B", size_str);
620
621 BLI_str_format_byte_unit(size_str, size = 1024, false);
622 EXPECT_STREQ("1 KiB", size_str);
623 BLI_str_format_byte_unit(size_str, size = -1024, false);
624 EXPECT_STREQ("-1 KiB", size_str);
625
626 /* LLONG_MAX - largest possible value */
627 BLI_str_format_byte_unit(size_str, size = 9223372036854775807, false);
628 EXPECT_STREQ("8192.0 PiB", size_str);
629 BLI_str_format_byte_unit(size_str, size = -9223372036854775807, false);
630 EXPECT_STREQ("-8192.0 PiB", size_str);
631
632 /* Test maximum string length. */
633 BLI_str_format_byte_unit(size_str, size = -9223200000000000000, false);
634 EXPECT_STREQ("-8191.8472 PiB", size_str);
635 /* Ensure the limit is correct. */
636 EXPECT_EQ(sizeof(size_str), strlen(size_str) + 1);
637}
638
641/* -------------------------------------------------------------------- */
645/* BLI_str_format_decimal_unit */
646TEST(string, StrFormatDecimalUnits)
647{
649 int size;
650
651 BLI_str_format_decimal_unit(size_str, size = 0);
652 EXPECT_STREQ("0", size_str);
653 BLI_str_format_decimal_unit(size_str, size = 1);
654 EXPECT_STREQ("1", size_str);
655 BLI_str_format_decimal_unit(size_str, size = 10);
656 EXPECT_STREQ("10", size_str);
657 BLI_str_format_decimal_unit(size_str, size = 15);
658 EXPECT_STREQ("15", size_str);
659 BLI_str_format_decimal_unit(size_str, size = 100);
660 EXPECT_STREQ("100", size_str);
661 BLI_str_format_decimal_unit(size_str, size = 155);
662 EXPECT_STREQ("155", size_str);
663 BLI_str_format_decimal_unit(size_str, size = 1000);
664 EXPECT_STREQ("1.0K", size_str);
665 BLI_str_format_decimal_unit(size_str, size = 1555);
666 EXPECT_STREQ("1.6K", size_str);
667 BLI_str_format_decimal_unit(size_str, size = 10000);
668 EXPECT_STREQ("10.0K", size_str);
669 BLI_str_format_decimal_unit(size_str, size = 15555);
670 EXPECT_STREQ("15.6K", size_str);
671 BLI_str_format_decimal_unit(size_str, size = 100000);
672 EXPECT_STREQ("100K", size_str);
673 BLI_str_format_decimal_unit(size_str, size = 100000);
674 EXPECT_STREQ("100K", size_str);
675 BLI_str_format_decimal_unit(size_str, size = 155555);
676 EXPECT_STREQ("156K", size_str);
677 BLI_str_format_decimal_unit(size_str, size = 1000000);
678 EXPECT_STREQ("1.0M", size_str);
679 BLI_str_format_decimal_unit(size_str, size = 1555555);
680 EXPECT_STREQ("1.6M", size_str);
681 BLI_str_format_decimal_unit(size_str, size = 10000000);
682 EXPECT_STREQ("10.0M", size_str);
683 BLI_str_format_decimal_unit(size_str, size = 15555555);
684 EXPECT_STREQ("15.6M", size_str);
685 BLI_str_format_decimal_unit(size_str, size = 100000000);
686 EXPECT_STREQ("100M", size_str);
687 BLI_str_format_decimal_unit(size_str, size = 155555555);
688 EXPECT_STREQ("156M", size_str);
689 BLI_str_format_decimal_unit(size_str, size = 1000000000);
690 EXPECT_STREQ("1.0B", size_str);
691
692 /* Largest possible value. */
693 BLI_str_format_decimal_unit(size_str, size = INT32_MAX);
694 EXPECT_STREQ("2.1B", size_str);
695
696 BLI_str_format_decimal_unit(size_str, size = -0);
697 EXPECT_STREQ("0", size_str);
698 BLI_str_format_decimal_unit(size_str, size = -1);
699 EXPECT_STREQ("-1", size_str);
700 BLI_str_format_decimal_unit(size_str, size = -10);
701 EXPECT_STREQ("-10", size_str);
702 BLI_str_format_decimal_unit(size_str, size = -15);
703 EXPECT_STREQ("-15", size_str);
704 BLI_str_format_decimal_unit(size_str, size = -100);
705 EXPECT_STREQ("-100", size_str);
706 BLI_str_format_decimal_unit(size_str, size = -155);
707 EXPECT_STREQ("-155", size_str);
708 BLI_str_format_decimal_unit(size_str, size = -1000);
709 EXPECT_STREQ("-1.0K", size_str);
710 BLI_str_format_decimal_unit(size_str, size = -1555);
711 EXPECT_STREQ("-1.6K", size_str);
712 BLI_str_format_decimal_unit(size_str, size = -10000);
713 EXPECT_STREQ("-10.0K", size_str);
714 BLI_str_format_decimal_unit(size_str, size = -15555);
715 EXPECT_STREQ("-15.6K", size_str);
716 BLI_str_format_decimal_unit(size_str, size = -100000);
717 EXPECT_STREQ("-100K", size_str);
718 BLI_str_format_decimal_unit(size_str, size = -155555);
719 EXPECT_STREQ("-156K", size_str);
720 BLI_str_format_decimal_unit(size_str, size = -1000000);
721 EXPECT_STREQ("-1.0M", size_str);
722 BLI_str_format_decimal_unit(size_str, size = -1555555);
723 EXPECT_STREQ("-1.6M", size_str);
724 BLI_str_format_decimal_unit(size_str, size = -10000000);
725 EXPECT_STREQ("-10.0M", size_str);
726 BLI_str_format_decimal_unit(size_str, size = -15555555);
727 EXPECT_STREQ("-15.6M", size_str);
728 BLI_str_format_decimal_unit(size_str, size = -100000000);
729 EXPECT_STREQ("-100M", size_str);
730 BLI_str_format_decimal_unit(size_str, size = -155555555);
731 EXPECT_STREQ("-156M", size_str);
732 BLI_str_format_decimal_unit(size_str, size = -1000000000);
733 EXPECT_STREQ("-1.0B", size_str);
734
735 /* Smallest possible value. */
736 BLI_str_format_decimal_unit(size_str, size = -INT32_MAX);
737 EXPECT_STREQ("-2.1B", size_str);
738}
739
740/* BLI_str_format_integer_unit */
741TEST(string, StrFormatIntegerUnits)
742{
744 int size;
745
746 BLI_str_format_integer_unit(size_str, size = 0);
747 EXPECT_STREQ("0", size_str);
748 BLI_str_format_integer_unit(size_str, size = 1);
749 EXPECT_STREQ("1", size_str);
750 BLI_str_format_integer_unit(size_str, size = 10);
751 EXPECT_STREQ("10", size_str);
752 BLI_str_format_integer_unit(size_str, size = 15);
753 EXPECT_STREQ("15", size_str);
754 BLI_str_format_integer_unit(size_str, size = 100);
755 EXPECT_STREQ("100", size_str);
756 BLI_str_format_integer_unit(size_str, size = 155);
757 EXPECT_STREQ("155", size_str);
758 BLI_str_format_integer_unit(size_str, size = 1000);
759 EXPECT_STREQ("1K", size_str);
760 BLI_str_format_integer_unit(size_str, size = 1555);
761 EXPECT_STREQ("1K", size_str);
762 BLI_str_format_integer_unit(size_str, size = 10000);
763 EXPECT_STREQ("10K", size_str);
764 BLI_str_format_integer_unit(size_str, size = 15555);
765 EXPECT_STREQ("15K", size_str);
766 BLI_str_format_integer_unit(size_str, size = 100000);
767 EXPECT_STREQ(".1M", size_str);
768 BLI_str_format_integer_unit(size_str, size = 155555);
769 EXPECT_STREQ(".1M", size_str);
770 BLI_str_format_integer_unit(size_str, size = 1000000);
771 EXPECT_STREQ("1M", size_str);
772 BLI_str_format_integer_unit(size_str, size = 1555555);
773 EXPECT_STREQ("1M", size_str);
774 BLI_str_format_integer_unit(size_str, size = 2555555);
775 EXPECT_STREQ("2M", size_str);
776 BLI_str_format_integer_unit(size_str, size = 10000000);
777 EXPECT_STREQ("10M", size_str);
778 BLI_str_format_integer_unit(size_str, size = 15555555);
779 EXPECT_STREQ("15M", size_str);
780 BLI_str_format_integer_unit(size_str, size = 100000000);
781 EXPECT_STREQ(".1B", size_str);
782 BLI_str_format_integer_unit(size_str, size = 155555555);
783 EXPECT_STREQ(".1B", size_str);
784 BLI_str_format_integer_unit(size_str, size = 255555555);
785 EXPECT_STREQ(".2B", size_str);
786 BLI_str_format_integer_unit(size_str, size = 1000000000);
787 EXPECT_STREQ("1B", size_str);
788
789 /* Largest possible value. */
790 BLI_str_format_integer_unit(size_str, size = INT32_MAX);
791 EXPECT_STREQ("2B", size_str);
792
793 BLI_str_format_integer_unit(size_str, size = -0);
794 EXPECT_STREQ("0", size_str);
795 BLI_str_format_integer_unit(size_str, size = -1);
796 EXPECT_STREQ("-1", size_str);
797 BLI_str_format_integer_unit(size_str, size = -10);
798 EXPECT_STREQ("-10", size_str);
799 BLI_str_format_integer_unit(size_str, size = -15);
800 EXPECT_STREQ("-15", size_str);
801 BLI_str_format_integer_unit(size_str, size = -100);
802 EXPECT_STREQ("-100", size_str);
803 BLI_str_format_integer_unit(size_str, size = -155);
804 EXPECT_STREQ("-155", size_str);
805 BLI_str_format_integer_unit(size_str, size = -1000);
806 EXPECT_STREQ("-1K", size_str);
807 BLI_str_format_integer_unit(size_str, size = -1555);
808 EXPECT_STREQ("-1K", size_str);
809 BLI_str_format_integer_unit(size_str, size = -10000);
810 EXPECT_STREQ("-10K", size_str);
811 BLI_str_format_integer_unit(size_str, size = -15555);
812 EXPECT_STREQ("-15K", size_str);
813 BLI_str_format_integer_unit(size_str, size = -100000);
814 EXPECT_STREQ("-.1M", size_str);
815 BLI_str_format_integer_unit(size_str, size = -155555);
816 EXPECT_STREQ("-.1M", size_str);
817 BLI_str_format_integer_unit(size_str, size = -1000000);
818 EXPECT_STREQ("-1M", size_str);
819 BLI_str_format_integer_unit(size_str, size = -1555555);
820 EXPECT_STREQ("-1M", size_str);
821 BLI_str_format_integer_unit(size_str, size = -10000000);
822 EXPECT_STREQ("-10M", size_str);
823 BLI_str_format_integer_unit(size_str, size = -15555555);
824 EXPECT_STREQ("-15M", size_str);
825 BLI_str_format_integer_unit(size_str, size = -100000000);
826 EXPECT_STREQ("-.1B", size_str);
827 BLI_str_format_integer_unit(size_str, size = -155555555);
828 EXPECT_STREQ("-.1B", size_str);
829 BLI_str_format_integer_unit(size_str, size = -1000000000);
830 EXPECT_STREQ("-1B", size_str);
831
832 /* Smallest possible value. */
833 BLI_str_format_integer_unit(size_str, size = -INT32_MAX);
834 EXPECT_STREQ("-2B", size_str);
835}
836
839/* -------------------------------------------------------------------- */
843TEST(string, StringNLen)
844{
845 EXPECT_EQ(0, BLI_strnlen("", 0));
846 EXPECT_EQ(0, BLI_strnlen("", 1));
847 EXPECT_EQ(0, BLI_strnlen("", 100));
848
849 EXPECT_EQ(0, BLI_strnlen("x", 0));
850 EXPECT_EQ(1, BLI_strnlen("x", 1));
851 EXPECT_EQ(1, BLI_strnlen("x", 100));
852
853 /* `ü` is `\xc3\xbc`. */
854 EXPECT_EQ(2, BLI_strnlen("ü", 100));
855
856 EXPECT_EQ(0, BLI_strnlen("this is a longer string", 0));
857 EXPECT_EQ(1, BLI_strnlen("this is a longer string", 1));
858 EXPECT_EQ(5, BLI_strnlen("this is a longer string", 5));
859 EXPECT_EQ(47, BLI_strnlen("This string writes about an agent without name.", 100));
860}
861
864/* -------------------------------------------------------------------- */
868#define BUFFER_SIZE 128
869
870static void string_join_array_test_truncate(const char *strings[],
871 int strings_num,
872 char buffer[BUFFER_SIZE])
873{
874 const int buffer_len = BLI_string_join_array(buffer, BUFFER_SIZE, strings, strings_num);
875
876 { /* Ensure the allocated version is the same. */
877 char *buffer_alloc = BLI_string_join_arrayN(strings, strings_num);
878 EXPECT_STREQ(buffer_alloc, buffer);
880 }
881
882 for (int dst_size = buffer_len + 1; dst_size > 0; dst_size--) {
883 char dst_tmp[BUFFER_SIZE];
884 int dst_tmp_len = BLI_string_join_array(dst_tmp, dst_size, strings, strings_num);
885 EXPECT_EQ(dst_tmp_len + 1, dst_size);
886 EXPECT_EQ(strncmp(dst_tmp, buffer, dst_tmp_len), 0);
887 }
888}
889
890static void string_join_array_with_sep_char_test_truncate(const char *strings[],
891 int strings_num,
892 char buffer[BUFFER_SIZE])
893{
894 const int buffer_len = BLI_string_join_array_by_sep_char(
895 buffer, BUFFER_SIZE, '|', strings, strings_num);
896
897 { /* Ensure the allocated version is the same. */
898 char *buffer_alloc = BLI_string_join_array_by_sep_charN('|', strings, strings_num);
899 EXPECT_STREQ(buffer_alloc, buffer);
901 }
902
903 for (int dst_size = buffer_len + 1; dst_size > 0; dst_size--) {
904 char dst_tmp[BUFFER_SIZE];
905 int dst_tmp_len = BLI_string_join_array_by_sep_char(
906 dst_tmp, dst_size, '|', strings, strings_num);
907 EXPECT_EQ(dst_tmp_len + 1, dst_size);
908 EXPECT_EQ(strncmp(dst_tmp, buffer, dst_tmp_len), 0);
909 }
910}
911
912TEST(string, StrJoin_Truncate)
913{
914 char buffer[BUFFER_SIZE];
915 { /* Multiple single char words. */
916 const char *strings[] = {"a", "b", "c", "d", "e", "f"};
917 string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
918 EXPECT_STREQ(buffer, "abcdef");
920 EXPECT_STREQ(buffer, "a|b|c|d|e|f");
921 }
922 { /* Multiple char pair words. */
923 const char *strings[] = {"aa", "bb", "cc", "dd", "ee", "ff"};
924 string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
925 EXPECT_STREQ(buffer, "aabbccddeeff");
927 EXPECT_STREQ(buffer, "aa|bb|cc|dd|ee|ff");
928 }
929 { /* Multiple empty words. */
930 const char *strings[] = {"", "", "", "", "", ""};
931 string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
932 EXPECT_STREQ(buffer, "");
934 EXPECT_STREQ(buffer, "|||||");
935 }
936 { /* Single word. */
937 const char *strings[] = {"test"};
938 string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
939 EXPECT_STREQ(buffer, "test");
941 EXPECT_STREQ(buffer, "test");
942 }
943 { /* Empty item. */
944 const char *strings[] = {""};
945 string_join_array_test_truncate(strings, ARRAY_SIZE(strings), buffer);
946 EXPECT_STREQ(buffer, "");
948 EXPECT_STREQ(buffer, "");
949 }
950 { /* Empty array. */
951 const char *strings[] = {"a"};
952 string_join_array_test_truncate(strings, 0, buffer);
953 EXPECT_STREQ(buffer, "");
955 EXPECT_STREQ(buffer, "");
956 }
957}
958
959#undef BUFFER_SIZE
960
963/* -------------------------------------------------------------------- */
967struct WordInfo {
968 WordInfo() = default;
969 WordInfo(int start, int end) : start(start), end(end) {}
970 bool operator==(const WordInfo &other) const
971 {
972 return start == other.start && end == other.end;
973 }
974 int start, end;
975};
976static std::ostream &operator<<(std::ostream &os, const WordInfo &word_info)
977{
978 os << "start: " << word_info.start << ", end: " << word_info.end;
979 return os;
980}
981
982class StringFindSplitWords : public testing::Test {
983 protected:
985
986 /* If max_words is -1 it will be initialized from the number of expected
987 * words +1. This way there is no need to pass an explicit number of words,
988 * but is also making it possible to catch situation when too many words
989 * are being returned. */
990 void testStringFindSplitWords(const string &str,
991 const size_t max_length,
992 initializer_list<WordInfo> expected_words_info_init,
993 int max_words = -1)
994 {
995 const vector<WordInfo> expected_words_info = expected_words_info_init;
996 if (max_words != -1) {
997 CHECK_LE(max_words, expected_words_info.size() - 1);
998 }
999 /* Since number of word info is used here, this makes it so we allow one
1000 * extra word to be collected from the input. This allows to catch possible
1001 * issues with word splitting not doing a correct thing. */
1002 const int effective_max_words = (max_words == -1) ? expected_words_info.size() : max_words;
1003 /* One extra element for the {-1, -1}. */
1004 vector<WordInfo> actual_word_info(effective_max_words + 1, WordInfo(-1, -1));
1005 const int actual_word_num = BLI_string_find_split_words(
1006 str.c_str(),
1007 max_length,
1008 ' ',
1009 reinterpret_cast<int(*)[2]>(actual_word_info.data()),
1010 effective_max_words);
1011 /* Schrink actual array to an actual number of words, so we can compare
1012 * vectors as-is. */
1013 EXPECT_LE(actual_word_num, actual_word_info.size() - 1);
1014 actual_word_info.resize(actual_word_num + 1);
1015 /* Perform actual comparison. */
1016 EXPECT_EQ_VECTOR(actual_word_info, expected_words_info);
1017 }
1018
1019 void testStringFindSplitWords(const string &str,
1020 initializer_list<WordInfo> expected_words_info_init)
1021 {
1022 testStringFindSplitWords(str, str.length(), expected_words_info_init);
1023 }
1024};
1025
1026/* BLI_string_find_split_words */
1028{
1029 testStringFindSplitWords("t", {{0, 1}, {-1, -1}});
1030 testStringFindSplitWords("test", {{0, 4}, {-1, -1}});
1031}
1033{
1034 testStringFindSplitWords("f t w", {{0, 1}, {2, 1}, {4, 1}, {-1, -1}});
1035 testStringFindSplitWords("find three words", {{0, 4}, {5, 5}, {11, 5}, {-1, -1}});
1036}
1038{
1039 testStringFindSplitWords("# ## ### ####", {{0, 1}, {2, 2}, {5, 3}, {9, 4}, {-1, -1}});
1040 testStringFindSplitWords("# # # #", {{0, 1}, {3, 1}, {7, 1}, {12, 1}, {-1, -1}});
1041}
1043{
1044 testStringFindSplitWords(" t", {{3, 1}, {-1, -1}});
1045 testStringFindSplitWords(" test", {{3, 4}, {-1, -1}});
1046}
1048{
1049 testStringFindSplitWords("t ", {{0, 1}, {-1, -1}});
1050 testStringFindSplitWords("test ", {{0, 4}, {-1, -1}});
1051}
1052TEST_F(StringFindSplitWords, Trailing_LeftRight)
1053{
1054 testStringFindSplitWords(" surrounding space test 123 ",
1055 {{3, 11}, {15, 5}, {21, 4}, {28, 3}, {-1, -1}});
1056}
1058{
1059 testStringFindSplitWords("", {{-1, -1}});
1060}
1062{
1063 testStringFindSplitWords(" ", {{-1, -1}});
1064 testStringFindSplitWords(" ", {{-1, -1}});
1065}
1067{
1068 const string words = "too many chars";
1069 const int words_len = words.length();
1070 testStringFindSplitWords(words, words_len, {{0, 3}, {4, 4}, {9, 5}, {-1, -1}}, 3);
1071 testStringFindSplitWords(words, words_len, {{0, 3}, {4, 4}, {-1, -1}}, 2);
1072 testStringFindSplitWords(words, words_len, {{0, 3}, {-1, -1}}, 1);
1073 testStringFindSplitWords(words, words_len, {{-1, -1}}, 0);
1074}
1076{
1077 const string words = "too many chars";
1078 const int words_len = words.length();
1079 testStringFindSplitWords(words, words_len, {{0, 3}, {4, 4}, {9, 5}, {-1, -1}});
1080 testStringFindSplitWords(words, words_len - 1, {{0, 3}, {4, 4}, {9, 4}, {-1, -1}});
1081 testStringFindSplitWords(words, words_len - 5, {{0, 3}, {4, 4}, {-1, -1}});
1082 testStringFindSplitWords(words, 1, {{0, 1}, {-1, -1}});
1083 testStringFindSplitWords(words, 0, {{-1, -1}});
1084}
1085
1088/* -------------------------------------------------------------------- */
1092/* #BLI_string_elem_split_by_delim */
1093
1094TEST(string, StringElemEmpty)
1095{
1096 EXPECT_FALSE(BLI_string_elem_split_by_delim("A", ':', ""));
1097
1098 EXPECT_TRUE(BLI_string_elem_split_by_delim("", ':', ""));
1099 EXPECT_TRUE(BLI_string_elem_split_by_delim(":", ':', ""));
1100 EXPECT_TRUE(BLI_string_elem_split_by_delim("::", ':', ""));
1101 EXPECT_TRUE(BLI_string_elem_split_by_delim("A:", ':', ""));
1102 EXPECT_TRUE(BLI_string_elem_split_by_delim(":A", ':', ""));
1103}
1104
1105TEST(string, StringElemSingle)
1106{
1107 EXPECT_TRUE(BLI_string_elem_split_by_delim("A", ':', "A"));
1108 EXPECT_FALSE(BLI_string_elem_split_by_delim("A", ':', "B"));
1109
1110 EXPECT_TRUE(BLI_string_elem_split_by_delim("B", 'A', "B"));
1111 EXPECT_FALSE(BLI_string_elem_split_by_delim("A", 'A', "A"));
1112}
1113
1114TEST(string, StringElemComplex)
1115{
1116 EXPECT_TRUE(BLI_string_elem_split_by_delim("TEST", ':', "TEST"));
1117
1118 EXPECT_TRUE(BLI_string_elem_split_by_delim(":TEST", ':', "TEST"));
1119 EXPECT_TRUE(BLI_string_elem_split_by_delim("TEST:", ':', "TEST"));
1120 EXPECT_TRUE(BLI_string_elem_split_by_delim(":TEST:", ':', "TEST"));
1121
1122 EXPECT_TRUE(BLI_string_elem_split_by_delim("::TEST", ':', "TEST"));
1123 EXPECT_TRUE(BLI_string_elem_split_by_delim("TEST::", ':', "TEST"));
1124 EXPECT_TRUE(BLI_string_elem_split_by_delim("::TEST::", ':', "TEST"));
1125
1126 EXPECT_FALSE(BLI_string_elem_split_by_delim(":TEST ", ':', "TEST"));
1127 EXPECT_FALSE(BLI_string_elem_split_by_delim(" TEST:", ':', "TEST"));
1128 EXPECT_FALSE(BLI_string_elem_split_by_delim(": TEST :", ':', "TEST"));
1129
1130 EXPECT_TRUE(BLI_string_elem_split_by_delim("A:B:TEST", ':', "TEST"));
1131 EXPECT_TRUE(BLI_string_elem_split_by_delim("TEST:A:B", ':', "TEST"));
1132 EXPECT_TRUE(BLI_string_elem_split_by_delim("A:TEST:B", ':', "TEST"));
1133 EXPECT_TRUE(BLI_string_elem_split_by_delim(":A:TEST:B:", ':', "TEST"));
1134}
1135
1138/* -------------------------------------------------------------------- */
1142/* BLI_strncasestr */
1143TEST(string, StringStrncasestr)
1144{
1145 const char *str_test0 = "search here";
1146 const char *res;
1147
1148 res = BLI_strncasestr(str_test0, "", 0);
1149 EXPECT_EQ(res, str_test0);
1150
1151 res = BLI_strncasestr(str_test0, " ", 1);
1152 EXPECT_EQ(res, str_test0 + 6);
1153
1154 res = BLI_strncasestr(str_test0, "her", 3);
1155 EXPECT_EQ(res, str_test0 + 7);
1156
1157 res = BLI_strncasestr(str_test0, "ARCh", 4);
1158 EXPECT_EQ(res, str_test0 + 2);
1159
1160 res = BLI_strncasestr(str_test0, "earcq", 4);
1161 EXPECT_EQ(res, str_test0 + 1);
1162
1163 res = BLI_strncasestr(str_test0, "not there", 9);
1164 EXPECT_EQ(res, (void *)nullptr);
1165}
1166
1169/* -------------------------------------------------------------------- */
1173/* BLI_string_max_possible_word_count */
1182
1185/* -------------------------------------------------------------------- */
1189/* BLI_string_is_decimal */
1190TEST(string, StrIsDecimal)
1191{
1192 EXPECT_FALSE(BLI_string_is_decimal(""));
1193 EXPECT_FALSE(BLI_string_is_decimal("je moeder"));
1194 EXPECT_FALSE(BLI_string_is_decimal("je møder"));
1195 EXPECT_FALSE(BLI_string_is_decimal("Agent 327"));
1196 EXPECT_FALSE(BLI_string_is_decimal("Agent\000327"));
1197 EXPECT_FALSE(BLI_string_is_decimal("\000327"));
1198 EXPECT_FALSE(BLI_string_is_decimal("0x16"));
1199 EXPECT_FALSE(BLI_string_is_decimal("16.4"));
1200 EXPECT_FALSE(BLI_string_is_decimal("-1"));
1201
1202 EXPECT_TRUE(BLI_string_is_decimal("0"));
1203 EXPECT_TRUE(BLI_string_is_decimal("1"));
1204 EXPECT_TRUE(BLI_string_is_decimal("001"));
1205 EXPECT_TRUE(BLI_string_is_decimal("11342908713948713498745980171334059871345098713405981734"));
1206}
1207
1210/* -------------------------------------------------------------------- */
1214/* BLI_strcasecmp_natural */
1215class StringCasecmpNatural : public testing::Test {
1216 protected:
1218
1219 using CompareWordsArray = vector<std::array<const char *, 2>>;
1220
1222 {
1223 for (const auto &item : items) {
1224 int res = BLI_strcasecmp_natural(item[0], item[1]);
1225 EXPECT_EQ(res, 0);
1226 }
1227 }
1229 {
1230 for (const auto &item : items) {
1231 int res = BLI_strcasecmp_natural(item[0], item[1]);
1232 EXPECT_LT(res, 0);
1233 }
1234 }
1236 {
1237 for (const auto &item : items) {
1238 int res = BLI_strcasecmp_natural(item[0], item[1]);
1239 EXPECT_GT(res, 0);
1240 }
1241 }
1242
1244 {
1245 CompareWordsArray ret_array;
1246
1247 /* E.g. {{"a", "b"}, {"ab", "cd"}} becomes {{"b", "a"}, {"cd", "ab"}} */
1248
1249 ret_array.reserve(items.size());
1250 for (const auto &item : items) {
1251 ret_array.push_back({item[1], item[0]});
1252 }
1253
1254 return ret_array;
1255 }
1256};
1257
1260/* -------------------------------------------------------------------- */
1265{
1266 const CompareWordsArray equal{
1267 {"", ""},
1268 };
1269 const CompareWordsArray negative{
1270 {"", "a"},
1271 {"", "A"},
1272 };
1273 CompareWordsArray positive = copyWithSwappedWords(negative);
1274
1275 testReturnsZeroForAll(equal);
1276 testReturnsLessThanZeroForAll(negative);
1277 testReturnsMoreThanZeroForAll(positive);
1278}
1279
1281{
1282 const CompareWordsArray equal{
1283 {" ", " "},
1284 {" a", " a"},
1285 {" a ", " a "},
1286 };
1287 const CompareWordsArray negative{
1288 {"", " "},
1289 {"", " a"},
1290 {"", " a "},
1291 {" ", " a"},
1292 };
1293 CompareWordsArray positive = copyWithSwappedWords(negative);
1294
1295 testReturnsZeroForAll(equal);
1296 testReturnsLessThanZeroForAll(negative);
1297 testReturnsMoreThanZeroForAll(positive);
1298}
1299
1300TEST_F(StringCasecmpNatural, TextOnlyLowerCase)
1301{
1302 const CompareWordsArray equal{
1303 {"a", "a"},
1304 {"aa", "aa"},
1305 {"ab", "ab"},
1306 {"ba", "ba"},
1307 {"je møder", "je møder"},
1308 };
1309 const CompareWordsArray negative{
1310 {"a", "b"},
1311 {"a", "aa"},
1312 {"a", "ab"},
1313 {"aa", "b"},
1314 {"je møda", "je møder"},
1315 };
1316 CompareWordsArray positive = copyWithSwappedWords(negative);
1317
1318 testReturnsZeroForAll(equal);
1319 testReturnsLessThanZeroForAll(negative);
1320 testReturnsMoreThanZeroForAll(positive);
1321}
1322
1324{
1325 const CompareWordsArray equal{
1326 {"A", "A"},
1327 {"AA", "AA"},
1328 {"AB", "AB"},
1329 {"Ab", "Ab"},
1330 {"aB", "aB"},
1331 };
1332 const CompareWordsArray negative{
1333 {"A", "a"},
1334 {"A", "B"},
1335 {"A", "b"},
1336 {"a", "B"},
1337 {"AA", "aA"},
1338 {"AA", "aA"},
1339 {"Ab", "ab"},
1340 {"AB", "Ab"},
1341 /* Different lengths */
1342 {"A", "ab"},
1343 {"Aa", "b"},
1344 {"aA", "b"},
1345 {"AA", "b"},
1346 {"A", "Ab"},
1347 {"A", "aB"},
1348 {"Aa", "B"},
1349 {"aA", "B"},
1350 {"AA", "B"},
1351 };
1352 CompareWordsArray positive = copyWithSwappedWords(negative);
1353
1354 testReturnsZeroForAll(equal);
1355 testReturnsLessThanZeroForAll(negative);
1356 testReturnsMoreThanZeroForAll(positive);
1357}
1358
1360{
1361 const CompareWordsArray equal{
1362 {".", "."},
1363 {". ", ". "},
1364 {" .", " ."},
1365 {" . ", " . "},
1366 };
1367 const CompareWordsArray negative{
1368 {".", ". "},
1369 {" .", " . "},
1370 {"foo.bar", "foo 1.bar"},
1371 };
1372 CompareWordsArray positive = copyWithSwappedWords(negative);
1373
1374 testReturnsZeroForAll(equal);
1375 testReturnsLessThanZeroForAll(negative);
1376 testReturnsMoreThanZeroForAll(positive);
1377}
1378
1380{
1381 const CompareWordsArray equal{
1382 {"0", "0"},
1383 {"0001", "0001"},
1384 {"42", "42"},
1385 {"0042", "0042"},
1386 };
1387 const CompareWordsArray negative{
1388 /* If numeric values are equal, number of leading zeros is used as tiebreaker. */
1389 {"1", "0001"},
1390 {"01", "001"},
1391 {"0042", "0043"},
1392 {"0042", "43"},
1393 };
1394 const CompareWordsArray positive = copyWithSwappedWords(negative);
1395
1396 testReturnsZeroForAll(equal);
1397 testReturnsLessThanZeroForAll(negative);
1398 testReturnsMoreThanZeroForAll(positive);
1399}
1400
1402{
1403 const CompareWordsArray equal{
1404 {"00je møder1", "00je møder1"},
1405 {".0 ", ".0 "},
1406 {" 1.", " 1."},
1407 {" .0 ", " .0 "},
1408 };
1409 const CompareWordsArray negative{
1410 {"00je møder0", "00je møder1"},
1411 {"05je møder0", "06je møder1"},
1412 {"Cube", "Cube.001"},
1413 {"Cube.001", "Cube.002"},
1414 {"CUbe.001", "Cube.002"},
1415 {"CUbe.002", "Cube.002"},
1416 };
1417 const CompareWordsArray positive = copyWithSwappedWords(negative);
1418
1419 testReturnsZeroForAll(equal);
1420 testReturnsLessThanZeroForAll(negative);
1421 testReturnsMoreThanZeroForAll(positive);
1422}
1423
1426/* -------------------------------------------------------------------- */
1432class StringEscape : public testing::Test {
1433 protected:
1434 StringEscape() = default;
1435
1436 using CompareWordsArray = vector<std::array<const char *, 2>>;
1437
1439 {
1440 size_t dst_test_len;
1441 char dst_test[64]; /* Must be big enough for all input. */
1442 for (const auto &item : items) {
1443 /* Validate the static size is big enough (test the test itself). */
1444 EXPECT_LT((strlen(item[0]) * 2) + 1, sizeof(dst_test));
1445 /* Escape the string. */
1446 dst_test_len = BLI_str_escape(dst_test, item[0], sizeof(dst_test));
1447 EXPECT_STREQ(dst_test, item[1]);
1448 EXPECT_EQ(dst_test_len, strlen(dst_test));
1449 /* Escape back. */
1450 dst_test_len = BLI_str_unescape(dst_test, item[1], strlen(item[1]));
1451 EXPECT_STREQ(dst_test, item[0]);
1452 EXPECT_EQ(dst_test_len, strlen(dst_test));
1453 }
1454 }
1455};
1456
1458{
1459 /* NOTE: clang-tidy `modernize-raw-string-literal` is disabled as it causes errors with MSVC.
1460 * TODO: investigate resolving with `/Zc:preprocessor` flag. */
1461
1462 const CompareWordsArray equal{
1463 {"", ""},
1464 {"/", "/"},
1465 {"'", "'"},
1466 {"?", "?"},
1467 };
1468
1469 const CompareWordsArray escaped{
1470 {"\\", "\\\\"},
1471 {"A\\", "A\\\\"},
1472 {"\\A", "\\\\A"},
1473 {"A\\B", "A\\\\B"},
1474 {"?", "?"},
1475 /* NOLINTNEXTLINE: modernize-raw-string-literal. */
1476 {"\"\\", "\\\"\\\\"},
1477 /* NOLINTNEXTLINE: modernize-raw-string-literal. */
1478 {"\\\"", "\\\\\\\""},
1479 /* NOLINTNEXTLINE: modernize-raw-string-literal. */
1480 {"\"\\\"", "\\\"\\\\\\\""},
1481
1482 /* NOLINTNEXTLINE: modernize-raw-string-literal. */
1483 {"\"\"\"", "\\\"\\\"\\\""},
1484 /* NOLINTNEXTLINE: modernize-raw-string-literal. */
1485 {"\\\\\\", "\\\\\\\\\\\\"},
1486 };
1487
1488 testEscapeWords(equal);
1489 testEscapeWords(escaped);
1490}
1491
1493{
1494 const CompareWordsArray escaped{
1495 {"\n", "\\n"},
1496 {"\r", "\\r"},
1497 {"\t", "\\t"},
1498 {"\a", "\\a"},
1499 {"\b", "\\b"},
1500 {"\f", "\\f"},
1501 {"A\n", "A\\n"},
1502 {"\nA", "\\nA"},
1503 /* NOLINTNEXTLINE: modernize-raw-string-literal. */
1504 {"\n\r\t\a\b\f", "\\n\\r\\t\\a\\b\\f"},
1505 /* NOLINTNEXTLINE: modernize-raw-string-literal. */
1506 {"\n_\r_\t_\a_\b_\f", "\\n_\\r_\\t_\\a_\\b_\\f"},
1507 /* NOLINTNEXTLINE: modernize-raw-string-literal. */
1508 {"\n\\\r\\\t\\\a\\\b\\\f", "\\n\\\\\\r\\\\\\t\\\\\\a\\\\\\b\\\\\\f"},
1509 };
1510
1511 testEscapeWords(escaped);
1512}
1513
1516TEST(BLI_string, bounded_strcpy)
1517{
1518 {
1519 char str[8];
1520 STRNCPY(str, "Hello");
1521 EXPECT_STREQ(str, "Hello");
1522 }
1523
1524 {
1525 char str[8];
1526 STRNCPY(str, "Hello, World!");
1527 EXPECT_STREQ(str, "Hello, ");
1528 }
1529}
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
size_t BLI_str_format_int_grouped(char dst[BLI_STR_FORMAT_INT32_GROUPED_SIZE], int num) ATTR_NONNULL(1)
Definition string.c:1168
int bool bool bool size_t BLI_str_partition(const char *str, const char delim[], const char **sep, const char **suf) ATTR_NONNULL(1
int bool bool bool size_t size_t size_t int BLI_string_max_possible_word_count(int str_len) ATTR_WARN_UNUSED_RESULT
Definition string.c:569
#define STRNCPY(dst, src)
Definition BLI_string.h:593
size_t size_t size_t BLI_str_unescape(char *__restrict dst, const char *__restrict src, size_t src_maxncpy) ATTR_NONNULL(1
#define BLI_STR_FORMAT_INT64_BYTE_UNIT_SIZE
Definition BLI_string.h:28
int char char int int int int size_t BLI_strnlen(const char *str, size_t maxlen) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition string.c:909
#define BLI_STR_FORMAT_INT32_DECIMAL_UNIT_SIZE
Definition BLI_string.h:34
#define BLI_STR_FORMAT_INT32_GROUPED_SIZE
Definition BLI_string.h:25
void BLI_str_format_byte_unit(char dst[BLI_STR_FORMAT_INT64_BYTE_UNIT_SIZE], long long int bytes, bool base_10) ATTR_NONNULL(1)
Definition string.c:1192
int bool bool bool size_t size_t BLI_str_rpartition(const char *str, const char delim[], const char **sep, const char **suf) ATTR_NONNULL(1
#define BLI_STR_FORMAT_INT32_INTEGER_UNIT_SIZE
Definition BLI_string.h:37
#define BLI_STR_FORMAT_UINT64_GROUPED_SIZE
Definition BLI_string.h:22
void BLI_str_format_integer_unit(char dst[BLI_STR_FORMAT_INT32_INTEGER_UNIT_SIZE], int number_to_format) ATTR_NONNULL(1)
Definition string.c:1279
int char char * BLI_strncasestr(const char *s, const char *find, size_t len) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
int bool bool bool size_t size_t size_t BLI_str_partition_ex(const char *str, const char *end, const char delim[], const char **sep, const char **suf, bool from_right) ATTR_NONNULL(1
void BLI_str_format_decimal_unit(char dst[BLI_STR_FORMAT_INT32_DECIMAL_UNIT_SIZE], int number_to_format) ATTR_NONNULL(1)
Definition string.c:1255
int char char int int int BLI_strcasecmp_natural(const char *s1, const char *s2) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
size_t BLI_str_format_uint64_grouped(char dst[BLI_STR_FORMAT_UINT64_GROUPED_SIZE], uint64_t num) ATTR_NONNULL(1)
Definition string.c:1180
bool bool int bool BLI_string_elem_split_by_delim(const char *haystack, const char delim, const char *needle) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
bool bool int BLI_string_find_split_words(const char *str, size_t str_maxlen, char delim, int r_words[][2], int words_max) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
size_t BLI_str_escape(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
static void string_join_array_with_sep_char_test_truncate(const char *strings[], int strings_num, char buffer[BUFFER_SIZE])
#define STRNCPY_UTF8_TRUNCATE(byte_size,...)
#define STR_N_CAT(dst_init, dst_size, src, result_expect)
#define BUFFER_SIZE
#define STRNCPY_UTF8_ASCII_TRUNCATE(maxncpy,...)
#define STRNCPY_UTF8_ASCII(...)
TEST_F(StringFindSplitWords, Simple)
#define STRNCPY_UTF8_TERMINATE_EARLY(byte_size,...)
static std::ostream & operator<<(std::ostream &os, const WordInfo &word_info)
TEST(string, StrCopyUTF8_ASCII)
static void string_join_array_test_truncate(const char *strings[], int strings_num, char buffer[BUFFER_SIZE])
#define STR_REPLACE_RANGE(src, size, beg, end, dst, result_expect)
size_t size_t BLI_str_rpartition_utf8(const char *str, const unsigned int delim[], const char **r_sep, const char **r_suf) ATTR_NONNULL(1
size_t BLI_str_partition_utf8(const char *str, const unsigned int delim[], const char **r_sep, const char **r_suf) ATTR_NONNULL(1
size_t size_t size_t BLI_str_partition_ex_utf8(const char *str, const char *end, const unsigned int delim[], const char **r_sep, const char **r_suf, bool from_right) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1
size_t BLI_string_join_array_by_sep_char(char *result, size_t result_maxncpy, char sep, const char *strings[], uint strings_num) ATTR_NONNULL()
char * BLI_string_join_arrayN(const char *strings[], uint strings_num) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
char * BLI_string_join_array_by_sep_charN(char sep, const char *strings[], uint strings_num) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
size_t BLI_string_join_array(char *result, size_t result_maxncpy, const char *strings[], uint strings_num) ATTR_NONNULL()
size_t bool BLI_string_is_decimal(const char *string) ATTR_NONNULL(1)
unsigned int uint
#define ARRAY_SIZE(arr)
Read Guarded memory(de)allocation.
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static void * buffer_alloc(const BLI_Buffer *buffer, const size_t len)
Definition buffer.c:41
void testReturnsMoreThanZeroForAll(const CompareWordsArray &items)
void testReturnsZeroForAll(const CompareWordsArray &items)
void testReturnsLessThanZeroForAll(const CompareWordsArray &items)
vector< std::array< const char *, 2 > > CompareWordsArray
StringCasecmpNatural()=default
CompareWordsArray copyWithSwappedWords(const CompareWordsArray &items)
vector< std::array< const char *, 2 > > CompareWordsArray
StringEscape()=default
void testEscapeWords(const CompareWordsArray &items)
void testStringFindSplitWords(const string &str, initializer_list< WordInfo > expected_words_info_init)
StringFindSplitWords()=default
void testStringFindSplitWords(const string &str, const size_t max_length, initializer_list< WordInfo > expected_words_info_init, int max_words=-1)
#define str(s)
#define CHECK_LE(a, b)
Definition log.h:49
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
#define INT32_MAX
Definition stdint.h:137
unsigned __int64 uint64_t
Definition stdint.h:90
WordInfo()=default
bool operator==(const WordInfo &other) const
WordInfo(int start, int end)