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 (hb_bit_set_invertible_t& o) = default; 42 hb_bit_set_invertible_t (hb_bit_set_invertible_t&& o) = default; 43 hb_bit_set_invertible_t& operator= (const hb_bit_set_invertible_t& o) = default; 44 hb_bit_set_invertible_t& operator= (hb_bit_set_invertible_t&& o) = default; 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) 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 resethb_bit_set_invertible_t59 void reset () 60 { 61 s.reset (); 62 inverted = false; 63 } clearhb_bit_set_invertible_t64 void clear () 65 { 66 s.clear (); 67 if (likely (s.successful)) 68 inverted = false; 69 } inverthb_bit_set_invertible_t70 void invert () 71 { 72 if (likely (s.successful)) 73 inverted = !inverted; 74 } 75 is_emptyhb_bit_set_invertible_t76 bool is_empty () const 77 { 78 hb_codepoint_t v = INVALID; 79 next (&v); 80 return v == INVALID; 81 } get_minhb_bit_set_invertible_t82 hb_codepoint_t get_min () const 83 { 84 hb_codepoint_t v = INVALID; 85 next (&v); 86 return v; 87 } get_maxhb_bit_set_invertible_t88 hb_codepoint_t get_max () const 89 { 90 hb_codepoint_t v = INVALID; 91 previous (&v); 92 return v; 93 } get_populationhb_bit_set_invertible_t94 unsigned int get_population () const 95 { return inverted ? INVALID - s.get_population () : s.get_population (); } 96 97 addhb_bit_set_invertible_t98 void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); } add_rangehb_bit_set_invertible_t99 bool add_range (hb_codepoint_t a, hb_codepoint_t b) 100 { return unlikely (inverted) ? (s.del_range (a, b), true) : s.add_range (a, b); } 101 102 template <typename T> add_arrayhb_bit_set_invertible_t103 void add_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) 104 { inverted ? s.del_array (array, count, stride) : s.add_array (array, count, stride); } 105 template <typename T> add_arrayhb_bit_set_invertible_t106 void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); } 107 108 /* Might return false if array looks unsorted. 109 * Used for faster rejection of corrupt data. */ 110 template <typename T> add_sorted_arrayhb_bit_set_invertible_t111 bool add_sorted_array (const T *array, unsigned int count, unsigned int stride=sizeof(T)) 112 { return inverted ? s.del_sorted_array (array, count, stride) : s.add_sorted_array (array, count, stride); } 113 template <typename T> add_sorted_arrayhb_bit_set_invertible_t114 bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); } 115 delhb_bit_set_invertible_t116 void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); } del_rangehb_bit_set_invertible_t117 void del_range (hb_codepoint_t a, hb_codepoint_t b) 118 { unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); } 119 gethb_bit_set_invertible_t120 bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; } 121 122 /* Has interface. */ 123 static constexpr bool SENTINEL = false; 124 typedef bool value_t; operator []hb_bit_set_invertible_t125 value_t operator [] (hb_codepoint_t k) const { return get (k); } hashb_bit_set_invertible_t126 bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; } 127 /* Predicate. */ operator ()hb_bit_set_invertible_t128 bool operator () (hb_codepoint_t k) const { return has (k); } 129 130 /* Sink interface. */ operator <<hb_bit_set_invertible_t131 hb_bit_set_invertible_t& operator << (hb_codepoint_t v) 132 { add (v); return *this; } operator <<hb_bit_set_invertible_t133 hb_bit_set_invertible_t& operator << (const hb_pair_t<hb_codepoint_t, hb_codepoint_t>& range) 134 { add_range (range.first, range.second); return *this; } 135 intersectshb_bit_set_invertible_t136 bool intersects (hb_codepoint_t first, hb_codepoint_t last) const 137 { 138 hb_codepoint_t c = first - 1; 139 return next (&c) && c <= last; 140 } 141 sethb_bit_set_invertible_t142 void set (const hb_bit_set_invertible_t &other) 143 { 144 s.set (other.s); 145 if (likely (s.successful)) 146 inverted = other.inverted; 147 } 148 is_equalhb_bit_set_invertible_t149 bool is_equal (const hb_bit_set_invertible_t &other) const 150 { 151 if (likely (inverted == other.inverted)) 152 return s.is_equal (other.s); 153 else 154 { 155 /* TODO Add iter_ranges() and use here. */ 156 auto it1 = iter (); 157 auto it2 = other.iter (); 158 return hb_all (+ hb_zip (it1, it2) 159 | hb_map ([](hb_pair_t<hb_codepoint_t, hb_codepoint_t> _) { return _.first == _.second; })); 160 } 161 } 162 is_subsethb_bit_set_invertible_t163 bool is_subset (const hb_bit_set_invertible_t &larger_set) const 164 { 165 if (unlikely (inverted != larger_set.inverted)) 166 return hb_all (hb_iter (s) | hb_map (larger_set.s)); 167 else 168 return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s); 169 } 170 171 protected: 172 template <typename Op> processhb_bit_set_invertible_t173 void process (const Op& op, const hb_bit_set_invertible_t &other) 174 { s.process (op, other.s); } 175 public: union_hb_bit_set_invertible_t176 void union_ (const hb_bit_set_invertible_t &other) 177 { 178 if (likely (inverted == other.inverted)) 179 { 180 if (unlikely (inverted)) 181 process (hb_bitwise_and, other); 182 else 183 process (hb_bitwise_or, other); /* Main branch. */ 184 } 185 else 186 { 187 if (unlikely (inverted)) 188 process (hb_bitwise_gt, other); 189 else 190 process (hb_bitwise_lt, other); 191 } 192 if (likely (s.successful)) 193 inverted = inverted || other.inverted; 194 } intersecthb_bit_set_invertible_t195 void intersect (const hb_bit_set_invertible_t &other) 196 { 197 if (likely (inverted == other.inverted)) 198 { 199 if (unlikely (inverted)) 200 process (hb_bitwise_or, other); 201 else 202 process (hb_bitwise_and, other); /* Main branch. */ 203 } 204 else 205 { 206 if (unlikely (inverted)) 207 process (hb_bitwise_lt, other); 208 else 209 process (hb_bitwise_gt, other); 210 } 211 if (likely (s.successful)) 212 inverted = inverted && other.inverted; 213 } subtracthb_bit_set_invertible_t214 void subtract (const hb_bit_set_invertible_t &other) 215 { 216 if (likely (inverted == other.inverted)) 217 { 218 if (unlikely (inverted)) 219 process (hb_bitwise_lt, other); 220 else 221 process (hb_bitwise_gt, other); /* Main branch. */ 222 } 223 else 224 { 225 if (unlikely (inverted)) 226 process (hb_bitwise_or, other); 227 else 228 process (hb_bitwise_and, other); 229 } 230 if (likely (s.successful)) 231 inverted = inverted && !other.inverted; 232 } symmetric_differencehb_bit_set_invertible_t233 void symmetric_difference (const hb_bit_set_invertible_t &other) 234 { 235 process (hb_bitwise_xor, other); 236 if (likely (s.successful)) 237 inverted = inverted ^ other.inverted; 238 } 239 nexthb_bit_set_invertible_t240 bool next (hb_codepoint_t *codepoint) const 241 { 242 if (likely (!inverted)) 243 return s.next (codepoint); 244 245 auto old = *codepoint; 246 if (unlikely (old + 1 == INVALID)) 247 { 248 *codepoint = INVALID; 249 return false; 250 } 251 252 auto v = old; 253 s.next (&v); 254 if (old + 1 < v) 255 { 256 *codepoint = old + 1; 257 return true; 258 } 259 260 v = old; 261 s.next_range (&old, &v); 262 263 *codepoint = v + 1; 264 return *codepoint != INVALID; 265 } previoushb_bit_set_invertible_t266 bool previous (hb_codepoint_t *codepoint) const 267 { 268 if (likely (!inverted)) 269 return s.previous (codepoint); 270 271 auto old = *codepoint; 272 if (unlikely (old - 1 == INVALID)) 273 { 274 *codepoint = INVALID; 275 return false; 276 } 277 278 auto v = old; 279 s.previous (&v); 280 281 if (old - 1 > v || v == INVALID) 282 { 283 *codepoint = old - 1; 284 return true; 285 } 286 287 v = old; 288 s.previous_range (&v, &old); 289 290 *codepoint = v - 1; 291 return *codepoint != INVALID; 292 } next_rangehb_bit_set_invertible_t293 bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const 294 { 295 if (likely (!inverted)) 296 return s.next_range (first, last); 297 298 if (!next (last)) 299 { 300 *last = *first = INVALID; 301 return false; 302 } 303 304 *first = *last; 305 s.next (last); 306 --*last; 307 return true; 308 } previous_rangehb_bit_set_invertible_t309 bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const 310 { 311 if (likely (!inverted)) 312 return s.previous_range (first, last); 313 314 if (!previous (first)) 315 { 316 *last = *first = INVALID; 317 return false; 318 } 319 320 *last = *first; 321 s.previous (first); 322 ++*first; 323 return true; 324 } 325 326 static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID; 327 328 /* 329 * Iterator implementation. 330 */ 331 struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t> 332 { 333 static constexpr bool is_sorted_iterator = true; iter_thb_bit_set_invertible_t::iter_t334 iter_t (const hb_bit_set_invertible_t &s_ = Null (hb_bit_set_invertible_t), 335 bool init = true) : s (&s_), v (INVALID), l(0) 336 { 337 if (init) 338 { 339 l = s->get_population () + 1; 340 __next__ (); 341 } 342 } 343 344 typedef hb_codepoint_t __item_t__; __item__hb_bit_set_invertible_t::iter_t345 hb_codepoint_t __item__ () const { return v; } __more__hb_bit_set_invertible_t::iter_t346 bool __more__ () const { return v != INVALID; } __next__hb_bit_set_invertible_t::iter_t347 void __next__ () { s->next (&v); if (l) l--; } __prev__hb_bit_set_invertible_t::iter_t348 void __prev__ () { s->previous (&v); } __len__hb_bit_set_invertible_t::iter_t349 unsigned __len__ () const { return l; } endhb_bit_set_invertible_t::iter_t350 iter_t end () const { return iter_t (*s, false); } operator !=hb_bit_set_invertible_t::iter_t351 bool operator != (const iter_t& o) const 352 { return s != o.s || v != o.v; } 353 354 protected: 355 const hb_bit_set_invertible_t *s; 356 hb_codepoint_t v; 357 unsigned l; 358 }; iterhb_bit_set_invertible_t359 iter_t iter () const { return iter_t (*this); } operator iter_thb_bit_set_invertible_t360 operator iter_t () const { return iter (); } 361 }; 362 363 364 #endif /* HB_BIT_SET_INVERTIBLE_HH */ 365