• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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