4 * Copyright (C) 2012-2014 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
,
47 if (start
< min
|| end
> max
)
48 return NUMBERSET_INVALID_RANGE
;
50 nr
= (number_range
*)malloc(sizeof (number_range
));
52 return NUMBERSET_ALLOCATION_ERROR
;
63 number_set_prepend(number_range
* list
,
64 number_range
* element
)
69 if (element
->start
<= list
->end
)
71 if (element
->end
< list
->start
)
72 return NUMBERSET_NOT_ASCENDING
;
74 return NUMBERSET_OVERLAPPING_RANGES
;
78 && element
->start
== list
->end
+ 1)
80 /* merge adjacent ranges */
81 list
->end
= element
->end
;
95 number_set_reverse(number_range
* list
)
119 number_set_parse(const char* s
,
120 number_range
** number_set
,
124 number_range
* cur
= NULL
;
125 number_range
* new_range
;
128 const char* last_pos
= s
;
132 number_range
* error_code
= NULL
;
169 else if (isdigit(*s
))
177 || (n
== INT_MAX
/ 10 && digit
> 5))
179 error_code
= NUMBERSET_OVERFLOW
;
185 } while (isdigit(*s
));
194 break; /* end of data */
197 error_code
= NUMBERSET_INVALID_CHARACTER
;
215 || (m
== INT_MAX
/ 10 && digit
> 5))
217 error_code
= NUMBERSET_OVERFLOW
;
223 } while (isdigit(*s
));
242 if (n
< min
|| m
> max
)
244 error_code
= NUMBERSET_INVALID_RANGE
;
251 error_code
= NUMBERSET_NOT_ASCENDING
;
253 error_code
= NUMBERSET_OVERLAPPING_RANGES
;
258 && last_end
+ 1 == n
)
260 /* merge adjacent ranges */
267 new_range
= (number_range
*)malloc(sizeof (number_range
));
270 error_code
= NUMBERSET_ALLOCATION_ERROR
;
274 /* prepend new range to list */
275 new_range
->start
= n
;
277 new_range
->next
= cur
;
288 number_set_free(cur
);
292 *number_set
= error_code
;
296 /* success; now reverse list to have elements in ascending order */
297 number_range
* list
= NULL
;
317 number_set_free(number_range
* number_set
)
319 number_range
* nr
= number_set
;
335 number_set_show(number_range
* number_set
,
343 number_range
* nr
= number_set
;
371 comma
= *s
? ", " : "";
373 if (nr
->start
== nr
->end
)
374 s
= sdscatprintf(s
, "%s%i", comma
, nr
->start
);
375 else if (nr
->start
<= min
377 s
= sdscatprintf(s
, "-");
378 else if (nr
->start
<= min
)
379 s
= sdscatprintf(s
, "-%i", nr
->end
);
380 else if (nr
->end
>= max
)
381 s
= sdscatprintf(s
, "%s%i-", comma
, nr
->start
);
383 s
= sdscatprintf(s
, "%s%i-%i", comma
, nr
->start
, nr
->end
);
393 /* we return an empty string for an empty number set */
394 /* (this is, number_set == NULL or unsuitable `min' and `max' values) */
396 res
= (char*)malloc(len
);
407 number_set_is_element(number_range
* number_set
,
410 number_range
* nr
= number_set
;
415 if (number
< nr
->start
)
417 if (nr
->start
<= number
418 && number
<= nr
->end
)
428 number_set_get_first(number_set_iter
* iter_p
)
430 if (!iter_p
|| !iter_p
->range
)
433 iter_p
->val
= iter_p
->range
->start
;
440 number_set_get_next(number_set_iter
* iter_p
)
442 if (!iter_p
|| !iter_p
->range
)
447 if (iter_p
->val
> iter_p
->range
->end
)
449 iter_p
->range
= iter_p
->range
->next
;
452 iter_p
->val
= iter_p
->range
->start
;
458 /* end of numberset.c */