2 * Copyright © 2012 Google, Inc.
4 * This is part of HarfBuzz, a text shaping library.
6 * Permission is hereby granted, without written agreement and without
7 * license or royalty fees, to use, copy, modify, and distribute this
8 * software and its documentation for any purpose, provided that the
9 * above copyright notice and the following two paragraphs appear in
10 * all copies of this software.
12 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
13 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
14 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
15 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
19 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
22 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
24 * Google Author(s): Behdad Esfahbod
27 #ifndef HB_SET_PRIVATE_HH
28 #define HB_SET_PRIVATE_HH
30 #include "hb-private.hh"
32 #include "hb-object-private.hh"
35 struct hb_set_digest_common_bits_t
39 typedef unsigned int mask_t
;
41 inline void init (void) {
46 inline void add (hb_codepoint_t g
) {
47 if (unlikely (value
== (mask_t
) -1)) {
52 mask
^= (g
& mask
) ^ value
;
56 inline void add_range (hb_codepoint_t a
, hb_codepoint_t b
) {
57 /* The negation here stands for ~(x-1). */
58 mask
&= -(1 << _hb_bit_storage (a
^ b
));
62 inline bool may_have (hb_codepoint_t g
) const {
63 return (g
& mask
) == value
;
71 struct hb_set_digest_lowest_bits_t
75 typedef unsigned long mask_t
;
77 inline void init (void) {
81 inline void add (hb_codepoint_t g
) {
85 inline void add_range (hb_codepoint_t a
, hb_codepoint_t b
) {
86 if (b
- a
>= sizeof (mask_t
) * 8 - 1)
89 mask_t ma
= mask_for (a
);
90 mask_t mb
= mask_for (b
);
91 mask
|= mb
+ (mb
- ma
) - (mb
< ma
);
95 inline bool may_have (hb_codepoint_t g
) const {
96 return !!(mask
& mask_for (g
));
101 mask_t
mask_for (hb_codepoint_t g
) const { return ((mask_t
) 1) << (g
& (sizeof (mask_t
) * 8 - 1)); }
105 struct hb_set_digest_t
109 inline void init (void) {
114 inline void add (hb_codepoint_t g
) {
119 inline void add_range (hb_codepoint_t a
, hb_codepoint_t b
) {
120 digest1
.add_range (a
, b
);
121 digest2
.add_range (a
, b
);
124 inline bool may_have (hb_codepoint_t g
) const {
125 return digest1
.may_have (g
) && digest2
.may_have (g
);
129 hb_set_digest_common_bits_t digest1
;
130 hb_set_digest_lowest_bits_t digest2
;
134 /* TODO Make this faster and memmory efficient. */
138 hb_object_header_t header
;
141 inline void init (void) {
145 inline void fini (void) {
147 inline void clear (void) {
148 memset (elts
, 0, sizeof elts
);
150 inline bool empty (void) const {
151 for (unsigned int i
= 0; i
< ARRAY_LENGTH (elts
); i
++)
156 inline void add (hb_codepoint_t g
)
158 if (unlikely (g
== SENTINEL
)) return;
159 if (unlikely (g
> MAX_G
)) return;
162 inline void add_range (hb_codepoint_t a
, hb_codepoint_t b
)
164 for (unsigned int i
= a
; i
< b
+ 1; i
++)
167 inline void del (hb_codepoint_t g
)
169 if (unlikely (g
> MAX_G
)) return;
170 elt (g
) &= ~mask (g
);
172 inline bool has (hb_codepoint_t g
) const
174 if (unlikely (g
> MAX_G
)) return false;
175 return !!(elt (g
) & mask (g
));
177 inline bool intersects (hb_codepoint_t first
,
178 hb_codepoint_t last
) const
180 if (unlikely (first
> MAX_G
)) return false;
181 if (unlikely (last
> MAX_G
)) last
= MAX_G
;
182 unsigned int end
= last
+ 1;
183 for (hb_codepoint_t i
= first
; i
< end
; i
++)
188 inline bool equal (const hb_set_t
*other
) const
190 for (unsigned int i
= 0; i
< ELTS
; i
++)
191 if (elts
[i
] != other
->elts
[i
])
195 inline void set (const hb_set_t
*other
)
197 for (unsigned int i
= 0; i
< ELTS
; i
++)
198 elts
[i
] = other
->elts
[i
];
200 inline void union_ (const hb_set_t
*other
)
202 for (unsigned int i
= 0; i
< ELTS
; i
++)
203 elts
[i
] |= other
->elts
[i
];
205 inline void intersect (const hb_set_t
*other
)
207 for (unsigned int i
= 0; i
< ELTS
; i
++)
208 elts
[i
] &= other
->elts
[i
];
210 inline void subtract (const hb_set_t
*other
)
212 for (unsigned int i
= 0; i
< ELTS
; i
++)
213 elts
[i
] &= ~other
->elts
[i
];
215 inline void symmetric_difference (const hb_set_t
*other
)
217 for (unsigned int i
= 0; i
< ELTS
; i
++)
218 elts
[i
] ^= other
->elts
[i
];
220 inline bool next (hb_codepoint_t
*codepoint
)
222 if (unlikely (*codepoint
== SENTINEL
)) {
223 hb_codepoint_t i
= get_min ();
230 for (hb_codepoint_t i
= *codepoint
+ 1; i
< MAX_G
+ 1; i
++)
237 inline hb_codepoint_t
get_min (void) const
239 for (unsigned int i
= 0; i
< ELTS
; i
++)
241 for (unsigned int j
= 0; i
< BITS
; j
++)
242 if (elts
[i
] & (1 << j
))
246 inline hb_codepoint_t
get_max (void) const
248 for (unsigned int i
= ELTS
; i
; i
--)
250 for (unsigned int j
= BITS
; j
; j
--)
251 if (elts
[i
- 1] & (1 << (j
- 1)))
252 return (i
- 1) * BITS
+ (j
- 1);
256 typedef uint32_t elt_t
;
257 static const unsigned int MAX_G
= 65536 - 1; /* XXX Fix this... */
258 static const unsigned int SHIFT
= 5;
259 static const unsigned int BITS
= (1 << SHIFT
);
260 static const unsigned int MASK
= BITS
- 1;
261 static const unsigned int ELTS
= (MAX_G
+ 1 + (BITS
- 1)) / BITS
;
262 static const hb_codepoint_t SENTINEL
= (hb_codepoint_t
) -1;
264 elt_t
&elt (hb_codepoint_t g
) { return elts
[g
>> SHIFT
]; }
265 elt_t
elt (hb_codepoint_t g
) const { return elts
[g
>> SHIFT
]; }
266 elt_t
mask (hb_codepoint_t g
) const { return elt_t (1) << (g
& MASK
); }
268 elt_t elts
[ELTS
]; /* XXX 8kb */
270 ASSERT_STATIC (sizeof (elt_t
) * 8 == BITS
);
271 ASSERT_STATIC (sizeof (elt_t
) * 8 * ELTS
> MAX_G
);
276 #endif /* HB_SET_PRIVATE_HH */