/src/harfbuzz/src/hb-bit-vector.hh
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * This is part of HarfBuzz, a text shaping library. |
3 | | * |
4 | | * Permission is hereby granted, without written agreement and without |
5 | | * license or royalty fees, to use, copy, modify, and distribute this |
6 | | * software and its documentation for any purpose, provided that the |
7 | | * above copyright notice and the following two paragraphs appear in |
8 | | * all copies of this software. |
9 | | * |
10 | | * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR |
11 | | * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES |
12 | | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN |
13 | | * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH |
14 | | * DAMAGE. |
15 | | * |
16 | | * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, |
17 | | * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND |
18 | | * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
19 | | * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO |
20 | | * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
21 | | * |
22 | | * Author(s): Behdad Esfahbod |
23 | | */ |
24 | | |
25 | | #ifndef HB_BIT_VECTOR_HH |
26 | | #define HB_BIT_VECTOR_HH |
27 | | |
28 | | #include "hb.hh" |
29 | | |
30 | | #include "hb-atomic.hh" |
31 | | |
32 | | struct hb_min_max_t |
33 | | { |
34 | 0 | void add (hb_codepoint_t v) { min_v = hb_min (min_v, v); max_v = hb_max (max_v, v); } |
35 | | void add_range (hb_codepoint_t a, hb_codepoint_t b) |
36 | 0 | { |
37 | 0 | min_v = hb_min (min_v, a); |
38 | 0 | max_v = hb_max (max_v, b); |
39 | 0 | } |
40 | | |
41 | | template <typename set_t> |
42 | | void union_ (const set_t &set) |
43 | | { |
44 | | hb_codepoint_t set_min = set.get_min (); |
45 | | if (unlikely (set_min == HB_CODEPOINT_INVALID)) |
46 | | return; |
47 | | hb_codepoint_t set_max = set.get_max (); |
48 | | min_v = hb_min (min_v, set_min); |
49 | | max_v = hb_max (max_v, set_max); |
50 | | } |
51 | | |
52 | 0 | hb_codepoint_t get_min () const { return min_v; } |
53 | 0 | hb_codepoint_t get_max () const { return max_v; } |
54 | | |
55 | | private: |
56 | | hb_codepoint_t min_v = HB_CODEPOINT_INVALID; |
57 | | hb_codepoint_t max_v = 0; |
58 | | }; |
59 | | |
60 | | template <bool atomic = false> |
61 | | struct hb_bit_vector_t |
62 | | { |
63 | | using int_t = uint64_t; |
64 | | using elt_t = typename std::conditional<atomic, hb_atomic_t<int_t>, int_t>::type; |
65 | | |
66 | | hb_bit_vector_t () = delete; |
67 | | hb_bit_vector_t (const hb_bit_vector_t &other) = delete; |
68 | | hb_bit_vector_t &operator= (const hb_bit_vector_t &other) = delete; |
69 | | |
70 | | // Move |
71 | | hb_bit_vector_t (hb_bit_vector_t &&other) |
72 | | : min_v (other.min_v), max_v (other.max_v), count (other.count), elts (other.elts) |
73 | | { |
74 | | other.min_v = other.max_v = other.count = 0; |
75 | | other.elts = nullptr; |
76 | | } |
77 | | hb_bit_vector_t &operator= (hb_bit_vector_t &&other) |
78 | | { |
79 | | hb_swap (min_v, other.min_v); |
80 | | hb_swap (max_v, other.max_v); |
81 | | hb_swap (count, other.count); |
82 | | hb_swap (elts, other.elts); |
83 | | return *this; |
84 | | } |
85 | | |
86 | | hb_bit_vector_t (unsigned min_v, unsigned max_v) |
87 | | : min_v (min_v), max_v (max_v) |
88 | | { |
89 | | if (unlikely (min_v >= max_v)) |
90 | | { |
91 | | min_v = max_v = count = 0; |
92 | | return; |
93 | | } |
94 | | |
95 | | unsigned num = (max_v - min_v + sizeof (int_t) * 8) / (sizeof (int_t) * 8); |
96 | | elts = (elt_t *) hb_calloc (num, sizeof (int_t)); |
97 | | if (unlikely (!elts)) |
98 | | { |
99 | | min_v = max_v = count = 0; |
100 | | return; |
101 | | } |
102 | | |
103 | | count = max_v - min_v + 1; |
104 | | } |
105 | | ~hb_bit_vector_t () |
106 | | { |
107 | | hb_free (elts); |
108 | | } |
109 | | |
110 | | void add (hb_codepoint_t g) { elt (g) |= mask (g); } |
111 | | void del (hb_codepoint_t g) { elt (g) &= ~mask (g); } |
112 | | void set (hb_codepoint_t g, bool value) { if (value) add (g); else del (g); } |
113 | | bool get (hb_codepoint_t g) const { return elt (g) & mask (g); } |
114 | | bool has (hb_codepoint_t g) const { return get (g); } |
115 | | bool may_have (hb_codepoint_t g) const { return get (g); } |
116 | | |
117 | | bool operator [] (hb_codepoint_t g) const { return get (g); } |
118 | | bool operator () (hb_codepoint_t g) const { return get (g); } |
119 | | |
120 | | void add_range (hb_codepoint_t a, hb_codepoint_t b) |
121 | | { |
122 | | if (unlikely (!count || a > b || a < min_v || b > max_v)) |
123 | | return; |
124 | | |
125 | | elt_t *la = &elt (a); |
126 | | elt_t *lb = &elt (b); |
127 | | if (la == lb) |
128 | | *la |= (mask (b) << 1) - mask(a); |
129 | | else |
130 | | { |
131 | | *la |= ~(mask (a) - 1llu); |
132 | | la++; |
133 | | |
134 | | hb_memset (la, 0xff, (char *) lb - (char *) la); |
135 | | |
136 | | *lb |= ((mask (b) << 1) - 1llu); |
137 | | } |
138 | | } |
139 | | void del_range (hb_codepoint_t a, hb_codepoint_t b) |
140 | | { |
141 | | if (unlikely (!count || a > b || a < min_v || b > max_v)) |
142 | | return; |
143 | | |
144 | | elt_t *la = &elt (a); |
145 | | elt_t *lb = &elt (b); |
146 | | if (la == lb) |
147 | | *la &= ~((mask (b) << 1llu) - mask(a)); |
148 | | else |
149 | | { |
150 | | *la &= mask (a) - 1; |
151 | | la++; |
152 | | |
153 | | hb_memset (la, 0, (char *) lb - (char *) la); |
154 | | |
155 | | *lb &= ~((mask (b) << 1) - 1llu); |
156 | | } |
157 | | } |
158 | | void set_range (hb_codepoint_t a, hb_codepoint_t b, bool v) |
159 | | { if (v) add_range (a, b); else del_range (a, b); } |
160 | | |
161 | | template <typename set_t> |
162 | | void union_ (const set_t &set) |
163 | | { |
164 | | for (hb_codepoint_t g : set) |
165 | | add (g); |
166 | | } |
167 | | |
168 | | static const unsigned int ELT_BITS = sizeof (elt_t) * 8; |
169 | | static constexpr unsigned ELT_MASK = ELT_BITS - 1; |
170 | | |
171 | | static constexpr elt_t zero = 0; |
172 | | |
173 | | elt_t &elt (hb_codepoint_t g) |
174 | | { |
175 | | g -= min_v; |
176 | | if (unlikely (g >= count)) |
177 | | return Crap(elt_t); |
178 | | return elts[g / ELT_BITS]; |
179 | | } |
180 | | const elt_t& elt (hb_codepoint_t g) const |
181 | | { |
182 | | g -= min_v; |
183 | | if (unlikely (g >= count)) |
184 | | return Null(elt_t); |
185 | | return elts[g / ELT_BITS]; |
186 | | } |
187 | | |
188 | | static constexpr int_t mask (hb_codepoint_t g) { return elt_t (1) << (g & ELT_MASK); } |
189 | | |
190 | | hb_codepoint_t min_v = 0, max_v = 0, count = 0; |
191 | | elt_t *elts = nullptr; |
192 | | }; |
193 | | |
194 | | |
195 | | #endif /* HB_BIT_VECTOR_HH */ |