2 * Copyright © 2012,2017 Google, Inc.
3 * Copyright © 2021 Behdad Esfahbod
5 * This is part of HarfBuzz, a text shaping library.
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.
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
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.
25 * Google Author(s): Behdad Esfahbod
28 #ifndef HB_BIT_SET_INVERTIBLE_HH
29 #define HB_BIT_SET_INVERTIBLE_HH
32 #include "hb-bit-set.hh"
35 struct hb_bit_set_invertible_t
38 bool inverted = false;
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;
45 friend void swap (hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b)
47 if (likely (!a.s.successful || !b.s.successful))
49 hb_swap (a.inverted, b.inverted);
53 void init () { s.init (); inverted = false; }
54 void fini () { s.fini (); }
55 void err () { s.err (); }
56 bool in_error () const { return s.in_error (); }
57 explicit operator bool () const { return !is_empty (); }
67 if (likely (s.successful))
72 if (likely (s.successful))
76 bool is_empty () const
78 hb_codepoint_t v = INVALID;
82 hb_codepoint_t get_min () const
84 hb_codepoint_t v = INVALID;
88 hb_codepoint_t get_max () const
90 hb_codepoint_t v = INVALID;
94 unsigned int get_population () const
95 { return inverted ? INVALID - s.get_population () : s.get_population (); }
98 void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
99 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); }
102 template <typename T>
103 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>
106 void add_array (const hb_array_t<const T>& arr) { add_array (&arr, arr.len ()); }
108 /* Might return false if array looks unsorted.
109 * Used for faster rejection of corrupt data. */
110 template <typename T>
111 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>
114 bool add_sorted_array (const hb_sorted_array_t<const T>& arr) { return add_sorted_array (&arr, arr.len ()); }
116 void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); }
117 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); }
120 bool get (hb_codepoint_t g) const { return s.get (g) ^ inverted; }
123 static constexpr bool SENTINEL = false;
124 typedef bool value_t;
125 value_t operator [] (hb_codepoint_t k) const { return get (k); }
126 bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
128 bool operator () (hb_codepoint_t k) const { return has (k); }
130 /* Sink interface. */
131 hb_bit_set_invertible_t& operator << (hb_codepoint_t v)
132 { add (v); return *this; }
133 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; }
136 bool intersects (hb_codepoint_t first, hb_codepoint_t last) const
138 hb_codepoint_t c = first - 1;
139 return next (&c) && c <= last;
142 void set (const hb_bit_set_invertible_t &other)
145 if (likely (s.successful))
146 inverted = other.inverted;
149 bool is_equal (const hb_bit_set_invertible_t &other) const
151 if (likely (inverted == other.inverted))
152 return s.is_equal (other.s);
155 /* TODO Add iter_ranges() and use here. */
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; }));
163 bool is_subset (const hb_bit_set_invertible_t &larger_set) const
165 if (unlikely (inverted != larger_set.inverted))
166 return hb_all (hb_iter (s) | hb_map (larger_set.s));
168 return unlikely (inverted) ? larger_set.s.is_subset (s) : s.is_subset (larger_set.s);
172 template <typename Op>
173 void process (const Op& op, const hb_bit_set_invertible_t &other)
174 { s.process (op, other.s); }
176 void union_ (const hb_bit_set_invertible_t &other)
178 if (likely (inverted == other.inverted))
180 if (unlikely (inverted))
181 process (hb_bitwise_and, other);
183 process (hb_bitwise_or, other); /* Main branch. */
187 if (unlikely (inverted))
188 process (hb_bitwise_gt, other);
190 process (hb_bitwise_lt, other);
192 if (likely (s.successful))
193 inverted = inverted || other.inverted;
195 void intersect (const hb_bit_set_invertible_t &other)
197 if (likely (inverted == other.inverted))
199 if (unlikely (inverted))
200 process (hb_bitwise_or, other);
202 process (hb_bitwise_and, other); /* Main branch. */
206 if (unlikely (inverted))
207 process (hb_bitwise_lt, other);
209 process (hb_bitwise_gt, other);
211 if (likely (s.successful))
212 inverted = inverted && other.inverted;
214 void subtract (const hb_bit_set_invertible_t &other)
216 if (likely (inverted == other.inverted))
218 if (unlikely (inverted))
219 process (hb_bitwise_lt, other);
221 process (hb_bitwise_gt, other); /* Main branch. */
225 if (unlikely (inverted))
226 process (hb_bitwise_or, other);
228 process (hb_bitwise_and, other);
230 if (likely (s.successful))
231 inverted = inverted && !other.inverted;
233 void symmetric_difference (const hb_bit_set_invertible_t &other)
235 process (hb_bitwise_xor, other);
236 if (likely (s.successful))
237 inverted = inverted ^ other.inverted;
240 bool next (hb_codepoint_t *codepoint) const
242 if (likely (!inverted))
243 return s.next (codepoint);
245 auto old = *codepoint;
246 if (unlikely (old + 1 == INVALID))
248 *codepoint = INVALID;
256 *codepoint = old + 1;
261 s.next_range (&old, &v);
264 return *codepoint != INVALID;
266 bool previous (hb_codepoint_t *codepoint) const
268 if (likely (!inverted))
269 return s.previous (codepoint);
271 auto old = *codepoint;
272 if (unlikely (old - 1 == INVALID))
274 *codepoint = INVALID;
281 if (old - 1 > v || v == INVALID)
283 *codepoint = old - 1;
288 s.previous_range (&v, &old);
291 return *codepoint != INVALID;
293 bool next_range (hb_codepoint_t *first, hb_codepoint_t *last) const
295 if (likely (!inverted))
296 return s.next_range (first, last);
300 *last = *first = INVALID;
309 bool previous_range (hb_codepoint_t *first, hb_codepoint_t *last) const
311 if (likely (!inverted))
312 return s.previous_range (first, last);
314 if (!previous (first))
316 *last = *first = INVALID;
326 static constexpr hb_codepoint_t INVALID = hb_bit_set_t::INVALID;
329 * Iterator implementation.
331 struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
333 static constexpr bool is_sorted_iterator = true;
334 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)
339 l = s->get_population () + 1;
344 typedef hb_codepoint_t __item_t__;
345 hb_codepoint_t __item__ () const { return v; }
346 bool __more__ () const { return v != INVALID; }
347 void __next__ () { s->next (&v); if (l) l--; }
348 void __prev__ () { s->previous (&v); }
349 unsigned __len__ () const { return l; }
350 iter_t end () const { return iter_t (*s, false); }
351 bool operator != (const iter_t& o) const
352 { return s != o.s || v != o.v; }
355 const hb_bit_set_invertible_t *s;
359 iter_t iter () const { return iter_t (*this); }
360 operator iter_t () const { return iter (); }
364 #endif /* HB_BIT_SET_INVERTIBLE_HH */