QtBase  v6.3.1
hb-bit-set-invertible.hh
Go to the documentation of this file.
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 
36 {
38  bool inverted = false;
39 
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 
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 (); }
58 
59  void reset ()
60  {
61  s.reset ();
62  inverted = false;
63  }
64  void clear ()
65  {
66  s.clear ();
67  if (likely (s.successful))
68  inverted = false;
69  }
70  void invert ()
71  {
72  if (likely (s.successful))
73  inverted = !inverted;
74  }
75 
76  bool is_empty () const
77  {
79  next (&v);
80  return v == INVALID;
81  }
83  {
85  next (&v);
86  return v;
87  }
89  {
91  previous (&v);
92  return v;
93  }
94  unsigned int get_population () const
95  { return inverted ? INVALID - s.get_population () : s.get_population (); }
96 
97 
98  void add (hb_codepoint_t g) { unlikely (inverted) ? s.del (g) : s.add (g); }
100  { return unlikely (inverted) ? (s.del_range (a, b), true) : s.add_range (a, b); }
101 
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 ()); }
107 
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 ()); }
115 
116  void del (hb_codepoint_t g) { unlikely (inverted) ? s.add (g) : s.del (g); }
118  { unlikely (inverted) ? (void) s.add_range (a, b) : s.del_range (a, b); }
119 
120  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;
125  value_t operator [] (hb_codepoint_t k) const { return get (k); }
126  bool has (hb_codepoint_t k) const { return (*this)[k] != SENTINEL; }
127  /* Predicate. */
128  bool operator () (hb_codepoint_t k) const { return has (k); }
129 
130  /* Sink interface. */
132  { add (v); return *this; }
134  { add_range (range.first, range.second); return *this; }
135 
137  {
138  hb_codepoint_t c = first - 1;
139  return next (&c) && c <= last;
140  }
141 
143  {
144  s.set (other.s);
145  if (likely (s.successful))
146  inverted = other.inverted;
147  }
148 
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 
163  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>
173  void process (const Op& op, const hb_bit_set_invertible_t &other)
174  { s.process (op, other.s); }
175  public:
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  }
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  }
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  }
234  {
235  process (hb_bitwise_xor, other);
236  if (likely (s.successful))
237  inverted = inverted ^ other.inverted;
238  }
239 
240  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  }
266  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  }
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  }
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  unsigned int next_many (hb_codepoint_t codepoint,
328  unsigned int size) const
329  {
330  return inverted ? s.next_many_inverted (codepoint, out, size)
331  : s.next_many (codepoint, out, size);
332  }
333 
335 
336  /*
337  * Iterator implementation.
338  */
339  struct iter_t : hb_iter_with_fallback_t<iter_t, hb_codepoint_t>
340  {
341  static constexpr bool is_sorted_iterator = true;
343  bool init = true) : s (&s_), v (INVALID), l(0)
344  {
345  if (init)
346  {
347  l = s->get_population () + 1;
348  __next__ ();
349  }
350  }
351 
353  hb_codepoint_t __item__ () const { return v; }
354  bool __more__ () const { return v != INVALID; }
355  void __next__ () { s->next (&v); if (l) l--; }
356  void __prev__ () { s->previous (&v); }
357  unsigned __len__ () const { return l; }
358  iter_t end () const { return iter_t (*s, false); }
359  bool operator != (const iter_t& o) const
360  { return s != o.s || v != o.v; }
361 
362  protected:
365  unsigned l;
366  };
367  iter_t iter () const { return iter_t (*this); }
368  operator iter_t () const { return iter (); }
369 };
370 
371 
372 #endif /* HB_BIT_SET_INVERTIBLE_HH */
auto it hb_map(hb_second)) template< typename Type > inline hb_array_t< Type > operator()(hb_array_t< Type > array
#define _(S, M)
#define likely(expr)
Definition: hb.hh:250
#define unlikely(expr)
Definition: hb.hh:251
set set set set set set set macro pixldst1 op
void
Definition: png.h:1080
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei count
GLsizei range
const void GLsizei GLsizei stride
GLboolean GLboolean g
GLint first
const GLubyte * c
Definition: qopenglext.h:12701
GLenum array
Definition: qopenglext.h:7028
GLdouble s
[6]
Definition: qopenglext.h:235
uint32_t hb_codepoint_t
Definition: hb-common.h:106
QTextStream out(stdout)
[7]
QSharedPointer< T > other(t)
[5]
Definition: hb-null.hh:93
Definition: main.cpp:38
iter_t(const hb_bit_set_invertible_t &s_=Null(hb_bit_set_invertible_t), bool init=true)
const hb_bit_set_invertible_t * s
bool operator!=(const iter_t &o) const
bool is_subset(const hb_bit_set_invertible_t &larger_set) const
hb_bit_set_invertible_t(hb_bit_set_invertible_t &o)=default
void del(hb_codepoint_t g)
bool previous_range(hb_codepoint_t *first, hb_codepoint_t *last) const
hb_codepoint_t get_min() const
hb_bit_set_invertible_t & operator<<(hb_codepoint_t v)
bool next_range(hb_codepoint_t *first, hb_codepoint_t *last) const
bool add_sorted_array(const T *array, unsigned int count, unsigned int stride=sizeof(T))
void set(const hb_bit_set_invertible_t &other)
void intersect(const hb_bit_set_invertible_t &other)
static constexpr hb_codepoint_t INVALID
hb_bit_set_invertible_t(hb_bit_set_invertible_t &&o)=default
bool has(hb_codepoint_t k) const
bool previous(hb_codepoint_t *codepoint) const
unsigned int next_many(hb_codepoint_t codepoint, hb_codepoint_t *out, unsigned int size) const
bool intersects(hb_codepoint_t first, hb_codepoint_t last) const
void add_array(const T *array, unsigned int count, unsigned int stride=sizeof(T))
bool next(hb_codepoint_t *codepoint) const
bool operator()(hb_codepoint_t k) const
hb_codepoint_t get_max() const
bool is_equal(const hb_bit_set_invertible_t &other) const
void subtract(const hb_bit_set_invertible_t &other)
void process(const Op &op, const hb_bit_set_invertible_t &other)
void symmetric_difference(const hb_bit_set_invertible_t &other)
void del_range(hb_codepoint_t a, hb_codepoint_t b)
unsigned int get_population() const
friend void swap(hb_bit_set_invertible_t &a, hb_bit_set_invertible_t &b)
bool add_range(hb_codepoint_t a, hb_codepoint_t b)
bool add_sorted_array(const hb_sorted_array_t< const T > &arr)
bool get(hb_codepoint_t g) const
void add_array(const hb_array_t< const T > &arr)
void union_(const hb_bit_set_invertible_t &other)
hb_bit_set_invertible_t()=default
void add(hb_codepoint_t g)
hb_bit_set_invertible_t & operator=(const hb_bit_set_invertible_t &o)=default
value_t operator[](hb_codepoint_t k) const
static constexpr bool SENTINEL
static constexpr hb_codepoint_t INVALID
Definition: hb-bit-set.hh:837
bool is_subset(const hb_bit_set_t &larger_set) const
Definition: hb-bit-set.hh:377
unsigned len() const
Definition: hb-iter.hh:88