4 * Copyright (C) 2012-2015 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
)
72 if (element
->start
<= list
->end
)
74 if (element
->end
< list
->start
)
75 return NUMBERSET_NOT_ASCENDING
;
77 return NUMBERSET_OVERLAPPING_RANGES
;
81 && element
->start
== list
->end
+ 1)
83 /* merge adjacent ranges */
84 list
->end
= element
->end
;
98 number_set_reverse(number_range
* list
)
122 number_set_parse(const char* s
,
123 number_range
** number_set
,
127 number_range
* cur
= NULL
;
128 number_range
* new_range
;
131 const char* last_pos
= s
;
135 number_range
* error_code
= NULL
;
172 else if (isdigit(*s
))
180 || (n
== INT_MAX
/ 10 && digit
> 5))
182 error_code
= NUMBERSET_OVERFLOW
;
188 } while (isdigit(*s
));
197 break; /* end of data */
200 error_code
= NUMBERSET_INVALID_CHARACTER
;
218 || (m
== INT_MAX
/ 10 && digit
> 5))
220 error_code
= NUMBERSET_OVERFLOW
;
226 } while (isdigit(*s
));
245 if (n
< min
|| m
> max
)
247 error_code
= NUMBERSET_INVALID_RANGE
;
254 error_code
= NUMBERSET_NOT_ASCENDING
;
256 error_code
= NUMBERSET_OVERLAPPING_RANGES
;
261 && last_end
+ 1 == n
)
263 /* merge adjacent ranges */
270 new_range
= (number_range
*)malloc(sizeof (number_range
));
273 error_code
= NUMBERSET_ALLOCATION_ERROR
;
277 /* prepend new range to list */
278 new_range
->start
= n
;
280 new_range
->next
= cur
;
291 number_set_free(cur
);
295 *number_set
= error_code
;
299 /* success; now reverse list to have elements in ascending order */
300 number_range
* list
= NULL
;
320 number_set_free(number_range
* number_set
)
322 number_range
* nr
= number_set
;
338 number_set_show(number_range
* number_set
,
346 number_range
* nr
= number_set
;
374 comma
= *s
? ", " : "";
376 if (nr
->start
== nr
->end
)
377 s
= sdscatprintf(s
, "%s%i", comma
, nr
->start
);
378 else if (nr
->start
<= min
380 s
= sdscatprintf(s
, "-");
381 else if (nr
->start
<= min
)
382 s
= sdscatprintf(s
, "-%i", nr
->end
);
383 else if (nr
->end
>= max
)
384 s
= sdscatprintf(s
, "%s%i-", comma
, nr
->start
);
386 s
= sdscatprintf(s
, "%s%i-%i", comma
, nr
->start
, nr
->end
);
396 /* we return an empty string for an empty number set */
397 /* (this is, number_set == NULL or unsuitable `min' and `max' values) */
399 res
= (char*)malloc(len
);
410 number_set_is_element(number_range
* number_set
,
413 number_range
* nr
= number_set
;
418 if (number
< nr
->start
)
420 if (nr
->start
<= number
421 && number
<= nr
->end
)
431 number_set_get_first(number_set_iter
* iter_p
)
433 if (!iter_p
|| !iter_p
->range
)
436 iter_p
->val
= iter_p
->range
->start
;
443 number_set_get_next(number_set_iter
* iter_p
)
445 if (!iter_p
|| !iter_p
->range
)
450 if (iter_p
->val
> iter_p
->range
->end
)
452 iter_p
->range
= iter_p
->range
->next
;
455 iter_p
->val
= iter_p
->range
->start
;
461 /* end of numberset.c */