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_INVERTIBLE_HH 29 #define HB_BIT_SET_INVERTIBLE_HH 30 31 #include "hb.hh" 32 #include "hb-bit-set.hh" 33 34 35 struct hb_bit_set_invertible_t 36 { 37 hb_bit_set_t s; 38 bool inverted = false; 39 40 hb_bit_set_invertible_t () = default; 41 hb_bit_set_invertible_t (const hb_bit_set_invertible_t& o) = default; hb_bit_set_invertible_thb_bit_set_invertible_t42 hb_bit_set_invertible_t (hb_bit_set_invertible_t&& other) noexcept : hb_bit_set_invertible_t () { hb_swap (*this, other); } 43 hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default; operator =hb_bit_set_invertible_t44 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 friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b) noexcept 46 { 47 if (likely (!a.s.successful || !b.s.successful)) 48 return; 49 hb_swap (a.inverted, b.inverted); 50 hb_swap (a.s, b.s); 51 } 52 inithb_bit_set_invertible_t53 void init () { s.init (); inverted = false; } finihb_bit_set_invertible_t54 void fini () { s.fini (); } errhb_bit_set_invertible_t55 void err () { s.err (); } in_errorhb_bit_set_invertible_t56 bool in_error () const { return s.in_error (); } operator boolhb_bit_set_invertible_t57 explicit operator bool () const { return !is_empty (); } 58 allochb_bit_set_invertible_t59 void alloc (unsigned sz) { s.alloc (sz); } resethb_bit_set_invertible_t60 void reset () 61 { 62 s.reset (); 63 inverted = false; 64 } clearhb_bit_set_invertible_t65 void clear () 66 { 67 s.clear (); 68 if (likely (s.successful)) 69 inverted = false; 70 } inverthb_bit_set_invertible_t71 void invert () 72 { 73 if (likely (s.successful)) 74 inverted = !inverted; 75 } 76 is_invertedhb_bit_set_invertible_t77 bool is_inverted () const 78 { 79 return inverted; 80 } 81 is_emptyhb_bit_set_invertible_t82 bool is_empty () const 83 { 84 hb_codepoint_t v = INVALID; 85 next (&v); 86 return v == INVALID; 87 } hashhb_bit_set_invertible_t88 uint32_t hash () const { return s.hash () ^ (uint32_t) inverted; } 89 get_minhb_bit_set_invertible_t90 hb_codepoint_t get_min () const 91 { 92 hb_codepoint_t v = INVALID; 93 next (&v); 94 return v; 95 } get_maxhb_bit_set_invertible_t96 hb_codepoint_t get_max () const 97 { 98 hb_codepoint_t v = INVALID; 99 previous (&v); 100 return v; 101 } get_populationhb_bit_set_invertible_t102 unsigned int get_population () const 103 { return inverted ? INVALID - s.get_population () : s.get_population (); } 104 105 addhb_bit_set_invertible_t106 void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); } add_rangehb_bit_set_invertible_t107 bool add_range (hb_codepoint_t a, hb_codepoint_t b) 108 { return unlikely (inverted) ? ((void) s.del_range (a, b), true) : s.add_range (a, b); } 109 110 template <typename T> add_arrayhb_bit_set_invertible_t111 void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) 112 { inverted ? s.del_array (array, count, stride) : s.add_array (array, count, stride); } 113 template <typename T> add_arrayhb_bit_set_invertible_t114 void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); } 115 116 /* Might return false if array looks unsorted. 117 * Used for faster rejection of corrupt data. */ 118 template <typename T> add_sorted_arrayhb_bit_set_invertible_t119 bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) 120 { return inverted ? s.del_sorted_array (array, count, stride) : s.add_sorted_array (array, count, stride); } 121 template <typename T> add_sorted_arrayhb_bit_set_invertible_t122 bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } 123 delhb_bit_set_invertible_t124 void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); } del_rangehb_bit_set_invertible_t125 void del_range (hb_codepoint_t a, hb_codepoint_t b) 126 { unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); } 127 gethb_bit_set_invertible_t128 bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; } 129 130 /* Has interface. */ operator []hb_bit_set_invertible_t131 bool operator [] (hb_codepoint_t k) const { return get (k); } hashb_bit_set_invertible_t132 bool has (hb_codepoint_t k) const { return (*this)[k]; } 133 /* Predicate. */ operator ()hb_bit_set_invertible_t134 bool operator () (hb_codepoint_t k) const { return has (k); } 135 136 /* Sink interface. */ operator <<hb_bit_set_invertible_t137 hb_bit_set_invertible_t& operator << (hb_codepoint_t v) 138 { add (v); return *this; } operator <<hb_bit_set_invertible_t139 hb_bit_set_invertible_t& operator << (const hb_codepoint_pair_t& range) 140 { add_range (range.first, range.second); return *this; } 141 intersectshb_bit_set_invertible_t142 bool intersects (hb_codepoint_t first, hb_codepoint_t last) const 143 { 144 hb_codepoint_t c = first - 1; 145 return next (&c) && c <= last; 146 } 147 sethb_bit_set_invertible_t148 void set (const hb_bit_set_invertible_t &other) 149 { 150 s.set (other.s); 151 if (likely (s.successful)) 152 inverted = other.inverted; 153 } 154 is_equalhb_bit_set_invertible_t155 bool is_equal (const hb_bit_set_invertible_t &other) const 156 { 157 if (likely (inverted == other.inverted)) 158 return s.is_equal (other.s); 159 else 160 { 161 /* TODO Add iter_ranges() and use here. */ 162 auto it1 = iter (); 163 auto it2 = other.iter (); 164 return hb_all (+ hb_zip (it1, it2) 165 | hb_map ([](hb_codepoint_pair_t _) { return _.first == _.second; })); 166 } 167 } 168 is_subsethb_bit_set_invertible_t169 bool is_subset (const hb_bit_set_invertible_t &larger_set) const 170 { 171 if (unlikely (inverted != larger_set.inverted)) 172 return hb_all (hb_iter (s) | hb_map (larger_set.s)); 173 else 174 return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s); 175 } 176 177 protected: 178 template <typename Op> processhb_bit_set_invertible_t179 void process (const Op& op, const hb_bit_set_invertible_t &other) 180 { s.process (op, other.s); } 181 public: union_hb_bit_set_invertible_t182 void union_ (const hb_bit_set_invertible_t &other) 183 { 184 if (likely (inverted == other.inverted)) 185 { 186 if (unlikely (inverted)) 187 process (hb_bitwise_and, other); 188 else 189 process (hb_bitwise_or, other); /* Main branch. */ 190 } 191 else 192 { 193 if (unlikely (inverted)) 194 process (hb_bitwise_gt, other); 195 else 196 process (hb_bitwise_lt, other); 197 } 198 if (likely (s.successful)) 199 inverted = inverted || other.inverted; 200 } intersecthb_bit_set_invertible_t201 void intersect (const hb_bit_set_invertible_t &other) 202 { 203 if (likely (inverted == other.inverted)) 204 { 205 if (unlikely (inverted)) 206 process (hb_bitwise_or, other); 207 else 208 process (hb_bitwise_and, other); /* Main branch. */ 209 } 210 else 211 { 212 if (unlikely (inverted)) 213 process (hb_bitwise_lt, other); 214 else 215 process (hb_bitwise_gt, other); 216 } 217 if (likely (s.successful)) 218 inverted = inverted && other.inverted; 219 } subtracthb_bit_set_invertible_t220 void subtract (const hb_bit_set_invertible_t &other) 221 { 222 if (likely (inverted == other.inverted)) 223 { 224 if (unlikely (inverted)) 225 process (hb_bitwise_lt, other); 226 else 227 process (hb_bitwise_gt, other); /* Main branch. */ 228 } 229 else 230 { 231 if (unlikely (inverted)) 232 process (hb_bitwise_or, other); 233 else 234 process (hb_bitwise_and, other); 235 } 236 if (likely (s.successful)) 237 inverted = inverted && !other.inverted; 238 } symmetric_differencehb_bit_set_invertible_t239 void symmetric_difference (const hb_bit_set_invertible_t &other) 240 { 241 process (hb_bitwise_xor, other); 242 if (likely (s.successful)) 243 inverted = inverted ^ other.inverted; 244 } 245 nexthb_bit_set_invertible_t246 bool next (hb_codepoint_t *codepoint) const 247 { 248 if (likely (!inverted)) 249 return s.next (codepoint); 250 251 auto old = *codepoint; 252 if (unlikely (old + 1 == INVALID)) 253 { 254 *codepoint = INVALID; 255 return false; 256 } 257 258 auto v = old; 259 s.next (&v); 260 if (old + 1 < v) 261 { 262 *codepoint = old + 1; 263 return true; 264 } 265 266 v = old; 267 s.next_range (&old, &v); 268 269 *codepoint = v + 1; 270 return *codepoint != INVALID; 271 } previoushb_bit_set_invertible_t272 bool previous (hb_codepoint_t *codepoint) const 273 { 274 if (likely (!inverted)) 275 return s.previous (codepoint); 276 277 auto old = *codepoint; 278 if (unlikely (old - 1 == INVALID)) 279 { 280 *codepoint = INVALID; 281 return false; 282 } 283 284 auto v = old; 285 s.previous (&v); 286 287 if (old - 1 > v || v == INVALID) 288 { 289 *codepoint = old - 1; 290 return true; 291 } 292 293 v = old; 294 s.previous_range (&v, &old); 295 296 *codepoint = v - 1; 297 return *codepoint != INVALID; 298 } next_rangehb_bit_set_invertible_t299 bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const 300 { 301 if (likely (!inverted)) 302 return s.next_range (first, last); 303 304 if (!next (last)) 305 { 306 *last = *first = INVALID; 307 return false; 308 } 309 310 *first = *last; 311 s.next (last); 312 --*last; 313 return true; 314 } previous_rangehb_bit_set_invertible_t315 bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const 316 { 317 if (likely (!inverted)) 318 return s.previous_range (first, last); 319 320 if (!previous (first)) 321 { 322 *last = *first = INVALID; 323 return false; 324 } 325 326 *last = *first; 327 s.previous (first); 328 ++*first; 329 return true; 330 } 331 next_manyhb_bit_set_invertible_t332 unsigned int next_many (hb_codepoint_t codepoint, 333 hb_codepoint_t *out, 334 unsigned int size) const 335 { 336 return inverted ? s.next_many_inverted (codepoint, out, size) 337 : s.next_many (codepoint, out, size); 338 } 339 340 static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID; 341 342 /* 343 * Iterator implementation. 344 */ 345 struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t> 346 { 347 static constexpr bool is_sorted_iterator = true; 348 static constexpr bool has_fast_len = true; iter_thb_bit_set_invertible_t::iter_t349 iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t), 350 bool init = true) : s (&s_), v (INVALID), l(0) 351 { 352 if (init) 353 { 354 l = s->get_population () + 1; 355 __next__ (); 356 } 357 } 358 359 typedef hb_codepoint_t __item_t__; __item__hb_bit_set_invertible_t::iter_t360 hb_codepoint_t __item__ () const { return v; } __more__hb_bit_set_invertible_t::iter_t361 bool __more__ () const { return v != INVALID; } __next__hb_bit_set_invertible_t::iter_t362 void __next__ () { s->next (&v); if (likely (l)) l--; } __prev__hb_bit_set_invertible_t::iter_t363 void __prev__ () { s->previous (&v); l++; } __len__hb_bit_set_invertible_t::iter_t364 unsigned __len__ () const { return l; } endhb_bit_set_invertible_t::iter_t365 iter_t end () const { return iter_t (*s, false); } operator !=hb_bit_set_invertible_t::iter_t366 bool operator != (const iter_t& o) const 367 { return v != o.v || s != o.s; } 368 369 protected: 370 const hb_bit_set_invertible_t *s; 371 hb_codepoint_t v; 372 unsigned l; 373 }; iterhb_bit_set_invertible_t374 iter_t iter () const { return iter_t (*this); } operator iter_thb_bit_set_invertible_t375 operator iter_t () const { return iter (); } 376 }; 377 378 379 #endif /* HB_BIT_SET_INVERTIBLE_HH */ 380