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