1 /* 2 * Mask inlines 3 * Copyright (c) 2000 by Abramo Bagnara <abramo (at) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 * 20 */ 21 22 #include <sys/types.h> 23 24 #define MASK_INLINE static inline 25 26 #define MASK_MAX SND_MASK_MAX 27 #define MASK_SIZE (MASK_MAX / 32) 28 29 #define MASK_OFS(i) ((i) >> 5) 30 #define MASK_BIT(i) (1U << ((i) & 31)) 31 32 MASK_INLINE unsigned int ld2(u_int32_t v) 33 { 34 unsigned r = 0; 35 36 if (v >= 0x10000) { 37 v >>= 16; 38 r += 16; 39 } 40 if (v >= 0x100) { 41 v >>= 8; 42 r += 8; 43 } 44 if (v >= 0x10) { 45 v >>= 4; 46 r += 4; 47 } 48 if (v >= 4) { 49 v >>= 2; 50 r += 2; 51 } 52 if (v >= 2) 53 r++; 54 return r; 55 } 56 57 MASK_INLINE unsigned int hweight32(u_int32_t v) 58 { 59 v = (v & 0x55555555) + ((v >> 1) & 0x55555555); 60 v = (v & 0x33333333) + ((v >> 2) & 0x33333333); 61 v = (v & 0x0F0F0F0F) + ((v >> 4) & 0x0F0F0F0F); 62 v = (v & 0x00FF00FF) + ((v >> 8) & 0x00FF00FF); 63 return (v & 0x0000FFFF) + ((v >> 16) & 0x0000FFFF); 64 } 65 66 MASK_INLINE size_t snd_mask_sizeof(void) 67 { 68 return sizeof(snd_mask_t); 69 } 70 71 MASK_INLINE void snd_mask_none(snd_mask_t *mask) 72 { 73 memset(mask, 0, sizeof(*mask)); 74 } 75 76 MASK_INLINE void snd_mask_any(snd_mask_t *mask) 77 { 78 memset(mask, 0xff, MASK_SIZE * sizeof(u_int32_t)); 79 } 80 81 MASK_INLINE int snd_mask_empty(const snd_mask_t *mask) 82 { 83 int i; 84 for (i = 0; i < MASK_SIZE; i++) 85 if (mask->bits[i]) 86 return 0; 87 return 1; 88 } 89 90 MASK_INLINE int snd_mask_full(const snd_mask_t *mask) 91 { 92 int i; 93 for (i = 0; i < MASK_SIZE; i++) 94 if (mask->bits[i] != 0xffffffff) 95 return 0; 96 return 1; 97 } 98 99 MASK_INLINE unsigned int snd_mask_count(const snd_mask_t *mask) 100 { 101 int i, w = 0; 102 for (i = 0; i < MASK_SIZE; i++) 103 w += hweight32(mask->bits[i]); 104 return w; 105 } 106 107 MASK_INLINE unsigned int snd_mask_min(const snd_mask_t *mask) 108 { 109 int i; 110 assert(!snd_mask_empty(mask)); 111 for (i = 0; i < MASK_SIZE; i++) { 112 if (mask->bits[i]) 113 return ffs(mask->bits[i]) - 1 + (i << 5); 114 } 115 return 0; 116 } 117 118 MASK_INLINE unsigned int snd_mask_max(const snd_mask_t *mask) 119 { 120 int i; 121 assert(!snd_mask_empty(mask)); 122 for (i = MASK_SIZE - 1; i >= 0; i--) { 123 if (mask->bits[i]) 124 return ld2(mask->bits[i]) + (i << 5); 125 } 126 return 0; 127 } 128 129 MASK_INLINE void snd_mask_set(snd_mask_t *mask, unsigned int val) 130 { 131 assert(val <= SND_MASK_MAX); 132 mask->bits[MASK_OFS(val)] |= MASK_BIT(val); 133 } 134 135 MASK_INLINE void snd_mask_reset(snd_mask_t *mask, unsigned int val) 136 { 137 assert(val <= SND_MASK_MAX); 138 mask->bits[MASK_OFS(val)] &= ~MASK_BIT(val); 139 } 140 141 MASK_INLINE void snd_mask_set_range(snd_mask_t *mask, unsigned int from, unsigned int to) 142 { 143 unsigned int i; 144 assert(to <= SND_MASK_MAX && from <= to); 145 for (i = from; i <= to; i++) 146 mask->bits[MASK_OFS(i)] |= MASK_BIT(i); 147 } 148 149 MASK_INLINE void snd_mask_reset_range(snd_mask_t *mask, unsigned int from, unsigned int to) 150 { 151 unsigned int i; 152 assert(to <= SND_MASK_MAX && from <= to); 153 for (i = from; i <= to; i++) 154 mask->bits[MASK_OFS(i)] &= ~MASK_BIT(i); 155 } 156 157 MASK_INLINE void snd_mask_leave(snd_mask_t *mask, unsigned int val) 158 { 159 unsigned int v; 160 assert(val <= SND_MASK_MAX); 161 v = mask->bits[MASK_OFS(val)] & MASK_BIT(val); 162 snd_mask_none(mask); 163 mask->bits[MASK_OFS(val)] = v; 164 } 165 166 MASK_INLINE void snd_mask_intersect(snd_mask_t *mask, const snd_mask_t *v) 167 { 168 int i; 169 for (i = 0; i < MASK_SIZE; i++) 170 mask->bits[i] &= v->bits[i]; 171 } 172 173 MASK_INLINE void snd_mask_union(snd_mask_t *mask, const snd_mask_t *v) 174 { 175 int i; 176 for (i = 0; i < MASK_SIZE; i++) 177 mask->bits[i] |= v->bits[i]; 178 } 179 180 MASK_INLINE int snd_mask_eq(const snd_mask_t *mask, const snd_mask_t *v) 181 { 182 return ! memcmp(mask, v, MASK_SIZE * 4); 183 } 184 185 MASK_INLINE void snd_mask_copy(snd_mask_t *mask, const snd_mask_t *v) 186 { 187 *mask = *v; 188 } 189 190 MASK_INLINE int snd_mask_test(const snd_mask_t *mask, unsigned int val) 191 { 192 assert(val <= SND_MASK_MAX); 193 return mask->bits[MASK_OFS(val)] & MASK_BIT(val); 194 } 195 196 MASK_INLINE int snd_mask_single(const snd_mask_t *mask) 197 { 198 int i, c = 0; 199 assert(!snd_mask_empty(mask)); 200 for (i = 0; i < MASK_SIZE; i++) { 201 if (! mask->bits[i]) 202 continue; 203 if (mask->bits[i] & (mask->bits[i] - 1)) 204 return 0; 205 if (c) 206 return 0; 207 c++; 208 } 209 return 1; 210 } 211 212 MASK_INLINE int snd_mask_refine(snd_mask_t *mask, const snd_mask_t *v) 213 { 214 snd_mask_t old; 215 if (snd_mask_empty(mask)) 216 return -ENOENT; 217 snd_mask_copy(&old, mask); 218 snd_mask_intersect(mask, v); 219 if (snd_mask_empty(mask)) 220 return -EINVAL; 221 return !snd_mask_eq(mask, &old); 222 } 223 224 MASK_INLINE int snd_mask_refine_first(snd_mask_t *mask) 225 { 226 if (snd_mask_empty(mask)) 227 return -ENOENT; 228 if (snd_mask_single(mask)) 229 return 0; 230 snd_mask_leave(mask, snd_mask_min(mask)); 231 return 1; 232 } 233 234 MASK_INLINE int snd_mask_refine_last(snd_mask_t *mask) 235 { 236 if (snd_mask_empty(mask)) 237 return -ENOENT; 238 if (snd_mask_single(mask)) 239 return 0; 240 snd_mask_leave(mask, snd_mask_max(mask)); 241 return 1; 242 } 243 244 MASK_INLINE int snd_mask_refine_min(snd_mask_t *mask, unsigned int val) 245 { 246 if (snd_mask_empty(mask)) 247 return -ENOENT; 248 if (snd_mask_min(mask) >= val) 249 return 0; 250 snd_mask_reset_range(mask, 0, val - 1); 251 if (snd_mask_empty(mask)) 252 return -EINVAL; 253 return 1; 254 } 255 256 MASK_INLINE int snd_mask_refine_max(snd_mask_t *mask, unsigned int val) 257 { 258 if (snd_mask_empty(mask)) 259 return -ENOENT; 260 if (snd_mask_max(mask) <= val) 261 return 0; 262 snd_mask_reset_range(mask, val + 1, SND_MASK_MAX); 263 if (snd_mask_empty(mask)) 264 return -EINVAL; 265 return 1; 266 } 267 268 MASK_INLINE int snd_mask_refine_set(snd_mask_t *mask, unsigned int val) 269 { 270 int changed; 271 if (snd_mask_empty(mask)) 272 return -ENOENT; 273 changed = !snd_mask_single(mask); 274 snd_mask_leave(mask, val); 275 if (snd_mask_empty(mask)) 276 return -EINVAL; 277 return changed; 278 } 279 280 MASK_INLINE int snd_mask_value(const snd_mask_t *mask) 281 { 282 assert(!snd_mask_empty(mask)); 283 return snd_mask_min(mask); 284 } 285 286 MASK_INLINE int snd_mask_always_eq(const snd_mask_t *m1, const snd_mask_t *m2) 287 { 288 return snd_mask_single(m1) && snd_mask_single(m2) && 289 snd_mask_value(m1) == snd_mask_value(m2); 290 } 291 292 MASK_INLINE int snd_mask_never_eq(const snd_mask_t *m1, const snd_mask_t *m2) 293 { 294 int i; 295 for (i = 0; i < MASK_SIZE; i++) 296 if (m1->bits[i] & m2->bits[i]) 297 return 0; 298 return 1; 299 } 300