1 /*
2 * Mask inlines
3 * Copyright (c) 2000 by Abramo Bagnara <abramo@alsa-project.org>
4 *
5 *
6 * This library is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation; either version 2.1 of
9 * the License, or (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 *
20 */
21
22 #include <strings.h>
23 #include <sys/types.h>
24
25 #define MASK_INLINE static inline
26
27 #define MASK_MAX SND_MASK_MAX
28 #define MASK_SIZE (MASK_MAX / 32)
29
30 #define MASK_OFS(i) ((i) >> 5)
31 #define MASK_BIT(i) (1U << ((i) & 31))
32
ld2(uint32_t v)33 MASK_INLINE unsigned int ld2(uint32_t v)
34 {
35 unsigned r = 0;
36
37 if (v >= 0x10000) {
38 v >>= 16;
39 r += 16;
40 }
41 if (v >= 0x100) {
42 v >>= 8;
43 r += 8;
44 }
45 if (v >= 0x10) {
46 v >>= 4;
47 r += 4;
48 }
49 if (v >= 4) {
50 v >>= 2;
51 r += 2;
52 }
53 if (v >= 2)
54 r++;
55 return r;
56 }
57
hweight32(uint32_t v)58 MASK_INLINE unsigned int hweight32(uint32_t v)
59 {
60 v = (v & 0x55555555) + ((v >> 1) & 0x55555555);
61 v = (v & 0x33333333) + ((v >> 2) & 0x33333333);
62 v = (v & 0x0F0F0F0F) + ((v >> 4) & 0x0F0F0F0F);
63 v = (v & 0x00FF00FF) + ((v >> 8) & 0x00FF00FF);
64 return (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFF);
65 }
66
snd_mask_sizeof(void)67 MASK_INLINE size_t snd_mask_sizeof(void)
68 {
69 return sizeof(snd_mask_t);
70 }
71
snd_mask_none(snd_mask_t * mask)72 MASK_INLINE void snd_mask_none(snd_mask_t *mask)
73 {
74 memset(mask, 0, sizeof(*mask));
75 }
76
snd_mask_any(snd_mask_t * mask)77 MASK_INLINE void snd_mask_any(snd_mask_t *mask)
78 {
79 memset(mask, 0xff, MASK_SIZE * sizeof(uint32_t));
80 }
81
snd_mask_empty(const snd_mask_t * mask)82 MASK_INLINE int snd_mask_empty(const snd_mask_t *mask)
83 {
84 int i;
85 for (i = 0; i < MASK_SIZE; i++)
86 if (mask->bits[i])
87 return 0;
88 return 1;
89 }
90
snd_mask_full(const snd_mask_t * mask)91 MASK_INLINE int snd_mask_full(const snd_mask_t *mask)
92 {
93 int i;
94 for (i = 0; i < MASK_SIZE; i++)
95 if (mask->bits[i] != 0xffffffff)
96 return 0;
97 return 1;
98 }
99
snd_mask_count(const snd_mask_t * mask)100 MASK_INLINE unsigned int snd_mask_count(const snd_mask_t *mask)
101 {
102 int i, w = 0;
103 for (i = 0; i < MASK_SIZE; i++)
104 w += hweight32(mask->bits[i]);
105 return w;
106 }
107
snd_mask_min(const snd_mask_t * mask)108 MASK_INLINE unsigned int snd_mask_min(const snd_mask_t *mask)
109 {
110 int i;
111 assert(!snd_mask_empty(mask));
112 for (i = 0; i < MASK_SIZE; i++) {
113 if (mask->bits[i])
114 return ffs(mask->bits[i]) - 1 + (i << 5);
115 }
116 return 0;
117 }
118
snd_mask_max(const snd_mask_t * mask)119 MASK_INLINE unsigned int snd_mask_max(const snd_mask_t *mask)
120 {
121 int i;
122 assert(!snd_mask_empty(mask));
123 for (i = MASK_SIZE - 1; i >= 0; i--) {
124 if (mask->bits[i])
125 return ld2(mask->bits[i]) + (i << 5);
126 }
127 return 0;
128 }
129
snd_mask_set(snd_mask_t * mask,unsigned int val)130 MASK_INLINE void snd_mask_set(snd_mask_t *mask, unsigned int val)
131 {
132 assert(val <= SND_MASK_MAX);
133 mask->bits[MASK_OFS(val)] |= MASK_BIT(val);
134 }
135
snd_mask_reset(snd_mask_t * mask,unsigned int val)136 MASK_INLINE void snd_mask_reset(snd_mask_t *mask, unsigned int val)
137 {
138 assert(val <= SND_MASK_MAX);
139 mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val);
140 }
141
snd_mask_set_range(snd_mask_t * mask,unsigned int from,unsigned int to)142 MASK_INLINE void snd_mask_set_range(snd_mask_t *mask, unsigned int from, unsigned int to)
143 {
144 unsigned int i;
145 assert(to <= SND_MASK_MAX && from <= to);
146 for (i = from; i <= to; i++)
147 mask->bits[MASK_OFS(i)] |= MASK_BIT(i);
148 }
149
snd_mask_reset_range(snd_mask_t * mask,unsigned int from,unsigned int to)150 MASK_INLINE void snd_mask_reset_range(snd_mask_t *mask, unsigned int from, unsigned int to)
151 {
152 unsigned int i;
153 assert(to <= SND_MASK_MAX && from <= to);
154 for (i = from; i <= to; i++)
155 mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i);
156 }
157
snd_mask_leave(snd_mask_t * mask,unsigned int val)158 MASK_INLINE void snd_mask_leave(snd_mask_t *mask, unsigned int val)
159 {
160 unsigned int v;
161 assert(val <= SND_MASK_MAX);
162 v = mask->bits[MASK_OFS(val)] & MASK_BIT(val);
163 snd_mask_none(mask);
164 mask->bits[MASK_OFS(val)] = v;
165 }
166
snd_mask_intersect(snd_mask_t * mask,const snd_mask_t * v)167 MASK_INLINE void snd_mask_intersect(snd_mask_t *mask, const snd_mask_t *v)
168 {
169 int i;
170 for (i = 0; i < MASK_SIZE; i++)
171 mask->bits[i] &= v->bits[i];
172 }
173
snd_mask_union(snd_mask_t * mask,const snd_mask_t * v)174 MASK_INLINE void snd_mask_union(snd_mask_t *mask, const snd_mask_t *v)
175 {
176 int i;
177 for (i = 0; i < MASK_SIZE; i++)
178 mask->bits[i] |= v->bits[i];
179 }
180
snd_mask_eq(const snd_mask_t * mask,const snd_mask_t * v)181 MASK_INLINE int snd_mask_eq(const snd_mask_t *mask, const snd_mask_t *v)
182 {
183 return ! memcmp(mask, v, MASK_SIZE * 4);
184 }
185
snd_mask_copy(snd_mask_t * mask,const snd_mask_t * v)186 MASK_INLINE void snd_mask_copy(snd_mask_t *mask, const snd_mask_t *v)
187 {
188 *mask = *v;
189 }
190
snd_mask_test(const snd_mask_t * mask,unsigned int val)191 MASK_INLINE int snd_mask_test(const snd_mask_t *mask, unsigned int val)
192 {
193 assert(val <= SND_MASK_MAX);
194 return mask->bits[MASK_OFS(val)] & MASK_BIT(val);
195 }
196
snd_mask_single(const snd_mask_t * mask)197 MASK_INLINE int snd_mask_single(const snd_mask_t *mask)
198 {
199 int i, c = 0;
200 assert(!snd_mask_empty(mask));
201 for (i = 0; i < MASK_SIZE; i++) {
202 if (! mask->bits[i])
203 continue;
204 if (mask->bits[i] & (mask->bits[i] - 1))
205 return 0;
206 if (c)
207 return 0;
208 c++;
209 }
210 return 1;
211 }
212
snd_mask_refine(snd_mask_t * mask,const snd_mask_t * v)213 MASK_INLINE int snd_mask_refine(snd_mask_t *mask, const snd_mask_t *v)
214 {
215 snd_mask_t old;
216 if (snd_mask_empty(mask))
217 return -ENOENT;
218 snd_mask_copy(&old, mask);
219 snd_mask_intersect(mask, v);
220 if (snd_mask_empty(mask))
221 return -EINVAL;
222 return !snd_mask_eq(mask, &old);
223 }
224
snd_mask_refine_first(snd_mask_t * mask)225 MASK_INLINE int snd_mask_refine_first(snd_mask_t *mask)
226 {
227 if (snd_mask_empty(mask))
228 return -ENOENT;
229 if (snd_mask_single(mask))
230 return 0;
231 snd_mask_leave(mask, snd_mask_min(mask));
232 return 1;
233 }
234
snd_mask_refine_last(snd_mask_t * mask)235 MASK_INLINE int snd_mask_refine_last(snd_mask_t *mask)
236 {
237 if (snd_mask_empty(mask))
238 return -ENOENT;
239 if (snd_mask_single(mask))
240 return 0;
241 snd_mask_leave(mask, snd_mask_max(mask));
242 return 1;
243 }
244
snd_mask_refine_min(snd_mask_t * mask,unsigned int val)245 MASK_INLINE int snd_mask_refine_min(snd_mask_t *mask, unsigned int val)
246 {
247 if (snd_mask_empty(mask))
248 return -ENOENT;
249 if (snd_mask_min(mask) >= val)
250 return 0;
251 snd_mask_reset_range(mask, 0, val - 1);
252 if (snd_mask_empty(mask))
253 return -EINVAL;
254 return 1;
255 }
256
snd_mask_refine_max(snd_mask_t * mask,unsigned int val)257 MASK_INLINE int snd_mask_refine_max(snd_mask_t *mask, unsigned int val)
258 {
259 if (snd_mask_empty(mask))
260 return -ENOENT;
261 if (snd_mask_max(mask) <= val)
262 return 0;
263 snd_mask_reset_range(mask, val + 1, SND_MASK_MAX);
264 if (snd_mask_empty(mask))
265 return -EINVAL;
266 return 1;
267 }
268
snd_mask_refine_set(snd_mask_t * mask,unsigned int val)269 MASK_INLINE int snd_mask_refine_set(snd_mask_t *mask, unsigned int val)
270 {
271 int changed;
272 if (snd_mask_empty(mask))
273 return -ENOENT;
274 changed = !snd_mask_single(mask);
275 snd_mask_leave(mask, val);
276 if (snd_mask_empty(mask))
277 return -EINVAL;
278 return changed;
279 }
280
snd_mask_value(const snd_mask_t * mask)281 MASK_INLINE int snd_mask_value(const snd_mask_t *mask)
282 {
283 assert(!snd_mask_empty(mask));
284 return snd_mask_min(mask);
285 }
286
snd_mask_always_eq(const snd_mask_t * m1,const snd_mask_t * m2)287 MASK_INLINE int snd_mask_always_eq(const snd_mask_t *m1, const snd_mask_t *m2)
288 {
289 return snd_mask_single(m1) && snd_mask_single(m2) &&
290 snd_mask_value(m1) == snd_mask_value(m2);
291 }
292
snd_mask_never_eq(const snd_mask_t * m1,const snd_mask_t * m2)293 MASK_INLINE int snd_mask_never_eq(const snd_mask_t *m1, const snd_mask_t *m2)
294 {
295 int i;
296 for (i = 0; i < MASK_SIZE; i++)
297 if (m1->bits[i] & m2->bits[i])
298 return 0;
299 return 1;
300 }
301