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