4 * Copyright (C) 2012-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.
25 #include <numberset.h>
29 number_set_new(int start
,
56 if (start
< min
|| end
> max
)
57 return NUMBERSET_INVALID_RANGE
;
59 nr
= (number_range
*)malloc(sizeof (number_range
));
61 return NUMBERSET_ALLOCATION_ERROR
;
74 wrap_range_check_wraps(size_t num_wraps
,
80 /* `wraps' must have at least two elements */
81 if (!wraps
|| num_wraps
< 2)
84 /* first `wraps' element must be larger than or equal to -1 */
88 /* check that all elements of `wraps' are strictly ascending */
89 for (i
= 1; i
< num_wraps
; i
++)
90 if (wraps
[i
] <= wraps
[i
- 1])
98 wrap_range_new(int start
,
109 return NUMBERSET_INVALID_WRAP_RANGE
;
122 /* search fitting interval in `wraps' */
123 for (i
= 1; i
< num_wraps
; i
++)
125 if (s
> wraps
[i
- 1] && e
<= wraps
[i
])
129 return NUMBERSET_INVALID_WRAP_RANGE
;
131 nr
= (number_range
*)malloc(sizeof (number_range
));
133 return NUMBERSET_ALLOCATION_ERROR
;
137 nr
->base
= wraps
[i
- 1] + 1;
146 number_set_prepend(number_range
* list
,
147 number_range
* element
)
155 /* `list' and `element' must both be normal integer ranges */
156 if (list
->base
!= list
->wrap
|| element
->base
!= element
->wrap
)
157 return NUMBERSET_INVALID_RANGE
;
159 if (element
->start
<= list
->end
)
161 if (element
->end
< list
->start
)
162 return NUMBERSET_NOT_ASCENDING
;
164 return NUMBERSET_OVERLAPPING_RANGES
;
167 if (element
->start
== list
->end
+ 1)
169 /* merge adjacent ranges */
170 list
->end
= element
->end
;
177 element
->next
= list
;
184 number_set_prepend_unsorted(number_range
* list
,
185 number_range
* element
)
193 /* `list' and `element' must both be normal integer ranges */
194 if (list
->base
!= list
->wrap
|| element
->base
!= element
->wrap
)
195 return NUMBERSET_INVALID_RANGE
;
197 element
->next
= list
;
204 wrap_range_prepend(number_range
* list
,
205 number_range
* element
)
213 /* `list' and `element' must both be wrap-around ranges */
214 if (list
->base
== list
->wrap
|| element
->base
== element
->wrap
)
215 return NUMBERSET_INVALID_RANGE
;
217 /* we explicitly assume that the [base;wrap] intervals */
218 /* of `list' and `element' either don't overlap ... */
219 if (element
->base
< list
->base
)
220 return NUMBERSET_NOT_ASCENDING
;
221 if (element
->base
> list
->base
)
224 /* ... or are exactly the same; */
225 /* in this case, we can't append if the list's range really wraps around */
226 if (list
->start
> list
->end
)
227 return NUMBERSET_OVERLAPPING_RANGES
;
229 if (element
->start
<= list
->end
)
231 if (element
->end
< list
->start
)
232 return NUMBERSET_NOT_ASCENDING
;
234 return NUMBERSET_OVERLAPPING_RANGES
;
237 if (element
->start
> element
->end
)
239 number_range
* nr
= list
->next
;
242 /* we must search backwards to check */
243 /* whether the wrapped part of the range overlaps */
244 /* with an already existing range */
245 /* (in the same [base;wrap] interval) */
248 if (element
->base
!= nr
->base
)
250 if (element
->end
> nr
->start
)
251 return NUMBERSET_OVERLAPPING_RANGES
;
258 element
->next
= list
;
265 number_set_insert(number_range
* list
,
266 number_range
* element
)
268 number_range
* nr
= list
;
278 /* `list' and `element' must both be normal integer ranges */
279 if (list
->base
!= list
->wrap
|| element
->base
!= element
->wrap
)
280 return NUMBERSET_INVALID_RANGE
;
285 if (element
->start
<= nr
->end
286 && element
->end
>= nr
->start
)
287 return NUMBERSET_OVERLAPPING_RANGES
;
289 /* merge adjacent ranges */
290 if (element
->end
+ 1 == nr
->start
)
292 nr
->start
= element
->start
;
297 && nr
->next
->end
+ 1 == nr
->start
)
300 element
->end
= nr
->end
;
309 if (element
->start
> nr
->end
)
311 /* merge adjacent ranges */
312 if (nr
->end
+ 1 == element
->start
)
314 nr
->end
= element
->end
;
320 prev
->next
= element
;
323 return prev
? list
: element
;
330 /* prepend element */
331 prev
->next
= element
;
332 element
->next
= NULL
;
339 wrap_range_insert(number_range
* list
,
340 number_range
* element
)
342 number_range
* nr
= list
;
352 /* `list' and `element' must both be wrap-around ranges */
353 if (list
->base
== list
->wrap
|| element
->base
== element
->wrap
)
354 return NUMBERSET_INVALID_RANGE
;
359 /* we explicitly assume that the [base;wrap] intervals */
360 /* of `list' and `element' either don't overlap ... */
361 if (element
->base
< nr
->base
)
363 if (element
->base
> nr
->base
)
366 /* ... or are exactly the same */
368 if (nr
->start
> nr
->end
)
370 /* range really wraps around */
371 if (element
->start
> element
->end
)
372 return NUMBERSET_OVERLAPPING_RANGES
;
374 if (element
->start
<= nr
->end
375 || element
->end
>= nr
->start
)
376 return NUMBERSET_OVERLAPPING_RANGES
;
381 if (element
->start
<= nr
->end
382 && element
->end
>= nr
->start
)
383 return NUMBERSET_OVERLAPPING_RANGES
;
386 if (element
->start
> nr
->end
)
390 prev
->next
= element
;
393 return prev
? list
: element
;
402 /* prepend element */
403 prev
->next
= element
;
404 element
->next
= NULL
;
411 number_set_reverse(number_range
* list
)
435 number_set_parse(const char* s
,
436 number_range
** number_set
,
440 number_range
* cur
= NULL
;
441 number_range
* new_range
;
443 const char* last_pos
= s
;
447 number_range
* error_code
= NULL
;
484 else if (isdigit(*s
))
492 || (n
== INT_MAX
/ 10 && digit
> 5))
494 error_code
= NUMBERSET_OVERFLOW
;
500 } while (isdigit(*s
));
509 break; /* end of data */
512 error_code
= NUMBERSET_INVALID_CHARACTER
;
530 || (m
== INT_MAX
/ 10 && digit
> 5))
532 error_code
= NUMBERSET_OVERFLOW
;
538 } while (isdigit(*s
));
557 if (n
< min
|| m
> max
)
559 error_code
= NUMBERSET_INVALID_RANGE
;
566 error_code
= NUMBERSET_NOT_ASCENDING
;
568 error_code
= NUMBERSET_OVERLAPPING_RANGES
;
573 && last_end
+ 1 == n
)
575 /* merge adjacent ranges */
582 new_range
= (number_range
*)malloc(sizeof (number_range
));
585 error_code
= NUMBERSET_ALLOCATION_ERROR
;
589 /* prepend new range to list */
590 new_range
->start
= n
;
594 new_range
->next
= cur
;
605 number_set_free(cur
);
609 *number_set
= error_code
;
615 *number_set
= number_set_reverse(cur
);
623 number_set_free(number_range
* number_set
)
625 number_range
* nr
= number_set
;
641 number_set_show(number_range
* number_set
,
649 number_range
* nr
= number_set
;
654 if (nr
&& nr
->base
== nr
->wrap
)
672 /* `min' and `max' are meaningless for wrap-around ranges */
686 comma
= *s
? ", " : "";
688 if (nr
->start
== nr
->end
)
689 s
= sdscatprintf(s
, "%s%i", comma
, nr
->start
);
690 else if (nr
->start
<= min
692 s
= sdscatprintf(s
, "-");
693 else if (nr
->start
<= min
)
694 s
= sdscatprintf(s
, "-%i", nr
->end
);
695 else if (nr
->end
>= max
)
696 s
= sdscatprintf(s
, "%s%i-", comma
, nr
->start
);
698 s
= sdscatprintf(s
, "%s%i-%i", comma
, nr
->start
, nr
->end
);
708 /* we return an empty string for an empty number set */
709 /* (this is, number_set == NULL or unsuitable `min' and `max' values) */
711 res
= (char*)malloc(len
);
722 number_set_is_element(number_range
* number_set
,
725 number_range
* nr
= number_set
;
730 if (nr
->start
> nr
->end
)
732 if (number
< nr
->base
)
734 if (number
<= nr
->end
)
736 if ( number
< nr
->start
)
738 if (number
<= nr
->wrap
)
743 if (number
< nr
->start
)
745 if (number
<= nr
->end
)
757 number_set_get_first(number_set_iter
* iter_p
)
759 if (!iter_p
|| !iter_p
->range
)
762 iter_p
->val
= iter_p
->range
->start
;
769 number_set_get_next(number_set_iter
* iter_p
)
771 if (!iter_p
|| !iter_p
->range
)
776 if (iter_p
->range
->start
> iter_p
->range
->end
)
778 /* range really wraps around */
779 if (iter_p
->val
> iter_p
->range
->wrap
)
780 iter_p
->val
= iter_p
->range
->base
;
781 else if (iter_p
->val
< iter_p
->range
->start
782 && iter_p
->val
> iter_p
->range
->end
)
784 iter_p
->range
= iter_p
->range
->next
;
787 iter_p
->val
= iter_p
->range
->start
;
794 if (iter_p
->val
> iter_p
->range
->end
)
796 iter_p
->range
= iter_p
->range
->next
;
799 iter_p
->val
= iter_p
->range
->start
;
808 /* end of numberset.c */