/work/workdir/UnpackedTarball/harfbuzz/src/hb-set.cc
Line | Count | Source |
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 | 124k | { |
54 | 124k | hb_set_t *set; |
55 | | |
56 | 124k | if (!(set = hb_object_create<hb_set_t> ())) |
57 | 0 | return hb_set_get_empty (); |
58 | | |
59 | 124k | return set; |
60 | 124k | } |
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 | 0 | { |
74 | 0 | return const_cast<hb_set_t *> (&Null (hb_set_t)); |
75 | 0 | } |
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 | 0 | { |
90 | 0 | return hb_object_reference (set); |
91 | 0 | } |
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 | 373k | { |
106 | 373k | if (!hb_object_destroy (set)) return; |
107 | | |
108 | 124k | hb_free (set); |
109 | 124k | } |
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 | 0 | { |
132 | 0 | return hb_object_set_user_data (set, key, data, destroy, replace); |
133 | 0 | } |
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 | 0 | { |
151 | 0 | return hb_object_get_user_data (set, key); |
152 | 0 | } |
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 | 0 | { |
168 | 0 | return !set->in_error (); |
169 | 0 | } |
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 | 0 | { |
184 | 0 | hb_set_t *copy = hb_set_create (); |
185 | 0 | if (unlikely (copy->in_error ())) |
186 | 0 | return hb_set_get_empty (); |
187 | | |
188 | 0 | copy->set (*set); |
189 | 0 | return copy; |
190 | 0 | } |
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 | 0 | { |
203 | | /* Immutable-safe. */ |
204 | 0 | set->clear (); |
205 | 0 | } |
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 | 65 | { |
220 | 65 | return set->is_empty (); |
221 | 65 | } |
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 | 66 | { |
238 | 66 | return set->has (codepoint); |
239 | 66 | } |
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 | 496k | { |
254 | | /* Immutable-safe. */ |
255 | 496k | set->add (codepoint); |
256 | 496k | } |
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 | 0 | { |
275 | | /* Immutable-safe. */ |
276 | 0 | set->add_sorted_array (sorted_codepoints, |
277 | 0 | num_codepoints, |
278 | 0 | sizeof(hb_codepoint_t)); |
279 | 0 | } |
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 | 15.5k | { |
297 | | /* Immutable-safe. */ |
298 | 15.5k | set->add_range (first, last); |
299 | 15.5k | } |
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 | 218k | { |
314 | | /* Immutable-safe. */ |
315 | 218k | set->del (codepoint); |
316 | 218k | } |
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 | 0 | { |
337 | | /* Immutable-safe. */ |
338 | 0 | set->del_range (first, last); |
339 | 0 | } |
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 | 0 | { |
357 | 0 | return set->is_equal (*other); |
358 | 0 | } |
359 | | |
360 | | /** |
361 | | * hb_set_intersects: |
362 | | * @set: A set |
363 | | * @other: Another set |
364 | | * |
365 | | * Tests whether @set and @other have any elements in common. |
366 | | * |
367 | | * Return value: `true` if the two sets intersect, `false` otherwise. |
368 | | * |
369 | | * Since: 14.4.0 |
370 | | **/ |
371 | | hb_bool_t |
372 | | hb_set_intersects (const hb_set_t *set, |
373 | | const hb_set_t *other) |
374 | 0 | { |
375 | 0 | return set->intersects (*other); |
376 | 0 | } |
377 | | |
378 | | /** |
379 | | * hb_set_hash: |
380 | | * @set: A set |
381 | | * |
382 | | * Creates a hash representing @set. |
383 | | * |
384 | | * Return value: |
385 | | * A hash of @set. |
386 | | * |
387 | | * Since: 4.4.0 |
388 | | **/ |
389 | | HB_EXTERN unsigned int |
390 | | hb_set_hash (const hb_set_t *set) |
391 | 0 | { |
392 | 0 | return set->hash (); |
393 | 0 | } |
394 | | |
395 | | /** |
396 | | * hb_set_is_subset: |
397 | | * @set: A set |
398 | | * @larger_set: Another set |
399 | | * |
400 | | * Tests whether @set is a subset of @larger_set. |
401 | | * |
402 | | * Return value: `true` if the @set is a subset of (or equal to) @larger_set, `false` otherwise. |
403 | | * |
404 | | * Since: 1.8.1 |
405 | | **/ |
406 | | hb_bool_t |
407 | | hb_set_is_subset (const hb_set_t *set, |
408 | | const hb_set_t *larger_set) |
409 | 0 | { |
410 | 0 | return set->is_subset (*larger_set); |
411 | 0 | } |
412 | | |
413 | | /** |
414 | | * hb_set_set: |
415 | | * @set: A set |
416 | | * @other: Another set |
417 | | * |
418 | | * Makes the contents of @set equal to the contents of @other. |
419 | | * |
420 | | * Since: 0.9.2 |
421 | | **/ |
422 | | void |
423 | | hb_set_set (hb_set_t *set, |
424 | | const hb_set_t *other) |
425 | 0 | { |
426 | | /* Immutable-safe. */ |
427 | 0 | set->set (*other); |
428 | 0 | } |
429 | | |
430 | | /** |
431 | | * hb_set_union: |
432 | | * @set: A set |
433 | | * @other: Another set |
434 | | * |
435 | | * Makes @set the union of @set and @other. |
436 | | * |
437 | | * Since: 0.9.2 |
438 | | **/ |
439 | | void |
440 | | hb_set_union (hb_set_t *set, |
441 | | const hb_set_t *other) |
442 | 0 | { |
443 | | /* Immutable-safe. */ |
444 | 0 | set->union_ (*other); |
445 | 0 | } |
446 | | |
447 | | /** |
448 | | * hb_set_intersect: |
449 | | * @set: A set |
450 | | * @other: Another set |
451 | | * |
452 | | * Makes @set the intersection of @set and @other. |
453 | | * |
454 | | * Since: 0.9.2 |
455 | | **/ |
456 | | void |
457 | | hb_set_intersect (hb_set_t *set, |
458 | | const hb_set_t *other) |
459 | 0 | { |
460 | | /* Immutable-safe. */ |
461 | 0 | set->intersect (*other); |
462 | 0 | } |
463 | | |
464 | | /** |
465 | | * hb_set_subtract: |
466 | | * @set: A set |
467 | | * @other: Another set |
468 | | * |
469 | | * Subtracts the contents of @other from @set. |
470 | | * |
471 | | * Since: 0.9.2 |
472 | | **/ |
473 | | void |
474 | | hb_set_subtract (hb_set_t *set, |
475 | | const hb_set_t *other) |
476 | 0 | { |
477 | | /* Immutable-safe. */ |
478 | 0 | set->subtract (*other); |
479 | 0 | } |
480 | | |
481 | | /** |
482 | | * hb_set_symmetric_difference: |
483 | | * @set: A set |
484 | | * @other: Another set |
485 | | * |
486 | | * Makes @set the symmetric difference of @set |
487 | | * and @other. |
488 | | * |
489 | | * Since: 0.9.2 |
490 | | **/ |
491 | | void |
492 | | hb_set_symmetric_difference (hb_set_t *set, |
493 | | const hb_set_t *other) |
494 | 0 | { |
495 | | /* Immutable-safe. */ |
496 | 0 | set->symmetric_difference (*other); |
497 | 0 | } |
498 | | |
499 | | /** |
500 | | * hb_set_invert: |
501 | | * @set: A set |
502 | | * |
503 | | * Inverts the contents of @set. |
504 | | * |
505 | | * Since: 3.0.0 |
506 | | **/ |
507 | | void |
508 | | hb_set_invert (hb_set_t *set) |
509 | 15.5k | { |
510 | | /* Immutable-safe. */ |
511 | 15.5k | set->invert (); |
512 | 15.5k | } |
513 | | |
514 | | /** |
515 | | * hb_set_is_inverted: |
516 | | * @set: A set |
517 | | * |
518 | | * Returns whether the set is inverted. |
519 | | * |
520 | | * Return value: `true` if the set is inverted, `false` otherwise |
521 | | * |
522 | | * Since: 7.0.0 |
523 | | **/ |
524 | | hb_bool_t |
525 | | hb_set_is_inverted (const hb_set_t *set) |
526 | 0 | { |
527 | 0 | return set->is_inverted (); |
528 | 0 | } |
529 | | |
530 | | /** |
531 | | * hb_set_get_population: |
532 | | * @set: A set |
533 | | * |
534 | | * Returns the number of elements in the set. |
535 | | * |
536 | | * Return value: The population of @set |
537 | | * |
538 | | * Since: 0.9.7 |
539 | | **/ |
540 | | unsigned int |
541 | | hb_set_get_population (const hb_set_t *set) |
542 | 5 | { |
543 | 5 | return set->get_population (); |
544 | 5 | } |
545 | | |
546 | | /** |
547 | | * hb_set_get_min: |
548 | | * @set: A set |
549 | | * |
550 | | * Finds the smallest element in the set. |
551 | | * |
552 | | * Return value: minimum of @set, or #HB_SET_VALUE_INVALID if @set is empty. |
553 | | * |
554 | | * Since: 0.9.7 |
555 | | **/ |
556 | | hb_codepoint_t |
557 | | hb_set_get_min (const hb_set_t *set) |
558 | 0 | { |
559 | 0 | return set->get_min (); |
560 | 0 | } |
561 | | |
562 | | /** |
563 | | * hb_set_get_max: |
564 | | * @set: A set |
565 | | * |
566 | | * Finds the largest element in the set. |
567 | | * |
568 | | * Return value: maximum of @set, or #HB_SET_VALUE_INVALID if @set is empty. |
569 | | * |
570 | | * Since: 0.9.7 |
571 | | **/ |
572 | | hb_codepoint_t |
573 | | hb_set_get_max (const hb_set_t *set) |
574 | 0 | { |
575 | 0 | return set->get_max (); |
576 | 0 | } |
577 | | |
578 | | /** |
579 | | * hb_set_next: |
580 | | * @set: A set |
581 | | * @codepoint: (inout): Input = Code point to query |
582 | | * Output = Code point retrieved |
583 | | * |
584 | | * Fetches the next element in @set that is greater than current value of @codepoint. |
585 | | * |
586 | | * Set @codepoint to #HB_SET_VALUE_INVALID to get started. |
587 | | * |
588 | | * Return value: `true` if there was a next value, `false` otherwise |
589 | | * |
590 | | * Since: 0.9.2 |
591 | | **/ |
592 | | hb_bool_t |
593 | | hb_set_next (const hb_set_t *set, |
594 | | hb_codepoint_t *codepoint) |
595 | 0 | { |
596 | 0 | return set->next (codepoint); |
597 | 0 | } |
598 | | |
599 | | /** |
600 | | * hb_set_previous: |
601 | | * @set: A set |
602 | | * @codepoint: (inout): Input = Code point to query |
603 | | * Output = Code point retrieved |
604 | | * |
605 | | * Fetches the previous element in @set that is lower than current value of @codepoint. |
606 | | * |
607 | | * Set @codepoint to #HB_SET_VALUE_INVALID to get started. |
608 | | * |
609 | | * Return value: `true` if there was a previous value, `false` otherwise |
610 | | * |
611 | | * Since: 1.8.0 |
612 | | **/ |
613 | | hb_bool_t |
614 | | hb_set_previous (const hb_set_t *set, |
615 | | hb_codepoint_t *codepoint) |
616 | 15.5k | { |
617 | 15.5k | return set->previous (codepoint); |
618 | 15.5k | } |
619 | | |
620 | | /** |
621 | | * hb_set_next_range: |
622 | | * @set: A set |
623 | | * @first: (out): The first code point in the range |
624 | | * @last: (inout): Input = The current last code point in the range |
625 | | * Output = The last code point in the range |
626 | | * |
627 | | * Fetches the next consecutive range of elements in @set that |
628 | | * are greater than current value of @last. |
629 | | * |
630 | | * Set @last to #HB_SET_VALUE_INVALID to get started. |
631 | | * |
632 | | * Return value: `true` if there was a next range, `false` otherwise |
633 | | * |
634 | | * Since: 0.9.7 |
635 | | **/ |
636 | | hb_bool_t |
637 | | hb_set_next_range (const hb_set_t *set, |
638 | | hb_codepoint_t *first, |
639 | | hb_codepoint_t *last) |
640 | 630 | { |
641 | 630 | return set->next_range (first, last); |
642 | 630 | } |
643 | | |
644 | | /** |
645 | | * hb_set_previous_range: |
646 | | * @set: A set |
647 | | * @first: (inout): Input = The current first code point in the range |
648 | | * Output = The first code point in the range |
649 | | * @last: (out): The last code point in the range |
650 | | * |
651 | | * Fetches the previous consecutive range of elements in @set that |
652 | | * are greater than current value of @last. |
653 | | * |
654 | | * Set @first to #HB_SET_VALUE_INVALID to get started. |
655 | | * |
656 | | * Return value: `true` if there was a previous range, `false` otherwise |
657 | | * |
658 | | * Since: 1.8.0 |
659 | | **/ |
660 | | hb_bool_t |
661 | | hb_set_previous_range (const hb_set_t *set, |
662 | | hb_codepoint_t *first, |
663 | | hb_codepoint_t *last) |
664 | 0 | { |
665 | 0 | return set->previous_range (first, last); |
666 | 0 | } |
667 | | |
668 | | /** |
669 | | * hb_set_next_many: |
670 | | * @set: A set |
671 | | * @codepoint: Outputting codepoints starting after this one. |
672 | | * Use #HB_SET_VALUE_INVALID to get started. |
673 | | * @out: (array length=size): An array of codepoints to write to. |
674 | | * @size: The maximum number of codepoints to write out. |
675 | | * |
676 | | * Finds the next element in @set that is greater than @codepoint. Writes out |
677 | | * codepoints to @out, until either the set runs out of elements, or @size |
678 | | * codepoints are written, whichever comes first. |
679 | | * |
680 | | * Return value: the number of values written. |
681 | | * |
682 | | * Since: 4.2.0 |
683 | | **/ |
684 | | unsigned int |
685 | | hb_set_next_many (const hb_set_t *set, |
686 | | hb_codepoint_t codepoint, |
687 | | hb_codepoint_t *out, |
688 | | unsigned int size) |
689 | 0 | { |
690 | 0 | return set->next_many (codepoint, out, size); |
691 | 0 | } |