uvtd: vt: implement VT_GETMODE/SETMODE ioctl state-tracking
[platform/upstream/kmscon.git] / src / shl_flagset.h
1 /*
2  * shl - Flagset
3  *
4  * Copyright (c) 2013 David Herrmann <dh.herrmann@googlemail.com>
5  *
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:
13  *
14  * The above copyright notice and this permission notice shall be included
15  * in all copies or substantial portions of the Software.
16  *
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.
24  */
25
26 /*
27  * A dynamic flagset implementation
28  */
29
30 #ifndef SHL_FLAGSET_H
31 #define SHL_FLAGSET_H
32
33 #include <limits.h>
34 #include <stdbool.h>
35 #include <stddef.h>
36 #include <stdint.h>
37 #include <stdlib.h>
38 #include "shl_array.h"
39 #include "shl_misc.h"
40
41 static inline int shl_flagset_new(struct shl_array **out)
42 {
43         return shl_array_new(out, sizeof(unsigned long), 1);
44 }
45
46 static inline void shl_flagset_free(struct shl_array *arr)
47 {
48         return shl_array_free(arr);
49 }
50
51 static inline int shl_flagset_alloc(struct shl_array *arr, unsigned int *out)
52 {
53         static const unsigned long one = 1;
54         unsigned int i, j;
55         unsigned long *data;
56         int ret;
57
58         if (!arr)
59                 return -EINVAL;
60
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))) {
65                                 *data |= 1UL << j;
66                                 *out = i * SHL_ULONG_BITS + j;
67                                 return 0;
68                         }
69                 }
70         }
71
72         ret = shl_array_push(arr, &one);
73         if (ret)
74                 return ret;
75
76         *out = (arr->length - 1) * SHL_ULONG_BITS;
77         return 0;
78 }
79
80 static inline int shl_flagset_reserve(struct shl_array *arr, unsigned int num)
81 {
82         int ret;
83         unsigned int idx, off;
84         unsigned long *data;
85
86         if (!arr)
87                 return -EINVAL;
88
89         idx = num / SHL_ULONG_BITS;
90         off = num % SHL_ULONG_BITS;
91
92         if (idx >= arr->length) {
93                 ret = shl_array_zresize(arr, idx + 1);
94                 if (ret)
95                         return ret;
96         }
97
98         data = SHL_ARRAY_AT(arr, unsigned long, idx);
99         if (*data & (1UL << off))
100                 return -EEXIST;
101
102         *data |= 1UL << off;
103         return 0;
104 }
105
106 static inline int shl_flagset_set(struct shl_array *arr, unsigned int num)
107 {
108         int ret;
109
110         ret = shl_flagset_reserve(arr, num);
111         if (ret == -EEXIST)
112                 return 0;
113
114         return ret;
115 }
116
117 static inline void shl_flagset_unset(struct shl_array *arr, unsigned int num)
118 {
119         unsigned int idx, off;
120         unsigned long *data;
121
122         if (!arr)
123                 return;
124
125         idx = num / SHL_ULONG_BITS;
126         off = num % SHL_ULONG_BITS;
127
128         if (idx >= arr->length)
129                 return;
130
131         data = SHL_ARRAY_AT(arr, unsigned long, idx);
132         *data &= ~(1UL << off);
133 }
134
135 #endif /* SHL_FLAGSET_H */