1 | /* |
2 | * Copyright © 2012 Google, Inc. |
3 | * |
4 | * This is part of HarfBuzz, a text shaping library. |
5 | * |
6 | * Permission is hereby granted, without written agreement and without |
7 | * license or royalty fees, to use, copy, modify, and distribute this |
8 | * software and its documentation for any purpose, provided that the |
9 | * above copyright notice and the following two paragraphs appear in |
10 | * all copies of this software. |
11 | * |
12 | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
13 | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
14 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
15 | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
16 | * DAMAGE. |
17 | * |
18 | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
19 | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
20 | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
21 | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
22 | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
23 | * |
24 | * Google Author(s): Behdad Esfahbod |
25 | */ |
26 | |
27 | #include "hb-set.hh" |
28 | |
29 | |
30 | /** |
31 | * SECTION:hb-set |
32 | * @title: hb-set |
33 | * @short_description: Objects representing a set of integers |
34 | * @include: hb.h |
35 | * |
36 | * Set objects represent a mathematical set of integer values. They are |
37 | * used in non-shaping APIs to query certain sets of characters or glyphs, |
38 | * or other integer values. |
39 | **/ |
40 | |
41 | |
42 | /** |
43 | * hb_set_create: |
44 | * |
45 | * Creates a new, initially empty set. |
46 | * |
47 | * Return value: (transfer full): The new #hb_set_t |
48 | * |
49 | * Since: 0.9.2 |
50 | **/ |
51 | hb_set_t * |
52 | hb_set_create () |
53 | { |
54 | hb_set_t *set; |
55 | |
56 | if (!(set = hb_object_create<hb_set_t> ())) |
57 | return hb_set_get_empty (); |
58 | |
59 | return set; |
60 | } |
61 | |
62 | /** |
63 | * hb_set_get_empty: |
64 | * |
65 | * Fetches the singleton empty #hb_set_t. |
66 | * |
67 | * Return value: (transfer full): The empty #hb_set_t |
68 | * |
69 | * Since: 0.9.2 |
70 | **/ |
71 | hb_set_t * |
72 | hb_set_get_empty () |
73 | { |
74 | return const_cast<hb_set_t *> (&Null (hb_set_t)); |
75 | } |
76 | |
77 | /** |
78 | * hb_set_reference: (skip) |
79 | * @set: A set |
80 | * |
81 | * Increases the reference count on a set. |
82 | * |
83 | * Return value: (transfer full): The set |
84 | * |
85 | * Since: 0.9.2 |
86 | **/ |
87 | hb_set_t * |
88 | hb_set_reference (hb_set_t *set) |
89 | { |
90 | return hb_object_reference (set); |
91 | } |
92 | |
93 | /** |
94 | * hb_set_destroy: (skip) |
95 | * @set: A set |
96 | * |
97 | * Decreases the reference count on a set. When |
98 | * the reference count reaches zero, the set is |
99 | * destroyed, freeing all memory. |
100 | * |
101 | * Since: 0.9.2 |
102 | **/ |
103 | void |
104 | hb_set_destroy (hb_set_t *set) |
105 | { |
106 | if (!hb_object_destroy (set)) return; |
107 | |
108 | hb_free (set); |
109 | } |
110 | |
111 | /** |
112 | * hb_set_set_user_data: (skip) |
113 | * @set: A set |
114 | * @key: The user-data key to set |
115 | * @data: A pointer to the user data to set |
116 | * @destroy: (nullable): A callback to call when @data is not needed anymore |
117 | * @replace: Whether to replace an existing data with the same key |
118 | * |
119 | * Attaches a user-data key/data pair to the specified set. |
120 | * |
121 | * Return value: `true` if success, `false` otherwise |
122 | * |
123 | * Since: 0.9.2 |
124 | **/ |
125 | hb_bool_t |
126 | hb_set_set_user_data (hb_set_t *set, |
127 | hb_user_data_key_t *key, |
128 | void * data, |
129 | hb_destroy_func_t destroy, |
130 | hb_bool_t replace) |
131 | { |
132 | return hb_object_set_user_data (set, key, data, destroy, replace); |
133 | } |
134 | |
135 | /** |
136 | * hb_set_get_user_data: (skip) |
137 | * @set: A set |
138 | * @key: The user-data key to query |
139 | * |
140 | * Fetches the user data associated with the specified key, |
141 | * attached to the specified set. |
142 | * |
143 | * Return value: (transfer none): A pointer to the user data |
144 | * |
145 | * Since: 0.9.2 |
146 | **/ |
147 | void * |
148 | hb_set_get_user_data (const hb_set_t *set, |
149 | hb_user_data_key_t *key) |
150 | { |
151 | return hb_object_get_user_data (set, key); |
152 | } |
153 | |
154 | |
155 | /** |
156 | * hb_set_allocation_successful: |
157 | * @set: A set |
158 | * |
159 | * Tests whether memory allocation for a set was successful. |
160 | * |
161 | * Return value: `true` if allocation succeeded, `false` otherwise |
162 | * |
163 | * Since: 0.9.2 |
164 | **/ |
165 | hb_bool_t |
166 | hb_set_allocation_successful (const hb_set_t *set) |
167 | { |
168 | return !set->in_error (); |
169 | } |
170 | |
171 | /** |
172 | * hb_set_copy: |
173 | * @set: A set |
174 | * |
175 | * Allocate a copy of @set. |
176 | * |
177 | * Return value: (transfer full): Newly-allocated set. |
178 | * |
179 | * Since: 2.8.2 |
180 | **/ |
181 | hb_set_t * |
182 | hb_set_copy (const hb_set_t *set) |
183 | { |
184 | hb_set_t *copy = hb_set_create (); |
185 | if (unlikely (copy->in_error ())) |
186 | return hb_set_get_empty (); |
187 | |
188 | copy->set (*set); |
189 | return copy; |
190 | } |
191 | |
192 | /** |
193 | * hb_set_clear: |
194 | * @set: A set |
195 | * |
196 | * Clears out the contents of a set. |
197 | * |
198 | * Since: 0.9.2 |
199 | **/ |
200 | void |
201 | hb_set_clear (hb_set_t *set) |
202 | { |
203 | /* Immutible-safe. */ |
204 | set->clear (); |
205 | } |
206 | |
207 | /** |
208 | * hb_set_is_empty: |
209 | * @set: a set. |
210 | * |
211 | * Tests whether a set is empty (contains no elements). |
212 | * |
213 | * Return value: `true` if @set is empty |
214 | * |
215 | * Since: 0.9.7 |
216 | **/ |
217 | hb_bool_t |
218 | hb_set_is_empty (const hb_set_t *set) |
219 | { |
220 | return set->is_empty (); |
221 | } |
222 | |
223 | /** |
224 | * hb_set_has: |
225 | * @set: A set |
226 | * @codepoint: The element to query |
227 | * |
228 | * Tests whether @codepoint belongs to @set. |
229 | * |
230 | * Return value: `true` if @codepoint is in @set, `false` otherwise |
231 | * |
232 | * Since: 0.9.2 |
233 | **/ |
234 | hb_bool_t |
235 | hb_set_has (const hb_set_t *set, |
236 | hb_codepoint_t codepoint) |
237 | { |
238 | return set->has (codepoint); |
239 | } |
240 | |
241 | /** |
242 | * hb_set_add: |
243 | * @set: A set |
244 | * @codepoint: The element to add to @set |
245 | * |
246 | * Adds @codepoint to @set. |
247 | * |
248 | * Since: 0.9.2 |
249 | **/ |
250 | void |
251 | hb_set_add (hb_set_t *set, |
252 | hb_codepoint_t codepoint) |
253 | { |
254 | /* Immutible-safe. */ |
255 | set->add (codepoint); |
256 | } |
257 | |
258 | /** |
259 | * hb_set_add_sorted_array: |
260 | * @set: A set |
261 | * @sorted_codepoints: (array length=num_codepoints): Array of codepoints to add |
262 | * @num_codepoints: Length of @sorted_codepoints |
263 | * |
264 | * Adds @num_codepoints codepoints to a set at once. |
265 | * The codepoints array must be in increasing order, |
266 | * with size at least @num_codepoints. |
267 | * |
268 | * Since: 4.1.0 |
269 | */ |
270 | HB_EXTERN void |
271 | hb_set_add_sorted_array (hb_set_t *set, |
272 | const hb_codepoint_t *sorted_codepoints, |
273 | unsigned int num_codepoints) |
274 | { |
275 | /* Immutible-safe. */ |
276 | set->add_sorted_array (sorted_codepoints, |
277 | num_codepoints, |
278 | sizeof(hb_codepoint_t)); |
279 | } |
280 | |
281 | /** |
282 | * hb_set_add_range: |
283 | * @set: A set |
284 | * @first: The first element to add to @set |
285 | * @last: The final element to add to @set |
286 | * |
287 | * Adds all of the elements from @first to @last |
288 | * (inclusive) to @set. |
289 | * |
290 | * Since: 0.9.7 |
291 | **/ |
292 | void |
293 | hb_set_add_range (hb_set_t *set, |
294 | hb_codepoint_t first, |
295 | hb_codepoint_t last) |
296 | { |
297 | /* Immutible-safe. */ |
298 | set->add_range (first, last); |
299 | } |
300 | |
301 | /** |
302 | * hb_set_del: |
303 | * @set: A set |
304 | * @codepoint: Removes @codepoint from @set |
305 | * |
306 | * Removes @codepoint from @set. |
307 | * |
308 | * Since: 0.9.2 |
309 | **/ |
310 | void |
311 | hb_set_del (hb_set_t *set, |
312 | hb_codepoint_t codepoint) |
313 | { |
314 | /* Immutible-safe. */ |
315 | set->del (codepoint); |
316 | } |
317 | |
318 | /** |
319 | * hb_set_del_range: |
320 | * @set: A set |
321 | * @first: The first element to remove from @set |
322 | * @last: The final element to remove from @set |
323 | * |
324 | * Removes all of the elements from @first to @last |
325 | * (inclusive) from @set. |
326 | * |
327 | * If @last is #HB_SET_VALUE_INVALID, then all values |
328 | * greater than or equal to @first are removed. |
329 | * |
330 | * Since: 0.9.7 |
331 | **/ |
332 | void |
333 | hb_set_del_range (hb_set_t *set, |
334 | hb_codepoint_t first, |
335 | hb_codepoint_t last) |
336 | { |
337 | /* Immutible-safe. */ |
338 | set->del_range (first, last); |
339 | } |
340 | |
341 | /** |
342 | * hb_set_is_equal: |
343 | * @set: A set |
344 | * @other: Another set |
345 | * |
346 | * Tests whether @set and @other are equal (contain the same |
347 | * elements). |
348 | * |
349 | * Return value: `true` if the two sets are equal, `false` otherwise. |
350 | * |
351 | * Since: 0.9.7 |
352 | **/ |
353 | hb_bool_t |
354 | hb_set_is_equal (const hb_set_t *set, |
355 | const hb_set_t *other) |
356 | { |
357 | return set->is_equal (*other); |
358 | } |
359 | |
360 | /** |
361 | * hb_set_hash: |
362 | * @set: A set |
363 | * |
364 | * Creates a hash representing @set. |
365 | * |
366 | * Return value: |
367 | * A hash of @set. |
368 | * |
369 | * Since: 4.4.0 |
370 | **/ |
371 | HB_EXTERN unsigned int |
372 | hb_set_hash (const hb_set_t *set) |
373 | { |
374 | return set->hash (); |
375 | } |
376 | |
377 | /** |
378 | * hb_set_is_subset: |
379 | * @set: A set |
380 | * @larger_set: Another set |
381 | * |
382 | * Tests whether @set is a subset of @larger_set. |
383 | * |
384 | * Return value: `true` if the @set is a subset of (or equal to) @larger_set, `false` otherwise. |
385 | * |
386 | * Since: 1.8.1 |
387 | **/ |
388 | hb_bool_t |
389 | hb_set_is_subset (const hb_set_t *set, |
390 | const hb_set_t *larger_set) |
391 | { |
392 | return set->is_subset (*larger_set); |
393 | } |
394 | |
395 | /** |
396 | * hb_set_set: |
397 | * @set: A set |
398 | * @other: Another set |
399 | * |
400 | * Makes the contents of @set equal to the contents of @other. |
401 | * |
402 | * Since: 0.9.2 |
403 | **/ |
404 | void |
405 | hb_set_set (hb_set_t *set, |
406 | const hb_set_t *other) |
407 | { |
408 | /* Immutible-safe. */ |
409 | set->set (*other); |
410 | } |
411 | |
412 | /** |
413 | * hb_set_union: |
414 | * @set: A set |
415 | * @other: Another set |
416 | * |
417 | * Makes @set the union of @set and @other. |
418 | * |
419 | * Since: 0.9.2 |
420 | **/ |
421 | void |
422 | hb_set_union (hb_set_t *set, |
423 | const hb_set_t *other) |
424 | { |
425 | /* Immutible-safe. */ |
426 | set->union_ (*other); |
427 | } |
428 | |
429 | /** |
430 | * hb_set_intersect: |
431 | * @set: A set |
432 | * @other: Another set |
433 | * |
434 | * Makes @set the intersection of @set and @other. |
435 | * |
436 | * Since: 0.9.2 |
437 | **/ |
438 | void |
439 | hb_set_intersect (hb_set_t *set, |
440 | const hb_set_t *other) |
441 | { |
442 | /* Immutible-safe. */ |
443 | set->intersect (*other); |
444 | } |
445 | |
446 | /** |
447 | * hb_set_subtract: |
448 | * @set: A set |
449 | * @other: Another set |
450 | * |
451 | * Subtracts the contents of @other from @set. |
452 | * |
453 | * Since: 0.9.2 |
454 | **/ |
455 | void |
456 | hb_set_subtract (hb_set_t *set, |
457 | const hb_set_t *other) |
458 | { |
459 | /* Immutible-safe. */ |
460 | set->subtract (*other); |
461 | } |
462 | |
463 | /** |
464 | * hb_set_symmetric_difference: |
465 | * @set: A set |
466 | * @other: Another set |
467 | * |
468 | * Makes @set the symmetric difference of @set |
469 | * and @other. |
470 | * |
471 | * Since: 0.9.2 |
472 | **/ |
473 | void |
474 | hb_set_symmetric_difference (hb_set_t *set, |
475 | const hb_set_t *other) |
476 | { |
477 | /* Immutible-safe. */ |
478 | set->symmetric_difference (*other); |
479 | } |
480 | |
481 | /** |
482 | * hb_set_invert: |
483 | * @set: A set |
484 | * |
485 | * Inverts the contents of @set. |
486 | * |
487 | * Since: 3.0.0 |
488 | **/ |
489 | void |
490 | hb_set_invert (hb_set_t *set) |
491 | { |
492 | /* Immutible-safe. */ |
493 | set->invert (); |
494 | } |
495 | |
496 | /** |
497 | * hb_set_is_inverted: |
498 | * @set: A set |
499 | * |
500 | * Returns whether the set is inverted. |
501 | * |
502 | * Return value: `true` if the set is inverted, `false` otherwise |
503 | * |
504 | * Since: 7.0.0 |
505 | **/ |
506 | hb_bool_t |
507 | hb_set_is_inverted (const hb_set_t *set) |
508 | { |
509 | return set->is_inverted (); |
510 | } |
511 | |
512 | /** |
513 | * hb_set_get_population: |
514 | * @set: A set |
515 | * |
516 | * Returns the number of elements in the set. |
517 | * |
518 | * Return value: The population of @set |
519 | * |
520 | * Since: 0.9.7 |
521 | **/ |
522 | unsigned int |
523 | hb_set_get_population (const hb_set_t *set) |
524 | { |
525 | return set->get_population (); |
526 | } |
527 | |
528 | /** |
529 | * hb_set_get_min: |
530 | * @set: A set |
531 | * |
532 | * Finds the smallest element in the set. |
533 | * |
534 | * Return value: minimum of @set, or #HB_SET_VALUE_INVALID if @set is empty. |
535 | * |
536 | * Since: 0.9.7 |
537 | **/ |
538 | hb_codepoint_t |
539 | hb_set_get_min (const hb_set_t *set) |
540 | { |
541 | return set->get_min (); |
542 | } |
543 | |
544 | /** |
545 | * hb_set_get_max: |
546 | * @set: A set |
547 | * |
548 | * Finds the largest element in the set. |
549 | * |
550 | * Return value: maximum of @set, or #HB_SET_VALUE_INVALID if @set is empty. |
551 | * |
552 | * Since: 0.9.7 |
553 | **/ |
554 | hb_codepoint_t |
555 | hb_set_get_max (const hb_set_t *set) |
556 | { |
557 | return set->get_max (); |
558 | } |
559 | |
560 | /** |
561 | * hb_set_next: |
562 | * @set: A set |
563 | * @codepoint: (inout): Input = Code point to query |
564 | * Output = Code point retrieved |
565 | * |
566 | * Fetches the next element in @set that is greater than current value of @codepoint. |
567 | * |
568 | * Set @codepoint to #HB_SET_VALUE_INVALID to get started. |
569 | * |
570 | * Return value: `true` if there was a next value, `false` otherwise |
571 | * |
572 | * Since: 0.9.2 |
573 | **/ |
574 | hb_bool_t |
575 | hb_set_next (const hb_set_t *set, |
576 | hb_codepoint_t *codepoint) |
577 | { |
578 | return set->next (codepoint); |
579 | } |
580 | |
581 | /** |
582 | * hb_set_previous: |
583 | * @set: A set |
584 | * @codepoint: (inout): Input = Code point to query |
585 | * Output = Code point retrieved |
586 | * |
587 | * Fetches the previous element in @set that is lower than current value of @codepoint. |
588 | * |
589 | * Set @codepoint to #HB_SET_VALUE_INVALID to get started. |
590 | * |
591 | * Return value: `true` if there was a previous value, `false` otherwise |
592 | * |
593 | * Since: 1.8.0 |
594 | **/ |
595 | hb_bool_t |
596 | hb_set_previous (const hb_set_t *set, |
597 | hb_codepoint_t *codepoint) |
598 | { |
599 | return set->previous (codepoint); |
600 | } |
601 | |
602 | /** |
603 | * hb_set_next_range: |
604 | * @set: A set |
605 | * @first: (out): The first code point in the range |
606 | * @last: (inout): Input = The current last code point in the range |
607 | * Output = The last code point in the range |
608 | * |
609 | * Fetches the next consecutive range of elements in @set that |
610 | * are greater than current value of @last. |
611 | * |
612 | * Set @last to #HB_SET_VALUE_INVALID to get started. |
613 | * |
614 | * Return value: `true` if there was a next range, `false` otherwise |
615 | * |
616 | * Since: 0.9.7 |
617 | **/ |
618 | hb_bool_t |
619 | hb_set_next_range (const hb_set_t *set, |
620 | hb_codepoint_t *first, |
621 | hb_codepoint_t *last) |
622 | { |
623 | return set->next_range (first, last); |
624 | } |
625 | |
626 | /** |
627 | * hb_set_previous_range: |
628 | * @set: A set |
629 | * @first: (inout): Input = The current first code point in the range |
630 | * Output = The first code point in the range |
631 | * @last: (out): The last code point in the range |
632 | * |
633 | * Fetches the previous consecutive range of elements in @set that |
634 | * are greater than current value of @last. |
635 | * |
636 | * Set @first to #HB_SET_VALUE_INVALID to get started. |
637 | * |
638 | * Return value: `true` if there was a previous range, `false` otherwise |
639 | * |
640 | * Since: 1.8.0 |
641 | **/ |
642 | hb_bool_t |
643 | hb_set_previous_range (const hb_set_t *set, |
644 | hb_codepoint_t *first, |
645 | hb_codepoint_t *last) |
646 | { |
647 | return set->previous_range (first, last); |
648 | } |
649 | |
650 | /** |
651 | * hb_set_next_many: |
652 | * @set: A set |
653 | * @codepoint: Outputting codepoints starting after this one. |
654 | * Use #HB_SET_VALUE_INVALID to get started. |
655 | * @out: (array length=size): An array of codepoints to write to. |
656 | * @size: The maximum number of codepoints to write out. |
657 | * |
658 | * Finds the next element in @set that is greater than @codepoint. Writes out |
659 | * codepoints to @out, until either the set runs out of elements, or @size |
660 | * codepoints are written, whichever comes first. |
661 | * |
662 | * Return value: the number of values written. |
663 | * |
664 | * Since: 4.2.0 |
665 | **/ |
666 | unsigned int |
667 | hb_set_next_many (const hb_set_t *set, |
668 | hb_codepoint_t codepoint, |
669 | hb_codepoint_t *out, |
670 | unsigned int size) |
671 | { |
672 | return set->next_many (codepoint, out, size); |
673 | } |
674 | |