4 * Copyright (c) 2013 David Herrmann <dh.herrmann@googlemail.com>
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files
8 * (the "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * A dynamic flagset implementation
38 #include "shl_array.h"
41 static inline int shl_flagset_new(struct shl_array **out)
43 return shl_array_new(out, sizeof(unsigned long), 1);
46 static inline void shl_flagset_free(struct shl_array *arr)
48 return shl_array_free(arr);
51 static inline int shl_flagset_alloc(struct shl_array *arr, unsigned int *out)
53 static const unsigned long one = 1;
61 for (i = 0; i < arr->length; ++i) {
62 data = SHL_ARRAY_AT(arr, unsigned long, i);
63 for (j = 0; j < SHL_ULONG_BITS; ++j) {
64 if (!(*data & (1UL << j))) {
66 *out = i * SHL_ULONG_BITS + j;
72 ret = shl_array_push(arr, &one);
76 *out = (arr->length - 1) * SHL_ULONG_BITS;
80 static inline int shl_flagset_reserve(struct shl_array *arr, unsigned int num)
83 unsigned int idx, off;
89 idx = num / SHL_ULONG_BITS;
90 off = num % SHL_ULONG_BITS;
92 if (idx >= arr->length) {
93 ret = shl_array_zresize(arr, idx + 1);
98 data = SHL_ARRAY_AT(arr, unsigned long, idx);
99 if (*data & (1UL << off))
106 static inline int shl_flagset_set(struct shl_array *arr, unsigned int num)
110 ret = shl_flagset_reserve(arr, num);
117 static inline void shl_flagset_unset(struct shl_array *arr, unsigned int num)
119 unsigned int idx, off;
125 idx = num / SHL_ULONG_BITS;
126 off = num % SHL_ULONG_BITS;
128 if (idx >= arr->length)
131 data = SHL_ARRAY_AT(arr, unsigned long, idx);
132 *data &= ~(1UL << off);
135 #endif /* SHL_FLAGSET_H */