4 * Copyright (C) 2012-2017 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
;
72 number_set_prepend(number_range
* list
,
73 number_range
* element
)
81 if (element
->start
<= list
->end
)
83 if (element
->end
< list
->start
)
84 return NUMBERSET_NOT_ASCENDING
;
86 return NUMBERSET_OVERLAPPING_RANGES
;
89 if (element
->start
== list
->end
+ 1)
91 /* merge adjacent ranges */
92 list
->end
= element
->end
;
106 number_set_insert(number_range
* list
,
107 number_range
* element
)
109 number_range
* nr
= list
;
122 if (element
->start
<= nr
->end
123 && element
->end
>= nr
->start
)
124 return NUMBERSET_OVERLAPPING_RANGES
;
126 /* merge adjacent ranges */
127 if (element
->end
+ 1 == nr
->start
)
129 nr
->start
= element
->start
;
134 && nr
->next
->end
+ 1 == nr
->start
)
137 element
->end
= nr
->end
;
146 if (element
->start
> nr
->end
)
148 /* merge adjacent ranges */
149 if (nr
->end
+ 1 == element
->start
)
151 nr
->end
= element
->end
;
157 prev
->next
= element
;
160 return prev
? list
: element
;
167 /* prepend element */
168 prev
->next
= element
;
169 element
->next
= NULL
;
176 number_set_normalize(number_range
* list
)
189 return list
; /* only a single element, nothing to do */
193 if (prev
->end
+ 1 == cur
->start
)
198 prev
->end
= cur
->end
;
218 number_set_reverse(number_range
* list
)
242 number_set_parse(const char* s
,
243 number_range
** number_set
,
247 number_range
* cur
= NULL
;
248 number_range
* new_range
;
250 const char* last_pos
= s
;
254 number_range
* error_code
= NULL
;
291 else if (isdigit(*s
))
299 || (n
== INT_MAX
/ 10 && digit
> 5))
301 error_code
= NUMBERSET_OVERFLOW
;
307 } while (isdigit(*s
));
316 break; /* end of data */
319 error_code
= NUMBERSET_INVALID_CHARACTER
;
337 || (m
== INT_MAX
/ 10 && digit
> 5))
339 error_code
= NUMBERSET_OVERFLOW
;
345 } while (isdigit(*s
));
364 if (n
< min
|| m
> max
)
366 error_code
= NUMBERSET_INVALID_RANGE
;
373 error_code
= NUMBERSET_NOT_ASCENDING
;
375 error_code
= NUMBERSET_OVERLAPPING_RANGES
;
380 && last_end
+ 1 == n
)
382 /* merge adjacent ranges */
389 new_range
= (number_range
*)malloc(sizeof (number_range
));
392 error_code
= NUMBERSET_ALLOCATION_ERROR
;
396 /* prepend new range to list */
397 new_range
->start
= n
;
399 new_range
->next
= cur
;
410 number_set_free(cur
);
414 *number_set
= error_code
;
420 *number_set
= number_set_normalize(number_set_reverse(cur
));
428 number_set_free(number_range
* number_set
)
430 number_range
* nr
= number_set
;
446 number_set_show(number_range
* number_set
,
454 number_range
* nr
= number_set
;
482 comma
= *s
? ", " : "";
484 if (nr
->start
== nr
->end
)
485 s
= sdscatprintf(s
, "%s%i", comma
, nr
->start
);
486 else if (nr
->start
<= min
488 s
= sdscatprintf(s
, "-");
489 else if (nr
->start
<= min
)
490 s
= sdscatprintf(s
, "-%i", nr
->end
);
491 else if (nr
->end
>= max
)
492 s
= sdscatprintf(s
, "%s%i-", comma
, nr
->start
);
494 s
= sdscatprintf(s
, "%s%i-%i", comma
, nr
->start
, nr
->end
);
504 /* we return an empty string for an empty number set */
505 /* (this is, number_set == NULL or unsuitable `min' and `max' values) */
507 res
= (char*)malloc(len
);
518 number_set_is_element(number_range
* number_set
,
521 number_range
* nr
= number_set
;
526 if (number
< nr
->start
)
528 if (nr
->start
<= number
529 && number
<= nr
->end
)
539 number_set_get_first(number_set_iter
* iter_p
)
541 if (!iter_p
|| !iter_p
->range
)
544 iter_p
->val
= iter_p
->range
->start
;
551 number_set_get_next(number_set_iter
* iter_p
)
553 if (!iter_p
|| !iter_p
->range
)
558 if (iter_p
->val
> iter_p
->range
->end
)
560 iter_p
->range
= iter_p
->range
->next
;
563 iter_p
->val
= iter_p
->range
->start
;
571 /* end of numberset.c */