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: (Xconstructor)
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 *
hb_set_create()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 set->init_shallow ();
60
61 return set;
62 }
63
64 /**
65 * hb_set_get_empty:
66 *
67 * Fetches the singleton empty #hb_set_t.
68 *
69 * Return value: (transfer full): The empty #hb_set_t
70 *
71 * Since: 0.9.2
72 **/
73 hb_set_t *
hb_set_get_empty()74 hb_set_get_empty ()
75 {
76 return const_cast<hb_set_t *> (&Null (hb_set_t));
77 }
78
79 /**
80 * hb_set_reference: (skip)
81 * @set: A set
82 *
83 * Increases the reference count on a set.
84 *
85 * Return value: (transfer full): The set
86 *
87 * Since: 0.9.2
88 **/
89 hb_set_t *
hb_set_reference(hb_set_t * set)90 hb_set_reference (hb_set_t *set)
91 {
92 return hb_object_reference (set);
93 }
94
95 /**
96 * hb_set_destroy: (skip)
97 * @set: A set
98 *
99 * Decreases the reference count on a set. When
100 * the reference count reaches zero, the set is
101 * destroyed, freeing all memory.
102 *
103 * Since: 0.9.2
104 **/
105 void
hb_set_destroy(hb_set_t * set)106 hb_set_destroy (hb_set_t *set)
107 {
108 if (!hb_object_destroy (set)) return;
109
110 set->fini_shallow ();
111
112 hb_free (set);
113 }
114
115 /**
116 * hb_set_set_user_data: (skip)
117 * @set: A set
118 * @key: The user-data key to set
119 * @data: A pointer to the user data to set
120 * @destroy: (nullable): A callback to call when @data is not needed anymore
121 * @replace: Whether to replace an existing data with the same key
122 *
123 * Attaches a user-data key/data pair to the specified set.
124 *
125 * Return value: %true if success, %false otherwise
126 *
127 * Since: 0.9.2
128 **/
129 hb_bool_t
hb_set_set_user_data(hb_set_t * set,hb_user_data_key_t * key,void * data,hb_destroy_func_t destroy,hb_bool_t replace)130 hb_set_set_user_data (hb_set_t *set,
131 hb_user_data_key_t *key,
132 void * data,
133 hb_destroy_func_t destroy,
134 hb_bool_t replace)
135 {
136 return hb_object_set_user_data (set, key, data, destroy, replace);
137 }
138
139 /**
140 * hb_set_get_user_data: (skip)
141 * @set: A set
142 * @key: The user-data key to query
143 *
144 * Fetches the user data associated with the specified key,
145 * attached to the specified set.
146 *
147 * Return value: (transfer none): A pointer to the user data
148 *
149 * Since: 0.9.2
150 **/
151 void *
hb_set_get_user_data(hb_set_t * set,hb_user_data_key_t * key)152 hb_set_get_user_data (hb_set_t *set,
153 hb_user_data_key_t *key)
154 {
155 return hb_object_get_user_data (set, key);
156 }
157
158
159 /**
160 * hb_set_allocation_successful:
161 * @set: A set
162 *
163 * Tests whether memory allocation for a set was successful.
164 *
165 * Return value: %true if allocation succeeded, %false otherwise
166 *
167 * Since: 0.9.2
168 **/
169 hb_bool_t
hb_set_allocation_successful(const hb_set_t * set)170 hb_set_allocation_successful (const hb_set_t *set)
171 {
172 return !set->in_error ();
173 }
174
175 /**
176 * hb_set_copy:
177 * @set: A set
178 *
179 * Allocate a copy of @set.
180 *
181 * Return value: Newly-allocated set.
182 *
183 * Since: 2.8.2
184 **/
185 hb_set_t *
hb_set_copy(const hb_set_t * set)186 hb_set_copy (const hb_set_t *set)
187 {
188 hb_set_t *copy = hb_set_create ();
189 copy->set (*set);
190 return copy;
191 }
192
193 /**
194 * hb_set_clear:
195 * @set: A set
196 *
197 * Clears out the contents of a set.
198 *
199 * Since: 0.9.2
200 **/
201 void
hb_set_clear(hb_set_t * set)202 hb_set_clear (hb_set_t *set)
203 {
204 /* Immutible-safe. */
205 set->clear ();
206 }
207
208 /**
209 * hb_set_is_empty:
210 * @set: a set.
211 *
212 * Tests whether a set is empty (contains no elements).
213 *
214 * Return value: %true if @set is empty
215 *
216 * Since: 0.9.7
217 **/
218 hb_bool_t
hb_set_is_empty(const hb_set_t * set)219 hb_set_is_empty (const hb_set_t *set)
220 {
221 return set->is_empty ();
222 }
223
224 /**
225 * hb_set_has:
226 * @set: A set
227 * @codepoint: The element to query
228 *
229 * Tests whether @codepoint belongs to @set.
230 *
231 * Return value: %true if @codepoint is in @set, %false otherwise
232 *
233 * Since: 0.9.2
234 **/
235 hb_bool_t
hb_set_has(const hb_set_t * set,hb_codepoint_t codepoint)236 hb_set_has (const hb_set_t *set,
237 hb_codepoint_t codepoint)
238 {
239 return set->has (codepoint);
240 }
241
242 /**
243 * hb_set_add:
244 * @set: A set
245 * @codepoint: The element to add to @set
246 *
247 * Adds @codepoint to @set.
248 *
249 * Since: 0.9.2
250 **/
251 void
hb_set_add(hb_set_t * set,hb_codepoint_t codepoint)252 hb_set_add (hb_set_t *set,
253 hb_codepoint_t codepoint)
254 {
255 /* Immutible-safe. */
256 set->add (codepoint);
257 }
258
259 /**
260 * hb_set_add_range:
261 * @set: A set
262 * @first: The first element to add to @set
263 * @last: The final element to add to @set
264 *
265 * Adds all of the elements from @first to @last
266 * (inclusive) to @set.
267 *
268 * Since: 0.9.7
269 **/
270 void
hb_set_add_range(hb_set_t * set,hb_codepoint_t first,hb_codepoint_t last)271 hb_set_add_range (hb_set_t *set,
272 hb_codepoint_t first,
273 hb_codepoint_t last)
274 {
275 /* Immutible-safe. */
276 set->add_range (first, last);
277 }
278
279 /**
280 * hb_set_del:
281 * @set: A set
282 * @codepoint: Removes @codepoint from @set
283 *
284 * Removes @codepoint from @set.
285 *
286 * Since: 0.9.2
287 **/
288 void
hb_set_del(hb_set_t * set,hb_codepoint_t codepoint)289 hb_set_del (hb_set_t *set,
290 hb_codepoint_t codepoint)
291 {
292 /* Immutible-safe. */
293 set->del (codepoint);
294 }
295
296 /**
297 * hb_set_del_range:
298 * @set: A set
299 * @first: The first element to remove from @set
300 * @last: The final element to remove from @set
301 *
302 * Removes all of the elements from @first to @last
303 * (inclusive) from @set.
304 *
305 * If @last is #HB_SET_VALUE_INVALID, then all values
306 * greater than or equal to @first are removed.
307 *
308 * Since: 0.9.7
309 **/
310 void
hb_set_del_range(hb_set_t * set,hb_codepoint_t first,hb_codepoint_t last)311 hb_set_del_range (hb_set_t *set,
312 hb_codepoint_t first,
313 hb_codepoint_t last)
314 {
315 /* Immutible-safe. */
316 set->del_range (first, last);
317 }
318
319 /**
320 * hb_set_is_equal:
321 * @set: A set
322 * @other: Another set
323 *
324 * Tests whether @set and @other are equal (contain the same
325 * elements).
326 *
327 * Return value: %true if the two sets are equal, %false otherwise.
328 *
329 * Since: 0.9.7
330 **/
331 hb_bool_t
hb_set_is_equal(const hb_set_t * set,const hb_set_t * other)332 hb_set_is_equal (const hb_set_t *set,
333 const hb_set_t *other)
334 {
335 return set->is_equal (*other);
336 }
337
338 /**
339 * hb_set_is_subset:
340 * @set: A set
341 * @larger_set: Another set
342 *
343 * Tests whether @set is a subset of @larger_set.
344 *
345 * Return value: %true if the @set is a subset of (or equal to) @larger_set, %false otherwise.
346 *
347 * Since: 1.8.1
348 **/
349 hb_bool_t
hb_set_is_subset(const hb_set_t * set,const hb_set_t * larger_set)350 hb_set_is_subset (const hb_set_t *set,
351 const hb_set_t *larger_set)
352 {
353 return set->is_subset (*larger_set);
354 }
355
356 /**
357 * hb_set_set:
358 * @set: A set
359 * @other: Another set
360 *
361 * Makes the contents of @set equal to the contents of @other.
362 *
363 * Since: 0.9.2
364 **/
365 void
hb_set_set(hb_set_t * set,const hb_set_t * other)366 hb_set_set (hb_set_t *set,
367 const hb_set_t *other)
368 {
369 /* Immutible-safe. */
370 set->set (*other);
371 }
372
373 /**
374 * hb_set_union:
375 * @set: A set
376 * @other: Another set
377 *
378 * Makes @set the union of @set and @other.
379 *
380 * Since: 0.9.2
381 **/
382 void
hb_set_union(hb_set_t * set,const hb_set_t * other)383 hb_set_union (hb_set_t *set,
384 const hb_set_t *other)
385 {
386 /* Immutible-safe. */
387 set->union_ (*other);
388 }
389
390 /**
391 * hb_set_intersect:
392 * @set: A set
393 * @other: Another set
394 *
395 * Makes @set the intersection of @set and @other.
396 *
397 * Since: 0.9.2
398 **/
399 void
hb_set_intersect(hb_set_t * set,const hb_set_t * other)400 hb_set_intersect (hb_set_t *set,
401 const hb_set_t *other)
402 {
403 /* Immutible-safe. */
404 set->intersect (*other);
405 }
406
407 /**
408 * hb_set_subtract:
409 * @set: A set
410 * @other: Another set
411 *
412 * Subtracts the contents of @other from @set.
413 *
414 * Since: 0.9.2
415 **/
416 void
hb_set_subtract(hb_set_t * set,const hb_set_t * other)417 hb_set_subtract (hb_set_t *set,
418 const hb_set_t *other)
419 {
420 /* Immutible-safe. */
421 set->subtract (*other);
422 }
423
424 /**
425 * hb_set_symmetric_difference:
426 * @set: A set
427 * @other: Another set
428 *
429 * Makes @set the symmetric difference of @set
430 * and @other.
431 *
432 * Since: 0.9.2
433 **/
434 void
hb_set_symmetric_difference(hb_set_t * set,const hb_set_t * other)435 hb_set_symmetric_difference (hb_set_t *set,
436 const hb_set_t *other)
437 {
438 /* Immutible-safe. */
439 set->symmetric_difference (*other);
440 }
441
442 /**
443 * hb_set_invert:
444 * @set: A set
445 *
446 * Inverts the contents of @set.
447 *
448 * Since: 3.0.0
449 **/
450 void
hb_set_invert(hb_set_t * set)451 hb_set_invert (hb_set_t *set)
452 {
453 /* Immutible-safe. */
454 set->invert ();
455 }
456
457 /**
458 * hb_set_get_population:
459 * @set: A set
460 *
461 * Returns the number of elements in the set.
462 *
463 * Return value: The population of @set
464 *
465 * Since: 0.9.7
466 **/
467 unsigned int
hb_set_get_population(const hb_set_t * set)468 hb_set_get_population (const hb_set_t *set)
469 {
470 return set->get_population ();
471 }
472
473 /**
474 * hb_set_get_min:
475 * @set: A set
476 *
477 * Finds the smallest element in the set.
478 *
479 * Return value: minimum of @set, or #HB_SET_VALUE_INVALID if @set is empty.
480 *
481 * Since: 0.9.7
482 **/
483 hb_codepoint_t
hb_set_get_min(const hb_set_t * set)484 hb_set_get_min (const hb_set_t *set)
485 {
486 return set->get_min ();
487 }
488
489 /**
490 * hb_set_get_max:
491 * @set: A set
492 *
493 * Finds the largest element in the set.
494 *
495 * Return value: maximum of @set, or #HB_SET_VALUE_INVALID if @set is empty.
496 *
497 * Since: 0.9.7
498 **/
499 hb_codepoint_t
hb_set_get_max(const hb_set_t * set)500 hb_set_get_max (const hb_set_t *set)
501 {
502 return set->get_max ();
503 }
504
505 /**
506 * hb_set_next:
507 * @set: A set
508 * @codepoint: (inout): Input = Code point to query
509 * Output = Code point retrieved
510 *
511 * Fetches the next element in @set that is greater than current value of @codepoint.
512 *
513 * Set @codepoint to #HB_SET_VALUE_INVALID to get started.
514 *
515 * Return value: %true if there was a next value, %false otherwise
516 *
517 * Since: 0.9.2
518 **/
519 hb_bool_t
hb_set_next(const hb_set_t * set,hb_codepoint_t * codepoint)520 hb_set_next (const hb_set_t *set,
521 hb_codepoint_t *codepoint)
522 {
523 return set->next (codepoint);
524 }
525
526 /**
527 * hb_set_previous:
528 * @set: A set
529 * @codepoint: (inout): Input = Code point to query
530 * Output = Code point retrieved
531 *
532 * Fetches the previous element in @set that is lower than current value of @codepoint.
533 *
534 * Set @codepoint to #HB_SET_VALUE_INVALID to get started.
535 *
536 * Return value: %true if there was a previous value, %false otherwise
537 *
538 * Since: 1.8.0
539 **/
540 hb_bool_t
hb_set_previous(const hb_set_t * set,hb_codepoint_t * codepoint)541 hb_set_previous (const hb_set_t *set,
542 hb_codepoint_t *codepoint)
543 {
544 return set->previous (codepoint);
545 }
546
547 /**
548 * hb_set_next_range:
549 * @set: A set
550 * @first: (out): The first code point in the range
551 * @last: (inout): Input = The current last code point in the range
552 * Output = The last code point in the range
553 *
554 * Fetches the next consecutive range of elements in @set that
555 * are greater than current value of @last.
556 *
557 * Set @last to #HB_SET_VALUE_INVALID to get started.
558 *
559 * Return value: %true if there was a next range, %false otherwise
560 *
561 * Since: 0.9.7
562 **/
563 hb_bool_t
hb_set_next_range(const hb_set_t * set,hb_codepoint_t * first,hb_codepoint_t * last)564 hb_set_next_range (const hb_set_t *set,
565 hb_codepoint_t *first,
566 hb_codepoint_t *last)
567 {
568 return set->next_range (first, last);
569 }
570
571 /**
572 * hb_set_previous_range:
573 * @set: A set
574 * @first: (inout): Input = The current first code point in the range
575 * Output = The first code point in the range
576 * @last: (out): The last code point in the range
577 *
578 * Fetches the previous consecutive range of elements in @set that
579 * are greater than current value of @last.
580 *
581 * Set @first to #HB_SET_VALUE_INVALID to get started.
582 *
583 * Return value: %true if there was a previous range, %false otherwise
584 *
585 * Since: 1.8.0
586 **/
587 hb_bool_t
hb_set_previous_range(const hb_set_t * set,hb_codepoint_t * first,hb_codepoint_t * last)588 hb_set_previous_range (const hb_set_t *set,
589 hb_codepoint_t *first,
590 hb_codepoint_t *last)
591 {
592 return set->previous_range (first, last);
593 }
594