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., 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 32MASK_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 57MASK_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 66MASK_INLINE size_t snd_mask_sizeof(void) 67{ 68 return sizeof(snd_mask_t); 69} 70 71MASK_INLINE void snd_mask_none(snd_mask_t *mask) 72{ 73 memset(mask, 0, sizeof(*mask)); 74} 75 76MASK_INLINE void snd_mask_any(snd_mask_t *mask) 77{ 78 memset(mask, 0xff, MASK_SIZE * sizeof(u_int32_t)); 79} 80 81MASK_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 90MASK_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 99MASK_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 107MASK_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 118MASK_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 129MASK_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 135MASK_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 141MASK_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 149MASK_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 157MASK_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 166MASK_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 173MASK_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 180MASK_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 185MASK_INLINE void snd_mask_copy(snd_mask_t *mask, const snd_mask_t *v) 186{ 187 *mask = *v; 188} 189 190MASK_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 196MASK_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 212MASK_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 224MASK_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 234MASK_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 244MASK_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 256MASK_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 268MASK_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 280MASK_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 286MASK_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 292MASK_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