• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2012,2017  Google, Inc.
3  * Copyright © 2021 Behdad Esfahbod
4  *
5  *  This is part of HarfBuzz, a text shaping library.
6  *
7  * Permission is hereby granted, without written agreement and without
8  * license or royalty fees, to use, copy, modify, and distribute this
9  * software and its documentation for any purpose, provided that the
10  * above copyright notice and the following two paragraphs appear in
11  * all copies of this software.
12  *
13  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17  * DAMAGE.
18  *
19  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24  *
25  * Google Author(s): Behdad Esfahbod
26  */
27 
28 #ifndef HB_BIT_SET_HH
29 #define HB_BIT_SET_HH
30 
31 #include "hb.hh"
32 #include "hb-bit-page.hh"
33 #include "hb-machinery.hh"
34 
35 
36 struct hb_bit_set_t
37 {
38   hb_bit_set_t () = default;
39   ~hb_bit_set_t () = default;
40 
hb_bit_set_thb_bit_set_t41   hb_bit_set_t (const hb_bit_set_t& other) : hb_bit_set_t () { set (other); }
hb_bit_set_thb_bit_set_t42   hb_bit_set_t ( hb_bit_set_t&& other) : hb_bit_set_t () { hb_swap (*this, other); }
operator =hb_bit_set_t43   hb_bit_set_t& operator= (const hb_bit_set_t& other) { set (other); return *this; }
operator =hb_bit_set_t44   hb_bit_set_t& operator= (hb_bit_set_t&& other) { hb_swap (*this, other); return *this; }
swap(hb_bit_set_t & a,hb_bit_set_t & b)45   friend void swap (hb_bit_set_t &a, hb_bit_set_t &b)
46   {
47     if (likely (!a.successful || !b.successful))
48       return;
49     hb_swap (a.population, b.population);
50     hb_swap (a.last_page_lookup, b.last_page_lookup);
51     hb_swap (a.page_map, b.page_map);
52     hb_swap (a.pages, b.pages);
53   }
54 
inithb_bit_set_t55   void init ()
56   {
57     successful = true;
58     population = 0;
59     last_page_lookup = 0;
60     page_map.init ();
61     pages.init ();
62   }
finihb_bit_set_t63   void fini ()
64   {
65     page_map.fini ();
66     pages.fini ();
67   }
68 
69   using page_t = hb_bit_page_t;
70   struct page_map_t
71   {
cmphb_bit_set_t::page_map_t72     int cmp (const page_map_t &o) const { return cmp (o.major); }
cmphb_bit_set_t::page_map_t73     int cmp (uint32_t o_major) const { return (int) o_major - (int) major; }
74 
75     uint32_t major;
76     uint32_t index;
77   };
78 
79   bool successful = true; /* Allocations successful */
80   mutable unsigned int population = 0;
81   mutable hb_atomic_int_t last_page_lookup = 0;
82   hb_sorted_vector_t<page_map_t> page_map;
83   hb_vector_t<page_t> pages;
84 
errhb_bit_set_t85   void err () { if (successful) successful = false; } /* TODO Remove */
in_errorhb_bit_set_t86   bool in_error () const { return !successful; }
87 
resizehb_bit_set_t88   bool resize (unsigned int count, bool clear = true)
89   {
90     if (unlikely (!successful)) return false;
91     if (unlikely (!pages.resize (count, clear) || !page_map.resize (count, clear)))
92     {
93       pages.resize (page_map.length);
94       successful = false;
95       return false;
96     }
97     return true;
98   }
99 
allochb_bit_set_t100   void alloc (unsigned sz)
101   {
102     sz >>= (page_t::PAGE_BITS_LOG_2 - 1);
103     pages.alloc (sz);
104     page_map.alloc (sz);
105   }
106 
resethb_bit_set_t107   void reset ()
108   {
109     successful = true;
110     clear ();
111   }
112 
clearhb_bit_set_t113   void clear ()
114   {
115     resize (0);
116     if (likely (successful))
117       population = 0;
118   }
is_emptyhb_bit_set_t119   bool is_empty () const
120   {
121     unsigned int count = pages.length;
122     for (unsigned int i = 0; i < count; i++)
123       if (!pages[i].is_empty ())
124 	return false;
125     return true;
126   }
operator boolhb_bit_set_t127   explicit operator bool () const { return !is_empty (); }
128 
hashhb_bit_set_t129   uint32_t hash () const
130   {
131     uint32_t h = 0;
132     for (auto &map : page_map)
133       h = h * 31 + hb_hash (map.major) + hb_hash (pages[map.index]);
134     return h;
135   }
136 
137   private:
dirtyhb_bit_set_t138   void dirty () { population = UINT_MAX; }
139   public:
140 
addhb_bit_set_t141   void add (hb_codepoint_t g)
142   {
143     if (unlikely (!successful)) return;
144     if (unlikely (g == INVALID)) return;
145     dirty ();
146     page_t *page = page_for (g, true); if (unlikely (!page)) return;
147     page->add (g);
148   }
add_rangehb_bit_set_t149   bool add_range (hb_codepoint_t a, hb_codepoint_t b)
150   {
151     if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
152     if (unlikely (a > b || a == INVALID || b == INVALID)) return false;
153     dirty ();
154     unsigned int ma = get_major (a);
155     unsigned int mb = get_major (b);
156     if (ma == mb)
157     {
158       page_t *page = page_for (a, true); if (unlikely (!page)) return false;
159       page->add_range (a, b);
160     }
161     else
162     {
163       page_t *page = page_for (a, true); if (unlikely (!page)) return false;
164       page->add_range (a, major_start (ma + 1) - 1);
165 
166       for (unsigned int m = ma + 1; m < mb; m++)
167       {
168 	page = page_for (major_start (m), true); if (unlikely (!page)) return false;
169 	page->init1 ();
170       }
171 
172       page = page_for (b, true); if (unlikely (!page)) return false;
173       page->add_range (major_start (mb), b);
174     }
175     return true;
176   }
177 
178   template <typename T>
set_arrayhb_bit_set_t179   void set_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
180   {
181     if (unlikely (!successful)) return;
182     if (!count) return;
183     dirty ();
184     hb_codepoint_t g = *array;
185     while (count)
186     {
187       unsigned int m = get_major (g);
188       page_t *page = page_for (g, v); if (unlikely (v && !page)) return;
189       unsigned int start = major_start (m);
190       unsigned int end = major_start (m + 1);
191       do
192       {
193         if (v || page) /* The v check is to optimize out the page check if v is true. */
194 	  page->set (g, v);
195 
196 	array = &StructAtOffsetUnaligned<T> (array, stride);
197 	count--;
198       }
199       while (count && (g = *array, start <= g && g < end));
200     }
201   }
202 
203   template <typename T>
add_arrayhb_bit_set_t204   void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
205   { set_array (true, array, count, stride); }
206   template <typename T>
add_arrayhb_bit_set_t207   void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
208 
209   template <typename T>
del_arrayhb_bit_set_t210   void del_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
211   { set_array (false, array, count, stride); }
212   template <typename T>
del_arrayhb_bit_set_t213   void del_array (const hb_array_t<const T>& arr) { del_array (&arr, arr.len ()); }
214 
215   /* Might return false if array looks unsorted.
216    * Used for faster rejection of corrupt data. */
217   template <typename T>
set_sorted_arrayhb_bit_set_t218   bool set_sorted_array (bool v, const T *array, unsigned int count, unsigned int stride=sizeof(T))
219   {
220     if (unlikely (!successful)) return true; /* https://github.com/harfbuzz/harfbuzz/issues/657 */
221     if (unlikely (!count)) return true;
222     dirty ();
223     hb_codepoint_t g = *array;
224     hb_codepoint_t last_g = g;
225     while (count)
226     {
227       unsigned int m = get_major (g);
228       page_t *page = page_for (g, v); if (unlikely (v && !page)) return false;
229       unsigned int end = major_start (m + 1);
230       do
231       {
232 	/* If we try harder we can change the following comparison to <=;
233 	 * Not sure if it's worth it. */
234 	if (g < last_g) return false;
235 	last_g = g;
236 
237         if (v || page) /* The v check is to optimize out the page check if v is true. */
238 	  page->add (g);
239 
240 	array = &StructAtOffsetUnaligned<T> (array, stride);
241 	count--;
242       }
243       while (count && (g = *array, g < end));
244     }
245     return true;
246   }
247 
248   template <typename T>
add_sorted_arrayhb_bit_set_t249   bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
250   { return set_sorted_array (true, array, count, stride); }
251   template <typename T>
add_sorted_arrayhb_bit_set_t252   bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
253 
254   template <typename T>
del_sorted_arrayhb_bit_set_t255   bool del_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
256   { return set_sorted_array (false, array, count, stride); }
257   template <typename T>
del_sorted_arrayhb_bit_set_t258   bool del_sorted_array (const hb_sorted_array_t<const T>& arr) { return del_sorted_array (&arr, arr.len ()); }
259 
delhb_bit_set_t260   void del (hb_codepoint_t g)
261   {
262     if (unlikely (!successful)) return;
263     page_t *page = page_for (g);
264     if (!page)
265       return;
266     dirty ();
267     page->del (g);
268   }
269 
270   private:
del_pageshb_bit_set_t271   void del_pages (int ds, int de)
272   {
273     if (ds <= de)
274     {
275       // Pre-allocate the workspace that compact() will need so we can bail on allocation failure
276       // before attempting to rewrite the page map.
277       hb_vector_t<unsigned> compact_workspace;
278       if (unlikely (!allocate_compact_workspace (compact_workspace))) return;
279 
280       unsigned int write_index = 0;
281       for (unsigned int i = 0; i < page_map.length; i++)
282       {
283 	int m = (int) page_map[i].major;
284 	if (m < ds || de < m)
285 	  page_map[write_index++] = page_map[i];
286       }
287       compact (compact_workspace, write_index);
288       resize (write_index);
289     }
290   }
291 
292 
293   public:
del_rangehb_bit_set_t294   void del_range (hb_codepoint_t a, hb_codepoint_t b)
295   {
296     if (unlikely (!successful)) return;
297     if (unlikely (a > b || a == INVALID)) return;
298     dirty ();
299     unsigned int ma = get_major (a);
300     unsigned int mb = get_major (b);
301     /* Delete pages from ds through de if ds <= de. */
302     int ds = (a == major_start (ma))? (int) ma: (int) (ma + 1);
303     int de = (b + 1 == major_start (mb + 1))? (int) mb: ((int) mb - 1);
304     if (ds > de || (int) ma < ds)
305     {
306       page_t *page = page_for (a);
307       if (page)
308       {
309 	if (ma == mb)
310 	  page->del_range (a, b);
311 	else
312 	  page->del_range (a, major_start (ma + 1) - 1);
313       }
314     }
315     if (de < (int) mb && ma != mb)
316     {
317       page_t *page = page_for (b);
318       if (page)
319 	page->del_range (major_start (mb), b);
320     }
321     del_pages (ds, de);
322   }
323 
gethb_bit_set_t324   bool get (hb_codepoint_t g) const
325   {
326     const page_t *page = page_for (g);
327     if (!page)
328       return false;
329     return page->get (g);
330   }
331 
332   /* Has interface. */
operator []hb_bit_set_t333   bool operator [] (hb_codepoint_t k) const { return get (k); }
hashb_bit_set_t334   bool has (hb_codepoint_t k) const { return (*this)[k]; }
335   /* Predicate. */
operator ()hb_bit_set_t336   bool operator () (hb_codepoint_t k) const { return has (k); }
337 
338   /* Sink interface. */
operator <<hb_bit_set_t339   hb_bit_set_t& operator << (hb_codepoint_t v)
340   { add (v); return *this; }
operator <<hb_bit_set_t341   hb_bit_set_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range)
342   { add_range (range.first, range.second); return *this; }
343 
intersectshb_bit_set_t344   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
345   {
346     hb_codepoint_t c = first - 1;
347     return next (&c) && c <= last;
348   }
sethb_bit_set_t349   void set (const hb_bit_set_t &other)
350   {
351     if (unlikely (!successful)) return;
352     unsigned int count = other.pages.length;
353     if (unlikely (!resize (count, false)))
354       return;
355     population = other.population;
356 
357     page_map = other.page_map;
358     pages = other.pages;
359   }
360 
is_equalhb_bit_set_t361   bool is_equal (const hb_bit_set_t &other) const
362   {
363     if (has_population () && other.has_population () &&
364 	population != other.population)
365       return false;
366 
367     unsigned int na = pages.length;
368     unsigned int nb = other.pages.length;
369 
370     unsigned int a = 0, b = 0;
371     for (; a < na && b < nb; )
372     {
373       if (page_at (a).is_empty ()) { a++; continue; }
374       if (other.page_at (b).is_empty ()) { b++; continue; }
375       if (page_map[a].major != other.page_map[b].major ||
376 	  !page_at (a).is_equal (other.page_at (b)))
377 	return false;
378       a++;
379       b++;
380     }
381     for (; a < na; a++)
382       if (!page_at (a).is_empty ()) { return false; }
383     for (; b < nb; b++)
384       if (!other.page_at (b).is_empty ()) { return false; }
385 
386     return true;
387   }
388 
is_subsethb_bit_set_t389   bool is_subset (const hb_bit_set_t &larger_set) const
390   {
391     if (has_population () && larger_set.has_population () &&
392 	population > larger_set.population)
393       return false;
394 
395     uint32_t spi = 0;
396     for (uint32_t lpi = 0; spi < page_map.length && lpi < larger_set.page_map.length; lpi++)
397     {
398       uint32_t spm = page_map[spi].major;
399       uint32_t lpm = larger_set.page_map[lpi].major;
400       auto sp = page_at (spi);
401       auto lp = larger_set.page_at (lpi);
402 
403       if (spm < lpm && !sp.is_empty ())
404         return false;
405 
406       if (lpm < spm)
407         continue;
408 
409       if (!sp.is_subset (lp))
410         return false;
411 
412       spi++;
413     }
414 
415     while (spi < page_map.length)
416       if (!page_at (spi++).is_empty ())
417         return false;
418 
419     return true;
420   }
421 
422   private:
allocate_compact_workspacehb_bit_set_t423   bool allocate_compact_workspace (hb_vector_t<unsigned>& workspace)
424   {
425     if (unlikely (!workspace.resize (pages.length)))
426     {
427       successful = false;
428       return false;
429     }
430 
431     return true;
432   }
433 
434   /*
435    * workspace should be a pre-sized vector allocated to hold at exactly pages.length
436    * elements.
437    */
compacthb_bit_set_t438   void compact (hb_vector_t<unsigned>& workspace,
439                 unsigned int length)
440   {
441     assert(workspace.length == pages.length);
442     hb_vector_t<unsigned>& old_index_to_page_map_index = workspace;
443 
444     hb_fill (old_index_to_page_map_index.writer(), 0xFFFFFFFF);
445     for (unsigned i = 0; i < length; i++)
446       old_index_to_page_map_index[page_map[i].index] =  i;
447 
448     compact_pages (old_index_to_page_map_index);
449   }
compact_pageshb_bit_set_t450   void compact_pages (const hb_vector_t<unsigned>& old_index_to_page_map_index)
451   {
452     unsigned int write_index = 0;
453     for (unsigned int i = 0; i < pages.length; i++)
454     {
455       if (old_index_to_page_map_index[i] == 0xFFFFFFFF) continue;
456 
457       if (write_index < i)
458 	pages[write_index] = pages[i];
459 
460       page_map[old_index_to_page_map_index[i]].index = write_index;
461       write_index++;
462     }
463   }
464   public:
465 
process_hb_bit_set_t466   void process_ (hb_bit_page_t::vector_t (*op) (const hb_bit_page_t::vector_t &, const hb_bit_page_t::vector_t &),
467 		 bool passthru_left, bool passthru_right,
468 		 const hb_bit_set_t &other)
469   {
470     if (unlikely (!successful)) return;
471 
472     dirty ();
473 
474     unsigned int na = pages.length;
475     unsigned int nb = other.pages.length;
476     unsigned int next_page = na;
477 
478     unsigned int count = 0, newCount = 0;
479     unsigned int a = 0, b = 0;
480     unsigned int write_index = 0;
481 
482     // Pre-allocate the workspace that compact() will need so we can bail on allocation failure
483     // before attempting to rewrite the page map.
484     hb_vector_t<unsigned> compact_workspace;
485     if (!passthru_left && unlikely (!allocate_compact_workspace (compact_workspace))) return;
486 
487     for (; a < na && b < nb; )
488     {
489       if (page_map[a].major == other.page_map[b].major)
490       {
491 	if (!passthru_left)
492 	{
493 	  // Move page_map entries that we're keeping from the left side set
494 	  // to the front of the page_map vector. This isn't necessary if
495 	  // passthru_left is set since no left side pages will be removed
496 	  // in that case.
497 	  if (write_index < a)
498 	    page_map[write_index] = page_map[a];
499 	  write_index++;
500 	}
501 
502 	count++;
503 	a++;
504 	b++;
505       }
506       else if (page_map[a].major < other.page_map[b].major)
507       {
508 	if (passthru_left)
509 	  count++;
510 	a++;
511       }
512       else
513       {
514 	if (passthru_right)
515 	  count++;
516 	b++;
517       }
518     }
519     if (passthru_left)
520       count += na - a;
521     if (passthru_right)
522       count += nb - b;
523 
524     if (!passthru_left)
525     {
526       na  = write_index;
527       next_page = write_index;
528       compact (compact_workspace, write_index);
529     }
530 
531     if (unlikely (!resize (count)))
532       return;
533 
534     newCount = count;
535 
536     /* Process in-place backward. */
537     a = na;
538     b = nb;
539     for (; a && b; )
540     {
541       if (page_map.arrayZ[a - 1].major == other.page_map.arrayZ[b - 1].major)
542       {
543 	a--;
544 	b--;
545 	count--;
546 	page_map.arrayZ[count] = page_map.arrayZ[a];
547 	page_at (count).v = op (page_at (a).v, other.page_at (b).v);
548       }
549       else if (page_map.arrayZ[a - 1].major > other.page_map.arrayZ[b - 1].major)
550       {
551 	a--;
552 	if (passthru_left)
553 	{
554 	  count--;
555 	  page_map.arrayZ[count] = page_map.arrayZ[a];
556 	}
557       }
558       else
559       {
560 	b--;
561 	if (passthru_right)
562 	{
563 	  count--;
564 	  page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
565 	  page_map.arrayZ[count].index = next_page++;
566 	  page_at (count).v = other.page_at (b).v;
567 	}
568       }
569     }
570     if (passthru_left)
571       while (a)
572       {
573 	a--;
574 	count--;
575 	page_map.arrayZ[count] = page_map.arrayZ[a];
576       }
577     if (passthru_right)
578       while (b)
579       {
580 	b--;
581 	count--;
582 	page_map.arrayZ[count].major = other.page_map.arrayZ[b].major;
583 	page_map.arrayZ[count].index = next_page++;
584 	page_at (count).v = other.page_at (b).v;
585       }
586     assert (!count);
587     resize (newCount);
588   }
589   template <typename Op>
590   static hb_bit_page_t::vector_t
op_hb_bit_set_t591   op_ (const hb_bit_page_t::vector_t &a, const hb_bit_page_t::vector_t &b)
592   { return Op{} (a, b); }
593   template <typename Op>
processhb_bit_set_t594   void process (const Op& op, const hb_bit_set_t &other)
595   {
596     process_ (op_<Op>, op (1, 0), op (0, 1), other);
597   }
598 
union_hb_bit_set_t599   void union_ (const hb_bit_set_t &other) { process (hb_bitwise_or, other); }
intersecthb_bit_set_t600   void intersect (const hb_bit_set_t &other) { process (hb_bitwise_and, other); }
subtracthb_bit_set_t601   void subtract (const hb_bit_set_t &other) { process (hb_bitwise_gt, other); }
symmetric_differencehb_bit_set_t602   void symmetric_difference (const hb_bit_set_t &other) { process (hb_bitwise_xor, other); }
603 
nexthb_bit_set_t604   bool next (hb_codepoint_t *codepoint) const
605   {
606     if (unlikely (*codepoint == INVALID)) {
607       *codepoint = get_min ();
608       return *codepoint != INVALID;
609     }
610 
611     const auto* page_map_array = page_map.arrayZ;
612     unsigned int major = get_major (*codepoint);
613     unsigned int i = last_page_lookup;
614 
615     if (unlikely (i >= page_map.length || page_map_array[i].major != major))
616     {
617       page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
618       if (i >= page_map.length) {
619         *codepoint = INVALID;
620         return false;
621       }
622     }
623 
624     const auto* pages_array = pages.arrayZ;
625     const page_map_t &current = page_map_array[i];
626     if (likely (current.major == major))
627     {
628       if (pages_array[current.index].next (codepoint))
629       {
630         *codepoint += current.major * page_t::PAGE_BITS;
631         last_page_lookup = i;
632         return true;
633       }
634       i++;
635     }
636 
637     for (; i < page_map.length; i++)
638     {
639       const page_map_t &current = page_map_array[i];
640       hb_codepoint_t m = pages_array[current.index].get_min ();
641       if (m != INVALID)
642       {
643 	*codepoint = current.major * page_t::PAGE_BITS + m;
644         last_page_lookup = i;
645 	return true;
646       }
647     }
648     last_page_lookup = 0;
649     *codepoint = INVALID;
650     return false;
651   }
previoushb_bit_set_t652   bool previous (hb_codepoint_t *codepoint) const
653   {
654     if (unlikely (*codepoint == INVALID)) {
655       *codepoint = get_max ();
656       return *codepoint != INVALID;
657     }
658 
659     page_map_t map = {get_major (*codepoint), 0};
660     unsigned int i;
661     page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST);
662     if (i < page_map.length && page_map.arrayZ[i].major == map.major)
663     {
664       if (pages[page_map.arrayZ[i].index].previous (codepoint))
665       {
666 	*codepoint += page_map.arrayZ[i].major * page_t::PAGE_BITS;
667 	return true;
668       }
669     }
670     i--;
671     for (; (int) i >= 0; i--)
672     {
673       hb_codepoint_t m = pages.arrayZ[page_map.arrayZ[i].index].get_max ();
674       if (m != INVALID)
675       {
676 	*codepoint = page_map.arrayZ[i].major * page_t::PAGE_BITS + m;
677 	return true;
678       }
679     }
680     *codepoint = INVALID;
681     return false;
682   }
next_rangehb_bit_set_t683   bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
684   {
685     hb_codepoint_t i;
686 
687     i = *last;
688     if (!next (&i))
689     {
690       *last = *first = INVALID;
691       return false;
692     }
693 
694     /* TODO Speed up. */
695     *last = *first = i;
696     while (next (&i) && i == *last + 1)
697       (*last)++;
698 
699     return true;
700   }
previous_rangehb_bit_set_t701   bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
702   {
703     hb_codepoint_t i;
704 
705     i = *first;
706     if (!previous (&i))
707     {
708       *last = *first = INVALID;
709       return false;
710     }
711 
712     /* TODO Speed up. */
713     *last = *first = i;
714     while (previous (&i) && i == *first - 1)
715       (*first)--;
716 
717     return true;
718   }
719 
next_manyhb_bit_set_t720   unsigned int next_many (hb_codepoint_t  codepoint,
721 			  hb_codepoint_t *out,
722 			  unsigned int    size) const
723   {
724     // By default, start at the first bit of the first page of values.
725     unsigned int start_page = 0;
726     unsigned int start_page_value = 0;
727     if (unlikely (codepoint != INVALID))
728     {
729       const auto* page_map_array = page_map.arrayZ;
730       unsigned int major = get_major (codepoint);
731       unsigned int i = last_page_lookup;
732       if (unlikely (i >= page_map.length || page_map_array[i].major != major))
733       {
734 	page_map.bfind (major, &i, HB_NOT_FOUND_STORE_CLOSEST);
735 	if (i >= page_map.length)
736 	  return 0;  // codepoint is greater than our max element.
737       }
738       start_page = i;
739       start_page_value = page_remainder (codepoint + 1);
740       if (unlikely (start_page_value == 0))
741       {
742         // The export-after value was last in the page. Start on next page.
743         start_page++;
744         start_page_value = 0;
745       }
746     }
747 
748     unsigned int initial_size = size;
749     for (unsigned int i = start_page; i < page_map.length && size; i++)
750     {
751       uint32_t base = major_start (page_map[i].major);
752       unsigned int n = pages[page_map[i].index].write (base, start_page_value, out, size);
753       out += n;
754       size -= n;
755       start_page_value = 0;
756     }
757     return initial_size - size;
758   }
759 
next_many_invertedhb_bit_set_t760   unsigned int next_many_inverted (hb_codepoint_t  codepoint,
761 				   hb_codepoint_t *out,
762 				   unsigned int    size) const
763   {
764     unsigned int initial_size = size;
765     // By default, start at the first bit of the first page of values.
766     unsigned int start_page = 0;
767     unsigned int start_page_value = 0;
768     if (unlikely (codepoint != INVALID))
769     {
770       const auto* page_map_array = page_map.arrayZ;
771       unsigned int major = get_major (codepoint);
772       unsigned int i = last_page_lookup;
773       if (unlikely (i >= page_map.length || page_map_array[i].major != major))
774       {
775         page_map.bfind(major, &i, HB_NOT_FOUND_STORE_CLOSEST);
776         if (unlikely (i >= page_map.length))
777         {
778           // codepoint is greater than our max element.
779           while (++codepoint != INVALID && size)
780           {
781             *out++ = codepoint;
782             size--;
783           }
784           return initial_size - size;
785         }
786       }
787       start_page = i;
788       start_page_value = page_remainder (codepoint + 1);
789       if (unlikely (start_page_value == 0))
790       {
791         // The export-after value was last in the page. Start on next page.
792         start_page++;
793         start_page_value = 0;
794       }
795     }
796 
797     hb_codepoint_t next_value = codepoint + 1;
798     for (unsigned int i=start_page; i<page_map.length && size; i++)
799     {
800       uint32_t base = major_start (page_map[i].major);
801       unsigned int n = pages[page_map[i].index].write_inverted (base, start_page_value, out, size, &next_value);
802       out += n;
803       size -= n;
804       start_page_value = 0;
805     }
806     while (next_value < HB_SET_VALUE_INVALID && size) {
807       *out++ = next_value++;
808       size--;
809     }
810     return initial_size - size;
811   }
812 
has_populationhb_bit_set_t813   bool has_population () const { return population != UINT_MAX; }
get_populationhb_bit_set_t814   unsigned int get_population () const
815   {
816     if (has_population ())
817       return population;
818 
819     unsigned int pop = 0;
820     unsigned int count = pages.length;
821     for (unsigned int i = 0; i < count; i++)
822       pop += pages[i].get_population ();
823 
824     population = pop;
825     return pop;
826   }
get_minhb_bit_set_t827   hb_codepoint_t get_min () const
828   {
829     unsigned count = pages.length;
830     for (unsigned i = 0; i < count; i++)
831     {
832       const auto& map = page_map[i];
833       const auto& page = pages[map.index];
834 
835       if (!page.is_empty ())
836 	return map.major * page_t::PAGE_BITS + page.get_min ();
837     }
838     return INVALID;
839   }
get_maxhb_bit_set_t840   hb_codepoint_t get_max () const
841   {
842     unsigned count = pages.length;
843     for (signed i = count - 1; i >= 0; i--)
844     {
845       const auto& map = page_map[(unsigned) i];
846       const auto& page = pages[map.index];
847 
848       if (!page.is_empty ())
849 	return map.major * page_t::PAGE_BITS + page.get_max ();
850     }
851     return INVALID;
852   }
853 
854   static constexpr hb_codepoint_t INVALID = page_t::INVALID;
855 
856   /*
857    * Iterator implementation.
858    */
859   struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
860   {
861     static constexpr bool is_sorted_iterator = true;
iter_thb_bit_set_t::iter_t862     iter_t (const hb_bit_set_t &s_ = Null (hb_bit_set_t),
863 	    bool init = true) : s (&s_), v (INVALID), l(0)
864     {
865       if (init)
866       {
867 	l = s->get_population () + 1;
868 	__next__ ();
869       }
870     }
871 
872     typedef hb_codepoint_t __item_t__;
__item__hb_bit_set_t::iter_t873     hb_codepoint_t __item__ () const { return v; }
__more__hb_bit_set_t::iter_t874     bool __more__ () const { return v != INVALID; }
__next__hb_bit_set_t::iter_t875     void __next__ () { s->next (&v); if (l) l--; }
__prev__hb_bit_set_t::iter_t876     void __prev__ () { s->previous (&v); }
__len__hb_bit_set_t::iter_t877     unsigned __len__ () const { return l; }
endhb_bit_set_t::iter_t878     iter_t end () const { return iter_t (*s, false); }
operator !=hb_bit_set_t::iter_t879     bool operator != (const iter_t& o) const
880     { return s != o.s || v != o.v; }
881 
882     protected:
883     const hb_bit_set_t *s;
884     hb_codepoint_t v;
885     unsigned l;
886   };
iterhb_bit_set_t887   iter_t iter () const { return iter_t (*this); }
operator iter_thb_bit_set_t888   operator iter_t () const { return iter (); }
889 
890   protected:
891 
page_forhb_bit_set_t892   page_t *page_for (hb_codepoint_t g, bool insert = false)
893   {
894     unsigned major = get_major (g);
895 
896     /* The extra page_map length is necessary; can't just rely on vector here,
897      * since the next check would be tricked because a null page also has
898      * major==0, which we can't distinguish from an actualy major==0 page... */
899     unsigned i = last_page_lookup;
900     if (likely (i < page_map.length))
901     {
902       auto &cached_page = page_map.arrayZ[i];
903       if (cached_page.major == major)
904 	return &pages.arrayZ[cached_page.index];
905     }
906 
907     page_map_t map = {major, pages.length};
908     if (!page_map.bfind (map, &i, HB_NOT_FOUND_STORE_CLOSEST))
909     {
910       if (!insert)
911         return nullptr;
912 
913       if (unlikely (!resize (pages.length + 1)))
914 	return nullptr;
915 
916       pages.arrayZ[map.index].init0 ();
917       memmove (page_map.arrayZ + i + 1,
918 	       page_map.arrayZ + i,
919 	       (page_map.length - 1 - i) * page_map.item_size);
920       page_map[i] = map;
921     }
922 
923     last_page_lookup = i;
924     return &pages.arrayZ[page_map.arrayZ[i].index];
925   }
page_forhb_bit_set_t926   const page_t *page_for (hb_codepoint_t g) const
927   {
928     unsigned major = get_major (g);
929 
930     /* The extra page_map length is necessary; can't just rely on vector here,
931      * since the next check would be tricked because a null page also has
932      * major==0, which we can't distinguish from an actualy major==0 page... */
933     unsigned i = last_page_lookup;
934     if (likely (i < page_map.length))
935     {
936       auto &cached_page = page_map.arrayZ[i];
937       if (cached_page.major == major)
938 	return &pages.arrayZ[cached_page.index];
939     }
940 
941     page_map_t key = {major};
942     if (!page_map.bfind (key, &i))
943       return nullptr;
944 
945     last_page_lookup = i;
946     return &pages.arrayZ[page_map[i].index];
947   }
page_athb_bit_set_t948   page_t &page_at (unsigned int i)
949   {
950     assert (i < page_map.length);
951     return pages.arrayZ[page_map.arrayZ[i].index];
952   }
page_athb_bit_set_t953   const page_t &page_at (unsigned int i) const
954   {
955     assert (i < page_map.length);
956     return pages.arrayZ[page_map.arrayZ[i].index];
957   }
get_majorhb_bit_set_t958   unsigned int get_major (hb_codepoint_t g) const { return g >> page_t::PAGE_BITS_LOG_2; }
page_remainderhb_bit_set_t959   unsigned int page_remainder (hb_codepoint_t g) const { return g & page_t::PAGE_BITMASK; }
major_starthb_bit_set_t960   hb_codepoint_t major_start (unsigned int major) const { return major << page_t::PAGE_BITS_LOG_2; }
961 };
962 
963 
964 #endif /* HB_BIT_SET_HH */
965