4 * Copyright (C) 2017-2022 by Werner Lemberg.
6 * This file is part of the ttfautohint library, and may only be used,
7 * modified, and distributed under the terms given in `COPYING'. By
8 * continuing to use, modify, or distribute this file you indicate that you
9 * have read `COPYING' and understand and accept it fully.
11 * The file `COPYING' mentioned in the previous paragraph is distributed
12 * with the ttfautohint library.
20 * -o numberset-test numberset-test.c numberset.c sds.c
22 * after configuration. The resulting binary aborts with an assertion
23 * message in case of an error, otherwise it produces no output.
25 * If you want to check the code coverage with `gcov', add compiler options
27 * -fprofile-arcs -ftest-coverage
29 * Except memory allocation errors, all code in `numberset.c' is covered.
41 #include <numberset.h>
60 int wraps
[] = {-1, 4, 9, 20};
61 size_t num_wraps
= sizeof(wraps
) / sizeof(int);
68 nr
= number_set_new(1, 1, 2, 2);
69 assert(nr
== NUMBERSET_INVALID_RANGE
);
72 nr
= number_set_new(2, 2, 1, 1);
73 assert(nr
== NUMBERSET_INVALID_RANGE
);
75 /* min < 0, max < 0 */
76 nr
= number_set_new(1, 2, -1, -1);
77 assert(nr
< NUMBERSET_INVALID_WRAP_RANGE
);
80 /* min > max, start > end */
81 nr
= number_set_new(2, 1, 2, 1);
82 assert(nr
< NUMBERSET_INVALID_WRAP_RANGE
);
85 /* wrap_range_check_wraps */
86 /* ---------------------- */
89 i
= wrap_range_check_wraps(0, NULL
);
93 i
= wrap_range_check_wraps(1, wraps
);
98 int wraps_bad1
[] = { -2, 2 };
99 size_t num_wraps_bad1
= sizeof(wraps_bad1
) / sizeof(int);
102 i
= wrap_range_check_wraps(num_wraps_bad1
, wraps_bad1
);
106 /* wraps[n] >= wraps[n+1] */
108 int wraps_bad2
[] = { 1, 1 };
109 size_t num_wraps_bad2
= sizeof(wraps_bad2
) / sizeof(int);
112 i
= wrap_range_check_wraps(num_wraps_bad2
, wraps_bad2
);
117 i
= wrap_range_check_wraps(num_wraps
, wraps
);
124 nr
= wrap_range_new(0, 0, 0, NULL
);
125 assert(nr
== NUMBERSET_INVALID_WRAP_RANGE
);
127 /* start < wraps[n] < end */
128 nr
= wrap_range_new(2, 6, num_wraps
, wraps
);
129 assert(nr
== NUMBERSET_INVALID_WRAP_RANGE
);
132 nr
= wrap_range_new(1, 1, num_wraps
, wraps
);
133 assert(nr
< NUMBERSET_INVALID_WRAP_RANGE
);
137 nr
= wrap_range_new(2, 1, num_wraps
, wraps
);
138 assert(nr
< NUMBERSET_INVALID_WRAP_RANGE
);
141 /* number_set_show */
142 /* --------------- */
144 /* single integer normal range, min < 0, max < 0 */
145 nr
= number_set_new(1, 1, 1, 1);
146 s
= number_set_show(nr
, -1, -1);
147 assert(!strcmp(s
, "1"));
151 /* one normal full range, max < min */
152 nr
= number_set_new(1, 2, 1, 2);
153 s
= number_set_show(nr
, 2, 1);
154 assert(!strcmp(s
, "-"));
158 /* one wrap-around range */
159 nr
= wrap_range_new(2, 1, num_wraps
, wraps
);
160 s
= number_set_show(nr
, 0, 0);
161 assert(!strcmp(s
, "2-1"));
165 /* two normal ranges, start > max */
166 nr
= number_set_new(1, 2, 1, 2);
167 nr1
= number_set_new(4, 5, 4, 5);
169 s
= number_set_show(nr
, 0, 3);
170 assert(!strcmp(s
, "1-2"));
175 /* two normal ranges, start > max */
176 nr
= number_set_new(1, 2, 1, 2);
177 nr1
= number_set_new(4, 5, 4, 5);
179 s
= number_set_show(nr
, 3, 6);
180 assert(!strcmp(s
, "4-5"));
186 nr
= number_set_new(1, 2, 1, 2);
187 nr1
= number_set_new(4, 5, 4, 5);
188 nr2
= number_set_new(7, 8, 7, 8);
191 s
= number_set_show(nr
, 1, 8);
192 assert(!strcmp(s
, "-2, 4-5, 7-"));
198 /* number_set_prepend */
199 /* ------------------ */
202 list
= number_set_prepend(NUMBERSET_INVALID_CHARACTER
, NULL
);
203 assert(list
== NUMBERSET_INVALID_CHARACTER
);
206 list
= number_set_prepend(NULL
, NUMBERSET_INVALID_CHARACTER
);
207 assert(list
== NUMBERSET_INVALID_CHARACTER
);
209 /* different range types */
210 nr
= number_set_new(1, 2, 1, 2);
211 nr1
= wrap_range_new(3, 4, num_wraps
, wraps
);
212 list
= number_set_prepend(nr
, nr1
);
213 assert(list
== NUMBERSET_INVALID_RANGE
);
217 /* ranges not ascending */
218 nr
= number_set_new(3, 4, 3, 4);
219 nr1
= number_set_new(1, 2, 1, 2);
220 list
= number_set_prepend(nr
, nr1
);
221 assert(list
== NUMBERSET_NOT_ASCENDING
);
225 /* ranges overlapping */
226 nr
= number_set_new(1, 5, 1, 5);
227 nr1
= number_set_new(1, 2, 1, 2);
228 list
= number_set_prepend(nr
, nr1
);
229 assert(list
== NUMBERSET_OVERLAPPING_RANGES
);
233 /* merge adjacent ranges */
234 nr
= number_set_new(1, 2, 1, 2);
235 nr1
= number_set_new(3, 4, 3, 4);
236 list
= number_set_prepend(nr
, nr1
);
237 s
= number_set_show(list
, -1, -1);
238 assert(!strcmp(s
, "1-4"));
239 number_set_free(list
);
243 nr
= number_set_new(1, 2, 1, 2);
244 nr1
= number_set_new(4, 5, 4, 5);
245 list
= number_set_prepend(nr
, nr1
);
246 s
= number_set_show(list
, -1, -1);
247 assert(!strcmp(s
, "4-5, 1-2"));
248 number_set_free(list
);
251 /* wrap_range_prepend */
252 /* ------------------ */
255 list
= wrap_range_prepend(NUMBERSET_INVALID_CHARACTER
, NULL
);
256 assert(list
== NUMBERSET_INVALID_CHARACTER
);
259 list
= wrap_range_prepend(NULL
, NUMBERSET_INVALID_CHARACTER
);
260 assert(list
== NUMBERSET_INVALID_CHARACTER
);
262 /* different range types */
263 nr
= number_set_new(1, 2, 1, 2);
264 nr1
= wrap_range_new(3, 4, num_wraps
, wraps
);
265 list
= wrap_range_prepend(nr
, nr1
);
266 assert(list
== NUMBERSET_INVALID_RANGE
);
270 /* ranges not ascending (different intervals) */
271 nr
= wrap_range_new(10, 12, num_wraps
, wraps
);
272 nr1
= wrap_range_new(1, 2, num_wraps
, wraps
);
273 list
= wrap_range_prepend(nr
, nr1
);
274 assert(list
== NUMBERSET_NOT_ASCENDING
);
278 /* appending to real wrap-around range */
279 nr
= wrap_range_new(12, 10, num_wraps
, wraps
);
280 nr1
= wrap_range_new(13, 14, num_wraps
, wraps
);
281 list
= wrap_range_prepend(nr
, nr1
);
282 assert(list
== NUMBERSET_OVERLAPPING_RANGES
);
286 /* ranges not ascending (same interval) */
287 nr
= wrap_range_new(12, 14, num_wraps
, wraps
);
288 nr1
= wrap_range_new(10, 11, num_wraps
, wraps
);
289 list
= wrap_range_prepend(nr
, nr1
);
290 assert(list
== NUMBERSET_NOT_ASCENDING
);
294 /* ranges overlapping (same interval) */
295 nr
= wrap_range_new(1, 3, num_wraps
, wraps
);
296 nr1
= wrap_range_new(2, 4, num_wraps
, wraps
);
297 list
= wrap_range_prepend(nr
, nr1
);
298 assert(list
== NUMBERSET_OVERLAPPING_RANGES
);
302 /* ranges overlapping (with real wrap-around range) */
303 nr
= wrap_range_new(12, 13, num_wraps
, wraps
);
304 nr1
= wrap_range_new(15, 16, num_wraps
, wraps
);
305 nr2
= wrap_range_new(17, 18, num_wraps
, wraps
);
306 nr3
= wrap_range_new(19, 14, num_wraps
, wraps
);
307 list
= wrap_range_prepend(nr
, nr1
);
308 list
= wrap_range_prepend(list
, nr2
);
309 list
= wrap_range_prepend(list
, nr3
);
310 assert(list
== NUMBERSET_OVERLAPPING_RANGES
);
316 /* normal prepend (different intervals) */
317 nr
= wrap_range_new(1, 2, num_wraps
, wraps
);
318 nr1
= wrap_range_new(18, 20, num_wraps
, wraps
);
319 list
= wrap_range_prepend(nr
, nr1
);
320 s
= number_set_show(list
, -1, -1);
321 assert(!strcmp(s
, "18-20, 1-2"));
322 number_set_free(list
);
325 /* normal prepend (same interval) */
326 nr
= wrap_range_new(11, 12, num_wraps
, wraps
);
327 nr1
= wrap_range_new(18, 20, num_wraps
, wraps
);
328 list
= wrap_range_prepend(nr
, nr1
);
329 s
= number_set_show(list
, -1, -1);
330 assert(!strcmp(s
, "18-20, 11-12"));
331 number_set_free(list
);
334 /* prepend real wrap-around range (different intervals) */
335 nr
= wrap_range_new(3, 4, num_wraps
, wraps
);
336 nr1
= wrap_range_new(6, 7, num_wraps
, wraps
);
337 nr2
= wrap_range_new(12, 13, num_wraps
, wraps
);
338 nr3
= wrap_range_new(19, 14, num_wraps
, wraps
);
339 list
= wrap_range_prepend(nr
, nr1
);
340 list
= wrap_range_prepend(list
, nr2
);
341 list
= wrap_range_prepend(list
, nr3
);
342 s
= number_set_show(list
, -1, -1);
343 assert(!strcmp(s
, "19-14, 12-13, 6-7, 3-4"));
344 number_set_free(list
);
347 /* number_set_insert */
348 /* ----------------- */
351 list
= number_set_insert(NUMBERSET_INVALID_CHARACTER
, NULL
);
352 assert(list
== NUMBERSET_INVALID_CHARACTER
);
355 list
= number_set_insert(NULL
, NUMBERSET_INVALID_CHARACTER
);
356 assert(list
== NUMBERSET_INVALID_CHARACTER
);
358 /* different range types */
359 nr
= number_set_new(1, 2, 1, 2);
360 nr1
= wrap_range_new(3, 4, num_wraps
, wraps
);
361 list
= number_set_insert(nr
, nr1
);
362 assert(list
== NUMBERSET_INVALID_RANGE
);
366 /* ranges overlapping */
367 nr
= number_set_new(1, 5, 1, 5);
368 nr1
= number_set_new(1, 2, 1, 2);
369 list
= number_set_insert(nr
, nr1
);
370 assert(list
== NUMBERSET_OVERLAPPING_RANGES
);
374 /* merge adjacent ranges (right) */
375 nr
= number_set_new(1, 2, 1, 2);
376 nr1
= number_set_new(8, 9, 8, 9);
377 nr2
= number_set_new(3, 4, 3, 4);
378 list
= number_set_insert(nr
, nr1
);
379 list
= number_set_insert(list
, nr2
);
380 s
= number_set_show(list
, -1, -1);
381 assert(!strcmp(s
, "8-9, 1-4"));
382 number_set_free(list
);
385 /* merge adjacent ranges (left) */
386 nr
= number_set_new(1, 2, 1, 2);
387 nr1
= number_set_new(8, 9, 8, 9);
388 nr2
= number_set_new(6, 7, 6, 7);
389 list
= number_set_insert(nr
, nr1
);
390 list
= number_set_insert(list
, nr2
);
391 s
= number_set_show(list
, -1, -1);
392 assert(!strcmp(s
, "6-9, 1-2"));
393 number_set_free(list
);
396 /* merge adjacent ranges (middle) */
397 nr
= number_set_new(1, 2, 1, 2);
398 nr1
= number_set_new(5, 6, 5, 6);
399 nr2
= number_set_new(3, 4, 3, 4);
400 list
= number_set_insert(nr
, nr1
);
401 list
= number_set_insert(list
, nr2
);
402 s
= number_set_show(list
, -1, -1);
403 assert(!strcmp(s
, "1-6"));
404 number_set_free(list
);
408 nr
= number_set_new(4, 5, 4, 5);
409 nr1
= number_set_new(1, 2, 1, 2);
410 list
= number_set_insert(nr
, nr1
);
411 s
= number_set_show(list
, -1, -1);
412 assert(!strcmp(s
, "4-5, 1-2"));
413 number_set_free(list
);
417 nr
= number_set_new(1, 2, 1, 2);
418 nr1
= number_set_new(7, 8, 7, 8);
419 nr2
= number_set_new(4, 5, 4, 5);
420 list
= number_set_insert(nr
, nr1
);
421 list
= number_set_insert(list
, nr2
);
422 s
= number_set_show(list
, -1, -1);
423 assert(!strcmp(s
, "7-8, 4-5, 1-2"));
424 number_set_free(list
);
427 /* wrap_range_insert */
428 /* ----------------- */
431 list
= wrap_range_insert(NUMBERSET_INVALID_CHARACTER
, NULL
);
432 assert(list
== NUMBERSET_INVALID_CHARACTER
);
435 list
= wrap_range_insert(NULL
, NUMBERSET_INVALID_CHARACTER
);
436 assert(list
== NUMBERSET_INVALID_CHARACTER
);
438 /* different range types */
439 nr
= number_set_new(1, 2, 1, 2);
440 nr1
= wrap_range_new(3, 4, num_wraps
, wraps
);
441 list
= wrap_range_insert(nr
, nr1
);
442 assert(list
== NUMBERSET_INVALID_RANGE
);
446 /* ranges overlapping */
447 nr
= wrap_range_new(1, 4, num_wraps
, wraps
);
448 nr1
= wrap_range_new(1, 2, num_wraps
, wraps
);
449 list
= wrap_range_insert(nr
, nr1
);
450 assert(list
== NUMBERSET_OVERLAPPING_RANGES
);
454 /* appending real wrap-around range to real wrap-around range */
455 /* (same interval) */
456 nr
= wrap_range_new(12, 10, num_wraps
, wraps
);
457 nr1
= wrap_range_new(13, 11, num_wraps
, wraps
);
458 list
= wrap_range_insert(nr
, nr1
);
459 assert(list
== NUMBERSET_OVERLAPPING_RANGES
);
463 /* appending to real wrap-around range (same interval) */
464 nr
= wrap_range_new(12, 10, num_wraps
, wraps
);
465 nr1
= wrap_range_new(13, 14, num_wraps
, wraps
);
466 list
= wrap_range_insert(nr
, nr1
);
467 assert(list
== NUMBERSET_OVERLAPPING_RANGES
);
471 /* prepend (different intervals) */
472 nr
= wrap_range_new(14, 17, num_wraps
, wraps
);
473 nr1
= wrap_range_new(1, 2, num_wraps
, wraps
);
474 list
= wrap_range_insert(nr
, nr1
);
475 s
= number_set_show(list
, -1, -1);
476 assert(!strcmp(s
, "14-17, 1-2"));
477 number_set_free(list
);
480 /* prepend (same interval) */
481 nr
= wrap_range_new(3, 4, num_wraps
, wraps
);
482 nr1
= wrap_range_new(1, 2, num_wraps
, wraps
);
483 list
= wrap_range_insert(nr
, nr1
);
484 s
= number_set_show(list
, -1, -1);
485 assert(!strcmp(s
, "3-4, 1-2"));
486 number_set_free(list
);
489 /* append (different intervals) */
490 nr
= wrap_range_new(1, 2, num_wraps
, wraps
);
491 nr1
= wrap_range_new(14, 17, num_wraps
, wraps
);
492 list
= wrap_range_insert(nr
, nr1
);
493 s
= number_set_show(list
, -1, -1);
494 assert(!strcmp(s
, "14-17, 1-2"));
495 number_set_free(list
);
498 /* append (same interval) */
499 nr
= wrap_range_new(1, 2, num_wraps
, wraps
);
500 nr1
= wrap_range_new(3, 4, num_wraps
, wraps
);
501 list
= wrap_range_insert(nr
, nr1
);
502 s
= number_set_show(list
, -1, -1);
503 assert(!strcmp(s
, "3-4, 1-2"));
504 number_set_free(list
);
507 /* insert (with real wrap-around range) */
508 nr
= wrap_range_new(13, 14, num_wraps
, wraps
);
509 nr1
= wrap_range_new(18, 12, num_wraps
, wraps
);
510 nr2
= wrap_range_new(15, 16, num_wraps
, wraps
);
511 list
= wrap_range_insert(nr
, nr1
);
512 list
= wrap_range_insert(list
, nr2
);
513 s
= number_set_show(list
, -1, -1);
514 assert(!strcmp(s
, "18-12, 15-16, 13-14"));
515 number_set_free(list
);
518 /* number_set_reverse */
519 /* ------------------ */
522 list
= number_set_reverse(NULL
);
523 assert(list
== NULL
);
526 nr
= wrap_range_new(13, 14, num_wraps
, wraps
);
527 nr1
= wrap_range_new(18, 12, num_wraps
, wraps
);
528 list
= wrap_range_insert(nr
, nr1
);
529 list
= number_set_reverse(list
);
530 s
= number_set_show(list
, -1, -1);
531 assert(!strcmp(s
, "13-14, 18-12"));
532 number_set_free(list
);
535 /* number_set_get_first */
536 /* -------------------- */
539 i
= number_set_get_first(NULL
);
544 i
= number_set_get_first(&iter
);
547 /* number_set_get_next */
548 /* ------------------- */
551 i
= number_set_get_next(NULL
);
556 i
= number_set_get_next(&iter
);
559 /* number_set_get_first & number_set_get_next (single normal range) */
560 /* ---------------------------------------------------------------- */
562 list
= number_set_new(12, 18, 12, 18);
564 s
= (char*)malloc(100);
566 i
= number_set_get_first(&iter
);
569 p
+= sprintf(p
, "%d ", i
);
570 i
= number_set_get_next(&iter
);
572 assert(!strcmp(s
, "12 13 14 15 16 17 18 "));
573 number_set_free(list
);
577 /* number_set_get_first & number_set_get_next (single wrap-around range) */
578 /* --------------------------------------------------------------------- */
580 list
= wrap_range_new(18, 12, num_wraps
, wraps
);
582 s
= (char*)malloc(100);
584 i
= number_set_get_first(&iter
);
587 p
+= sprintf(p
, "%d ", i
);
588 i
= number_set_get_next(&iter
);
590 assert(!strcmp(s
, "18 19 20 10 11 12 "));
591 number_set_free(list
);
594 /* number_set_get_first & number_set_get_next (two ranges) */
595 /* ------------------------------------------------------- */
597 nr
= wrap_range_new(13, 14, num_wraps
, wraps
);
598 nr1
= wrap_range_new(18, 12, num_wraps
, wraps
);
599 list
= wrap_range_insert(nr
, nr1
);
600 list
= number_set_reverse(list
);
602 s
= (char*)malloc(100);
604 i
= number_set_get_first(&iter
);
607 p
+= sprintf(p
, "%d ", i
);
608 i
= number_set_get_next(&iter
);
610 assert(!strcmp(s
, "13 14 18 19 20 10 11 12 "));
611 number_set_free(list
);
614 /* number_set_get_first & number_set_get_next (three ranges) */
615 /* --------------------------------------------------------- */
617 nr
= wrap_range_new(2, 3, num_wraps
, wraps
);
618 nr1
= wrap_range_new(8, 6, num_wraps
, wraps
);
619 nr2
= wrap_range_new(18, 12, num_wraps
, wraps
);
620 list
= wrap_range_insert(nr
, nr1
);
621 list
= wrap_range_insert(list
, nr2
);
622 list
= number_set_reverse(list
);
624 s
= (char*)malloc(100);
626 i
= number_set_get_first(&iter
);
629 p
+= sprintf(p
, "%d ", i
);
630 i
= number_set_get_next(&iter
);
632 assert(!strcmp(s
, "2 3 8 9 5 6 18 19 20 10 11 12 "));
633 number_set_free(list
);
636 /* number_set_is_element */
637 /* --------------------- */
640 nr
= number_set_new(12, 18, 12, 18);
641 s
= (char*)malloc(100);
643 for (i
= 8; i
< 23; i
++)
644 if (number_set_is_element(nr
, i
))
645 p
+= sprintf(p
, "%d ", i
);
646 assert(!strcmp(s
, "12 13 14 15 16 17 18 "));
650 /* real wrap-around range */
651 nr
= wrap_range_new(18, 12, num_wraps
, wraps
);
652 s
= (char*)malloc(100);
654 for (i
= 8; i
< 23; i
++)
655 if (number_set_is_element(nr
, i
))
656 p
+= sprintf(p
, "%d ", i
);
657 assert(!strcmp(s
, "10 11 12 18 19 20 "));
661 /* number_set_parse */
662 /* ---------------- */
665 r
= number_set_parse(NULL
, NULL
, 0, 0);
667 /* min < 0, max < 0, empty input */
669 r
= number_set_parse(in
, NULL
, -1, -1);
672 /* min > max, numeric overflow */
674 s
= (char*)malloc(100);
675 sprintf(s
, "%ld", (long)INT_MAX
* 2);
676 r
= number_set_parse(s
, &list
, 10, 5);
677 assert(list
== NUMBERSET_OVERFLOW
);
681 /* numeric overflow of range */
683 s
= (char*)malloc(100);
684 sprintf(s
, "1-%ld", (long)INT_MAX
* 2);
685 r
= number_set_parse(s
, &list
, 10, 5);
686 assert(list
== NUMBERSET_OVERFLOW
);
690 /* invalid range (n < min) */
693 r
= number_set_parse(in
, &list
, 4, 6);
694 assert(list
== NUMBERSET_INVALID_RANGE
);
697 /* invalid range (m > max) */
700 r
= number_set_parse(in
, &list
, 1, 2);
701 assert(list
== NUMBERSET_INVALID_RANGE
);
707 r
= number_set_parse(in
, &list
, 0, 6);
708 assert(list
== NUMBERSET_NOT_ASCENDING
);
709 assert(r
== in
+ strlen("3-5 "));
711 /* overlapping ranges */
714 r
= number_set_parse(in
, &list
, 0, 7);
715 assert(list
== NUMBERSET_OVERLAPPING_RANGES
);
716 assert(r
== in
+ strlen("3-5 "));
718 /* invalid character */
721 r
= number_set_parse(in
, &list
, -1, -1);
722 assert(list
== NUMBERSET_INVALID_CHARACTER
);
725 /* whitespace, m < n, no list */
729 r
= number_set_parse(in
, &list
, 10, 5);
730 s
= number_set_show(list
, 2, 12);
731 assert(r
== in
+ strlen(in
));
732 assert(!strcmp(s
, out
));
733 number_set_free(list
);
738 r
= number_set_parse(in
, NULL
, 10, 5);
739 assert(r
== in
+ strlen(in
));
741 /* multiple range type representation forms, with merging */
743 in
= "-3, 4, 6-8, 10-";
744 out
= "-4, 6-8, 10-";
745 r
= number_set_parse(in
, &list
, 1, 13);
746 s
= number_set_show(list
, 2, 12);
747 assert(r
== in
+ strlen(in
));
748 assert(!strcmp(s
, out
));
749 number_set_free(list
);
755 /* end of numberset-test.c */