xref: /aosp_15_r20/external/harfbuzz_ng/src/hb-bit-set-invertible.hh (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker /*
2*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2012,2017  Google, Inc.
3*2d1272b8SAndroid Build Coastguard Worker  * Copyright © 2021 Behdad Esfahbod
4*2d1272b8SAndroid Build Coastguard Worker  *
5*2d1272b8SAndroid Build Coastguard Worker  *  This is part of HarfBuzz, a text shaping library.
6*2d1272b8SAndroid Build Coastguard Worker  *
7*2d1272b8SAndroid Build Coastguard Worker  * Permission is hereby granted, without written agreement and without
8*2d1272b8SAndroid Build Coastguard Worker  * license or royalty fees, to use, copy, modify, and distribute this
9*2d1272b8SAndroid Build Coastguard Worker  * software and its documentation for any purpose, provided that the
10*2d1272b8SAndroid Build Coastguard Worker  * above copyright notice and the following two paragraphs appear in
11*2d1272b8SAndroid Build Coastguard Worker  * all copies of this software.
12*2d1272b8SAndroid Build Coastguard Worker  *
13*2d1272b8SAndroid Build Coastguard Worker  * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
14*2d1272b8SAndroid Build Coastguard Worker  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
15*2d1272b8SAndroid Build Coastguard Worker  * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
16*2d1272b8SAndroid Build Coastguard Worker  * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
17*2d1272b8SAndroid Build Coastguard Worker  * DAMAGE.
18*2d1272b8SAndroid Build Coastguard Worker  *
19*2d1272b8SAndroid Build Coastguard Worker  * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
20*2d1272b8SAndroid Build Coastguard Worker  * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
21*2d1272b8SAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
22*2d1272b8SAndroid Build Coastguard Worker  * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
23*2d1272b8SAndroid Build Coastguard Worker  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24*2d1272b8SAndroid Build Coastguard Worker  *
25*2d1272b8SAndroid Build Coastguard Worker  * Google Author(s): Behdad Esfahbod
26*2d1272b8SAndroid Build Coastguard Worker  */
27*2d1272b8SAndroid Build Coastguard Worker 
28*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_BIT_SET_INVERTIBLE_HH
29*2d1272b8SAndroid Build Coastguard Worker #define HB_BIT_SET_INVERTIBLE_HH
30*2d1272b8SAndroid Build Coastguard Worker 
31*2d1272b8SAndroid Build Coastguard Worker #include "hb.hh"
32*2d1272b8SAndroid Build Coastguard Worker #include "hb-bit-set.hh"
33*2d1272b8SAndroid Build Coastguard Worker 
34*2d1272b8SAndroid Build Coastguard Worker 
35*2d1272b8SAndroid Build Coastguard Worker struct hb_bit_set_invertible_t
36*2d1272b8SAndroid Build Coastguard Worker {
37*2d1272b8SAndroid Build Coastguard Worker   hb_bit_set_t s;
38*2d1272b8SAndroid Build Coastguard Worker   bool inverted = false;
39*2d1272b8SAndroid Build Coastguard Worker 
40*2d1272b8SAndroid Build Coastguard Worker   hb_bit_set_invertible_t () = default;
41*2d1272b8SAndroid Build Coastguard Worker   hb_bit_set_invertible_t (const hb_bit_set_invertible_t& o) = default;
hb_bit_set_invertible_thb_bit_set_invertible_t42*2d1272b8SAndroid Build Coastguard Worker   hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other)  noexcept : hb_bit_set_invertible_t () { hb_swap (*this, other); }
43*2d1272b8SAndroid Build Coastguard Worker   hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default;
operator =hb_bit_set_invertible_t44*2d1272b8SAndroid Build Coastguard Worker   hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& other)  noexcept { hb_swap (*this, other); return *this; }
swap(hb_bit_set_invertible_t & a,hb_bit_set_invertible_t & b)45*2d1272b8SAndroid Build Coastguard Worker   friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b) noexcept
46*2d1272b8SAndroid Build Coastguard Worker   {
47*2d1272b8SAndroid Build Coastguard Worker     if (likely (!a.s.successful || !b.s.successful))
48*2d1272b8SAndroid Build Coastguard Worker       return;
49*2d1272b8SAndroid Build Coastguard Worker     hb_swap (a.inverted, b.inverted);
50*2d1272b8SAndroid Build Coastguard Worker     hb_swap (a.s, b.s);
51*2d1272b8SAndroid Build Coastguard Worker   }
52*2d1272b8SAndroid Build Coastguard Worker 
inithb_bit_set_invertible_t53*2d1272b8SAndroid Build Coastguard Worker   void init () { s.init (); inverted = false; }
finihb_bit_set_invertible_t54*2d1272b8SAndroid Build Coastguard Worker   void fini () { s.fini (); }
errhb_bit_set_invertible_t55*2d1272b8SAndroid Build Coastguard Worker   void err () { s.err (); }
in_errorhb_bit_set_invertible_t56*2d1272b8SAndroid Build Coastguard Worker   bool in_error () const { return s.in_error (); }
operator boolhb_bit_set_invertible_t57*2d1272b8SAndroid Build Coastguard Worker   explicit operator bool () const { return !is_empty (); }
58*2d1272b8SAndroid Build Coastguard Worker 
allochb_bit_set_invertible_t59*2d1272b8SAndroid Build Coastguard Worker   void alloc (unsigned sz) { s.alloc (sz); }
resethb_bit_set_invertible_t60*2d1272b8SAndroid Build Coastguard Worker   void reset ()
61*2d1272b8SAndroid Build Coastguard Worker   {
62*2d1272b8SAndroid Build Coastguard Worker     s.reset ();
63*2d1272b8SAndroid Build Coastguard Worker     inverted = false;
64*2d1272b8SAndroid Build Coastguard Worker   }
clearhb_bit_set_invertible_t65*2d1272b8SAndroid Build Coastguard Worker   void clear ()
66*2d1272b8SAndroid Build Coastguard Worker   {
67*2d1272b8SAndroid Build Coastguard Worker     s.clear ();
68*2d1272b8SAndroid Build Coastguard Worker     if (likely (s.successful))
69*2d1272b8SAndroid Build Coastguard Worker       inverted = false;
70*2d1272b8SAndroid Build Coastguard Worker   }
inverthb_bit_set_invertible_t71*2d1272b8SAndroid Build Coastguard Worker   void invert ()
72*2d1272b8SAndroid Build Coastguard Worker   {
73*2d1272b8SAndroid Build Coastguard Worker     if (likely (s.successful))
74*2d1272b8SAndroid Build Coastguard Worker       inverted = !inverted;
75*2d1272b8SAndroid Build Coastguard Worker   }
76*2d1272b8SAndroid Build Coastguard Worker 
is_invertedhb_bit_set_invertible_t77*2d1272b8SAndroid Build Coastguard Worker   bool is_inverted () const
78*2d1272b8SAndroid Build Coastguard Worker   {
79*2d1272b8SAndroid Build Coastguard Worker     return inverted;
80*2d1272b8SAndroid Build Coastguard Worker   }
81*2d1272b8SAndroid Build Coastguard Worker 
is_emptyhb_bit_set_invertible_t82*2d1272b8SAndroid Build Coastguard Worker   bool is_empty () const
83*2d1272b8SAndroid Build Coastguard Worker   {
84*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t v = INVALID;
85*2d1272b8SAndroid Build Coastguard Worker     next (&v);
86*2d1272b8SAndroid Build Coastguard Worker     return v == INVALID;
87*2d1272b8SAndroid Build Coastguard Worker   }
hashhb_bit_set_invertible_t88*2d1272b8SAndroid Build Coastguard Worker   uint32_t hash () const { return s.hash () ^ (uint32_t) inverted; }
89*2d1272b8SAndroid Build Coastguard Worker 
get_minhb_bit_set_invertible_t90*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t get_min () const
91*2d1272b8SAndroid Build Coastguard Worker   {
92*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t v = INVALID;
93*2d1272b8SAndroid Build Coastguard Worker     next (&v);
94*2d1272b8SAndroid Build Coastguard Worker     return v;
95*2d1272b8SAndroid Build Coastguard Worker   }
get_maxhb_bit_set_invertible_t96*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t get_max () const
97*2d1272b8SAndroid Build Coastguard Worker   {
98*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t v = INVALID;
99*2d1272b8SAndroid Build Coastguard Worker     previous (&v);
100*2d1272b8SAndroid Build Coastguard Worker     return v;
101*2d1272b8SAndroid Build Coastguard Worker   }
get_populationhb_bit_set_invertible_t102*2d1272b8SAndroid Build Coastguard Worker   unsigned int get_population () const
103*2d1272b8SAndroid Build Coastguard Worker   { return inverted ? INVALID - s.get_population () : s.get_population (); }
104*2d1272b8SAndroid Build Coastguard Worker 
105*2d1272b8SAndroid Build Coastguard Worker 
addhb_bit_set_invertible_t106*2d1272b8SAndroid Build Coastguard Worker   void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
add_rangehb_bit_set_invertible_t107*2d1272b8SAndroid Build Coastguard Worker   bool add_range (hb_codepoint_t a, hb_codepoint_t b)
108*2d1272b8SAndroid Build Coastguard Worker   { return unlikely (inverted) ? ((void) s.del_range (a, b), true) : s.add_range (a, b); }
109*2d1272b8SAndroid Build Coastguard Worker 
110*2d1272b8SAndroid Build Coastguard Worker   template <typename T>
add_arrayhb_bit_set_invertible_t111*2d1272b8SAndroid Build Coastguard Worker   void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
112*2d1272b8SAndroid Build Coastguard Worker   { inverted ? s.del_array (array, count, stride) : s.add_array (array, count, stride); }
113*2d1272b8SAndroid Build Coastguard Worker   template <typename T>
add_arrayhb_bit_set_invertible_t114*2d1272b8SAndroid Build Coastguard Worker   void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
115*2d1272b8SAndroid Build Coastguard Worker 
116*2d1272b8SAndroid Build Coastguard Worker   /* Might return false if array looks unsorted.
117*2d1272b8SAndroid Build Coastguard Worker    * Used for faster rejection of corrupt data. */
118*2d1272b8SAndroid Build Coastguard Worker   template <typename T>
add_sorted_arrayhb_bit_set_invertible_t119*2d1272b8SAndroid Build Coastguard Worker   bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T))
120*2d1272b8SAndroid Build Coastguard Worker   { return inverted ? s.del_sorted_array (array, count, stride) : s.add_sorted_array (array, count, stride); }
121*2d1272b8SAndroid Build Coastguard Worker   template <typename T>
add_sorted_arrayhb_bit_set_invertible_t122*2d1272b8SAndroid Build Coastguard Worker   bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
123*2d1272b8SAndroid Build Coastguard Worker 
delhb_bit_set_invertible_t124*2d1272b8SAndroid Build Coastguard Worker   void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); }
del_rangehb_bit_set_invertible_t125*2d1272b8SAndroid Build Coastguard Worker   void del_range (hb_codepoint_t a, hb_codepoint_t b)
126*2d1272b8SAndroid Build Coastguard Worker   { unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); }
127*2d1272b8SAndroid Build Coastguard Worker 
gethb_bit_set_invertible_t128*2d1272b8SAndroid Build Coastguard Worker   bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
129*2d1272b8SAndroid Build Coastguard Worker 
130*2d1272b8SAndroid Build Coastguard Worker   /* Has interface. */
operator []hb_bit_set_invertible_t131*2d1272b8SAndroid Build Coastguard Worker   bool operator [] (hb_codepoint_t k) const { return get (k); }
hashb_bit_set_invertible_t132*2d1272b8SAndroid Build Coastguard Worker   bool has (hb_codepoint_t k) const { return (*this)[k]; }
133*2d1272b8SAndroid Build Coastguard Worker   /* Predicate. */
operator ()hb_bit_set_invertible_t134*2d1272b8SAndroid Build Coastguard Worker   bool operator () (hb_codepoint_t k) const { return has (k); }
135*2d1272b8SAndroid Build Coastguard Worker 
136*2d1272b8SAndroid Build Coastguard Worker   /* Sink interface. */
operator <<hb_bit_set_invertible_t137*2d1272b8SAndroid Build Coastguard Worker   hb_bit_set_invertible_t& operator << (hb_codepoint_t v)
138*2d1272b8SAndroid Build Coastguard Worker   { add (v); return *this; }
operator <<hb_bit_set_invertible_t139*2d1272b8SAndroid Build Coastguard Worker   hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range)
140*2d1272b8SAndroid Build Coastguard Worker   { add_range (range.first, range.second); return *this; }
141*2d1272b8SAndroid Build Coastguard Worker 
intersectshb_bit_set_invertible_t142*2d1272b8SAndroid Build Coastguard Worker   bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
143*2d1272b8SAndroid Build Coastguard Worker   {
144*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t c = first - 1;
145*2d1272b8SAndroid Build Coastguard Worker     return next (&c) && c <= last;
146*2d1272b8SAndroid Build Coastguard Worker   }
147*2d1272b8SAndroid Build Coastguard Worker 
sethb_bit_set_invertible_t148*2d1272b8SAndroid Build Coastguard Worker   void set (const hb_bit_set_invertible_t &other)
149*2d1272b8SAndroid Build Coastguard Worker   {
150*2d1272b8SAndroid Build Coastguard Worker     s.set (other.s);
151*2d1272b8SAndroid Build Coastguard Worker     if (likely (s.successful))
152*2d1272b8SAndroid Build Coastguard Worker       inverted = other.inverted;
153*2d1272b8SAndroid Build Coastguard Worker   }
154*2d1272b8SAndroid Build Coastguard Worker 
is_equalhb_bit_set_invertible_t155*2d1272b8SAndroid Build Coastguard Worker   bool is_equal (const hb_bit_set_invertible_t &other) const
156*2d1272b8SAndroid Build Coastguard Worker   {
157*2d1272b8SAndroid Build Coastguard Worker     if (likely (inverted == other.inverted))
158*2d1272b8SAndroid Build Coastguard Worker       return s.is_equal (other.s);
159*2d1272b8SAndroid Build Coastguard Worker     else
160*2d1272b8SAndroid Build Coastguard Worker     {
161*2d1272b8SAndroid Build Coastguard Worker       /* TODO Add iter_ranges() and use here. */
162*2d1272b8SAndroid Build Coastguard Worker       auto it1 = iter ();
163*2d1272b8SAndroid Build Coastguard Worker       auto it2 = other.iter ();
164*2d1272b8SAndroid Build Coastguard Worker       return hb_all (+ hb_zip (it1, it2)
165*2d1272b8SAndroid Build Coastguard Worker 		     | hb_map ([](hb_codepoint_pair_t _) { return _.first == _.second; }));
166*2d1272b8SAndroid Build Coastguard Worker     }
167*2d1272b8SAndroid Build Coastguard Worker   }
168*2d1272b8SAndroid Build Coastguard Worker 
is_subsethb_bit_set_invertible_t169*2d1272b8SAndroid Build Coastguard Worker   bool is_subset (const hb_bit_set_invertible_t &larger_set) const
170*2d1272b8SAndroid Build Coastguard Worker   {
171*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (inverted != larger_set.inverted))
172*2d1272b8SAndroid Build Coastguard Worker       return hb_all (hb_iter (s) | hb_map (larger_set.s));
173*2d1272b8SAndroid Build Coastguard Worker     else
174*2d1272b8SAndroid Build Coastguard Worker       return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s);
175*2d1272b8SAndroid Build Coastguard Worker   }
176*2d1272b8SAndroid Build Coastguard Worker 
177*2d1272b8SAndroid Build Coastguard Worker   protected:
178*2d1272b8SAndroid Build Coastguard Worker   template <typename Op>
processhb_bit_set_invertible_t179*2d1272b8SAndroid Build Coastguard Worker   void process (const Op& op, const hb_bit_set_invertible_t &other)
180*2d1272b8SAndroid Build Coastguard Worker   { s.process (op, other.s); }
181*2d1272b8SAndroid Build Coastguard Worker   public:
union_hb_bit_set_invertible_t182*2d1272b8SAndroid Build Coastguard Worker   void union_ (const hb_bit_set_invertible_t &other)
183*2d1272b8SAndroid Build Coastguard Worker   {
184*2d1272b8SAndroid Build Coastguard Worker     if (likely (inverted == other.inverted))
185*2d1272b8SAndroid Build Coastguard Worker     {
186*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (inverted))
187*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_and, other);
188*2d1272b8SAndroid Build Coastguard Worker       else
189*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_or, other); /* Main branch. */
190*2d1272b8SAndroid Build Coastguard Worker     }
191*2d1272b8SAndroid Build Coastguard Worker     else
192*2d1272b8SAndroid Build Coastguard Worker     {
193*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (inverted))
194*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_gt, other);
195*2d1272b8SAndroid Build Coastguard Worker       else
196*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_lt, other);
197*2d1272b8SAndroid Build Coastguard Worker     }
198*2d1272b8SAndroid Build Coastguard Worker     if (likely (s.successful))
199*2d1272b8SAndroid Build Coastguard Worker       inverted = inverted || other.inverted;
200*2d1272b8SAndroid Build Coastguard Worker   }
intersecthb_bit_set_invertible_t201*2d1272b8SAndroid Build Coastguard Worker   void intersect (const hb_bit_set_invertible_t &other)
202*2d1272b8SAndroid Build Coastguard Worker   {
203*2d1272b8SAndroid Build Coastguard Worker     if (likely (inverted == other.inverted))
204*2d1272b8SAndroid Build Coastguard Worker     {
205*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (inverted))
206*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_or, other);
207*2d1272b8SAndroid Build Coastguard Worker       else
208*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_and, other); /* Main branch. */
209*2d1272b8SAndroid Build Coastguard Worker     }
210*2d1272b8SAndroid Build Coastguard Worker     else
211*2d1272b8SAndroid Build Coastguard Worker     {
212*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (inverted))
213*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_lt, other);
214*2d1272b8SAndroid Build Coastguard Worker       else
215*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_gt, other);
216*2d1272b8SAndroid Build Coastguard Worker     }
217*2d1272b8SAndroid Build Coastguard Worker     if (likely (s.successful))
218*2d1272b8SAndroid Build Coastguard Worker       inverted = inverted && other.inverted;
219*2d1272b8SAndroid Build Coastguard Worker   }
subtracthb_bit_set_invertible_t220*2d1272b8SAndroid Build Coastguard Worker   void subtract (const hb_bit_set_invertible_t &other)
221*2d1272b8SAndroid Build Coastguard Worker   {
222*2d1272b8SAndroid Build Coastguard Worker     if (likely (inverted == other.inverted))
223*2d1272b8SAndroid Build Coastguard Worker     {
224*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (inverted))
225*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_lt, other);
226*2d1272b8SAndroid Build Coastguard Worker       else
227*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_gt, other); /* Main branch. */
228*2d1272b8SAndroid Build Coastguard Worker     }
229*2d1272b8SAndroid Build Coastguard Worker     else
230*2d1272b8SAndroid Build Coastguard Worker     {
231*2d1272b8SAndroid Build Coastguard Worker       if (unlikely (inverted))
232*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_or, other);
233*2d1272b8SAndroid Build Coastguard Worker       else
234*2d1272b8SAndroid Build Coastguard Worker 	process (hb_bitwise_and, other);
235*2d1272b8SAndroid Build Coastguard Worker     }
236*2d1272b8SAndroid Build Coastguard Worker     if (likely (s.successful))
237*2d1272b8SAndroid Build Coastguard Worker       inverted = inverted && !other.inverted;
238*2d1272b8SAndroid Build Coastguard Worker   }
symmetric_differencehb_bit_set_invertible_t239*2d1272b8SAndroid Build Coastguard Worker   void symmetric_difference (const hb_bit_set_invertible_t &other)
240*2d1272b8SAndroid Build Coastguard Worker   {
241*2d1272b8SAndroid Build Coastguard Worker     process (hb_bitwise_xor, other);
242*2d1272b8SAndroid Build Coastguard Worker     if (likely (s.successful))
243*2d1272b8SAndroid Build Coastguard Worker       inverted = inverted ^ other.inverted;
244*2d1272b8SAndroid Build Coastguard Worker   }
245*2d1272b8SAndroid Build Coastguard Worker 
nexthb_bit_set_invertible_t246*2d1272b8SAndroid Build Coastguard Worker   bool next (hb_codepoint_t *codepoint) const
247*2d1272b8SAndroid Build Coastguard Worker   {
248*2d1272b8SAndroid Build Coastguard Worker     if (likely (!inverted))
249*2d1272b8SAndroid Build Coastguard Worker       return s.next (codepoint);
250*2d1272b8SAndroid Build Coastguard Worker 
251*2d1272b8SAndroid Build Coastguard Worker     auto old = *codepoint;
252*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (old + 1 == INVALID))
253*2d1272b8SAndroid Build Coastguard Worker     {
254*2d1272b8SAndroid Build Coastguard Worker       *codepoint = INVALID;
255*2d1272b8SAndroid Build Coastguard Worker       return false;
256*2d1272b8SAndroid Build Coastguard Worker     }
257*2d1272b8SAndroid Build Coastguard Worker 
258*2d1272b8SAndroid Build Coastguard Worker     auto v = old;
259*2d1272b8SAndroid Build Coastguard Worker     s.next (&v);
260*2d1272b8SAndroid Build Coastguard Worker     if (old + 1 < v)
261*2d1272b8SAndroid Build Coastguard Worker     {
262*2d1272b8SAndroid Build Coastguard Worker       *codepoint = old + 1;
263*2d1272b8SAndroid Build Coastguard Worker       return true;
264*2d1272b8SAndroid Build Coastguard Worker     }
265*2d1272b8SAndroid Build Coastguard Worker 
266*2d1272b8SAndroid Build Coastguard Worker     v = old;
267*2d1272b8SAndroid Build Coastguard Worker     s.next_range (&old, &v);
268*2d1272b8SAndroid Build Coastguard Worker 
269*2d1272b8SAndroid Build Coastguard Worker     *codepoint = v + 1;
270*2d1272b8SAndroid Build Coastguard Worker     return *codepoint != INVALID;
271*2d1272b8SAndroid Build Coastguard Worker   }
previoushb_bit_set_invertible_t272*2d1272b8SAndroid Build Coastguard Worker   bool previous (hb_codepoint_t *codepoint) const
273*2d1272b8SAndroid Build Coastguard Worker   {
274*2d1272b8SAndroid Build Coastguard Worker     if (likely (!inverted))
275*2d1272b8SAndroid Build Coastguard Worker       return s.previous (codepoint);
276*2d1272b8SAndroid Build Coastguard Worker 
277*2d1272b8SAndroid Build Coastguard Worker     auto old = *codepoint;
278*2d1272b8SAndroid Build Coastguard Worker     if (unlikely (old - 1 == INVALID))
279*2d1272b8SAndroid Build Coastguard Worker     {
280*2d1272b8SAndroid Build Coastguard Worker       *codepoint = INVALID;
281*2d1272b8SAndroid Build Coastguard Worker       return false;
282*2d1272b8SAndroid Build Coastguard Worker     }
283*2d1272b8SAndroid Build Coastguard Worker 
284*2d1272b8SAndroid Build Coastguard Worker     auto v = old;
285*2d1272b8SAndroid Build Coastguard Worker     s.previous (&v);
286*2d1272b8SAndroid Build Coastguard Worker 
287*2d1272b8SAndroid Build Coastguard Worker     if (old - 1 > v || v == INVALID)
288*2d1272b8SAndroid Build Coastguard Worker     {
289*2d1272b8SAndroid Build Coastguard Worker       *codepoint = old - 1;
290*2d1272b8SAndroid Build Coastguard Worker       return true;
291*2d1272b8SAndroid Build Coastguard Worker     }
292*2d1272b8SAndroid Build Coastguard Worker 
293*2d1272b8SAndroid Build Coastguard Worker     v = old;
294*2d1272b8SAndroid Build Coastguard Worker     s.previous_range (&v, &old);
295*2d1272b8SAndroid Build Coastguard Worker 
296*2d1272b8SAndroid Build Coastguard Worker     *codepoint = v - 1;
297*2d1272b8SAndroid Build Coastguard Worker     return *codepoint != INVALID;
298*2d1272b8SAndroid Build Coastguard Worker   }
next_rangehb_bit_set_invertible_t299*2d1272b8SAndroid Build Coastguard Worker   bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
300*2d1272b8SAndroid Build Coastguard Worker   {
301*2d1272b8SAndroid Build Coastguard Worker     if (likely (!inverted))
302*2d1272b8SAndroid Build Coastguard Worker       return s.next_range (first, last);
303*2d1272b8SAndroid Build Coastguard Worker 
304*2d1272b8SAndroid Build Coastguard Worker     if (!next (last))
305*2d1272b8SAndroid Build Coastguard Worker     {
306*2d1272b8SAndroid Build Coastguard Worker       *last = *first = INVALID;
307*2d1272b8SAndroid Build Coastguard Worker       return false;
308*2d1272b8SAndroid Build Coastguard Worker     }
309*2d1272b8SAndroid Build Coastguard Worker 
310*2d1272b8SAndroid Build Coastguard Worker     *first = *last;
311*2d1272b8SAndroid Build Coastguard Worker     s.next (last);
312*2d1272b8SAndroid Build Coastguard Worker     --*last;
313*2d1272b8SAndroid Build Coastguard Worker     return true;
314*2d1272b8SAndroid Build Coastguard Worker   }
previous_rangehb_bit_set_invertible_t315*2d1272b8SAndroid Build Coastguard Worker   bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
316*2d1272b8SAndroid Build Coastguard Worker   {
317*2d1272b8SAndroid Build Coastguard Worker     if (likely (!inverted))
318*2d1272b8SAndroid Build Coastguard Worker       return s.previous_range (first, last);
319*2d1272b8SAndroid Build Coastguard Worker 
320*2d1272b8SAndroid Build Coastguard Worker     if (!previous (first))
321*2d1272b8SAndroid Build Coastguard Worker     {
322*2d1272b8SAndroid Build Coastguard Worker       *last = *first = INVALID;
323*2d1272b8SAndroid Build Coastguard Worker       return false;
324*2d1272b8SAndroid Build Coastguard Worker     }
325*2d1272b8SAndroid Build Coastguard Worker 
326*2d1272b8SAndroid Build Coastguard Worker     *last = *first;
327*2d1272b8SAndroid Build Coastguard Worker     s.previous (first);
328*2d1272b8SAndroid Build Coastguard Worker     ++*first;
329*2d1272b8SAndroid Build Coastguard Worker     return true;
330*2d1272b8SAndroid Build Coastguard Worker   }
331*2d1272b8SAndroid Build Coastguard Worker 
next_manyhb_bit_set_invertible_t332*2d1272b8SAndroid Build Coastguard Worker   unsigned int next_many (hb_codepoint_t  codepoint,
333*2d1272b8SAndroid Build Coastguard Worker 			  hb_codepoint_t *out,
334*2d1272b8SAndroid Build Coastguard Worker 			  unsigned int    size) const
335*2d1272b8SAndroid Build Coastguard Worker   {
336*2d1272b8SAndroid Build Coastguard Worker     return inverted ? s.next_many_inverted (codepoint, out, size)
337*2d1272b8SAndroid Build Coastguard Worker 		    : s.next_many (codepoint, out, size);
338*2d1272b8SAndroid Build Coastguard Worker   }
339*2d1272b8SAndroid Build Coastguard Worker 
340*2d1272b8SAndroid Build Coastguard Worker   static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID;
341*2d1272b8SAndroid Build Coastguard Worker 
342*2d1272b8SAndroid Build Coastguard Worker   /*
343*2d1272b8SAndroid Build Coastguard Worker    * Iterator implementation.
344*2d1272b8SAndroid Build Coastguard Worker    */
345*2d1272b8SAndroid Build Coastguard Worker   struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
346*2d1272b8SAndroid Build Coastguard Worker   {
347*2d1272b8SAndroid Build Coastguard Worker     static constexpr bool is_sorted_iterator = true;
348*2d1272b8SAndroid Build Coastguard Worker     static constexpr bool has_fast_len = true;
iter_thb_bit_set_invertible_t::iter_t349*2d1272b8SAndroid Build Coastguard Worker     iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t),
350*2d1272b8SAndroid Build Coastguard Worker 	    bool init = true) : s (&s_), v (INVALID), l(0)
351*2d1272b8SAndroid Build Coastguard Worker     {
352*2d1272b8SAndroid Build Coastguard Worker       if (init)
353*2d1272b8SAndroid Build Coastguard Worker       {
354*2d1272b8SAndroid Build Coastguard Worker 	l = s->get_population () + 1;
355*2d1272b8SAndroid Build Coastguard Worker 	__next__ ();
356*2d1272b8SAndroid Build Coastguard Worker       }
357*2d1272b8SAndroid Build Coastguard Worker     }
358*2d1272b8SAndroid Build Coastguard Worker 
359*2d1272b8SAndroid Build Coastguard Worker     typedef hb_codepoint_t __item_t__;
__item__hb_bit_set_invertible_t::iter_t360*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t __item__ () const { return v; }
__more__hb_bit_set_invertible_t::iter_t361*2d1272b8SAndroid Build Coastguard Worker     bool __more__ () const { return v != INVALID; }
__next__hb_bit_set_invertible_t::iter_t362*2d1272b8SAndroid Build Coastguard Worker     void __next__ () { s->next (&v); if (likely (l)) l--; }
__prev__hb_bit_set_invertible_t::iter_t363*2d1272b8SAndroid Build Coastguard Worker     void __prev__ () { s->previous (&v); l++; }
__len__hb_bit_set_invertible_t::iter_t364*2d1272b8SAndroid Build Coastguard Worker     unsigned __len__ () const { return l; }
endhb_bit_set_invertible_t::iter_t365*2d1272b8SAndroid Build Coastguard Worker     iter_t end () const { return iter_t (*s, false); }
operator !=hb_bit_set_invertible_t::iter_t366*2d1272b8SAndroid Build Coastguard Worker     bool operator != (const iter_t& o) const
367*2d1272b8SAndroid Build Coastguard Worker     { return v != o.v || s != o.s; }
368*2d1272b8SAndroid Build Coastguard Worker 
369*2d1272b8SAndroid Build Coastguard Worker     protected:
370*2d1272b8SAndroid Build Coastguard Worker     const hb_bit_set_invertible_t *s;
371*2d1272b8SAndroid Build Coastguard Worker     hb_codepoint_t v;
372*2d1272b8SAndroid Build Coastguard Worker     unsigned l;
373*2d1272b8SAndroid Build Coastguard Worker   };
iterhb_bit_set_invertible_t374*2d1272b8SAndroid Build Coastguard Worker   iter_t iter () const { return iter_t (*this); }
operator iter_thb_bit_set_invertible_t375*2d1272b8SAndroid Build Coastguard Worker   operator iter_t () const { return iter (); }
376*2d1272b8SAndroid Build Coastguard Worker };
377*2d1272b8SAndroid Build Coastguard Worker 
378*2d1272b8SAndroid Build Coastguard Worker 
379*2d1272b8SAndroid Build Coastguard Worker #endif /* HB_BIT_SET_INVERTIBLE_HH */
380