OPNGLIB
PNG optimization library
 All Data Structures Files Functions Typedefs Pages
bits.h
1 /*
2  * optk/bits.h
3  * Plain old bitset data type.
4  *
5  * Copyright (C) 2001-2012 Cosmin Truta.
6  *
7  * This software is distributed under the zlib license.
8  * Please see the accompanying LICENSE file.
9  */
10 
11 #ifndef OPTK_BITS_H_
12 #define OPTK_BITS_H_
13 
14 #include <limits.h>
15 #include <stddef.h>
16 
17 
18 #ifdef __cplusplus
19 extern "C" {
20 #endif
21 
22 
23 /*
24  * The bitset type.
25  */
26 typedef unsigned int optk_bits_t;
27 
28 
29 /*
30  * The size operator (not restricted to optk_bits_t).
31  */
32 #define OPTK_BITSIZEOF(object) (sizeof(object) * CHAR_BIT)
33 
34 
35 /*
36  * Bitset limits.
37  */
38 enum
39 {
40  OPTK_BITS_ELT_MIN = 0,
41  OPTK_BITS_ELT_MAX = (int)(OPTK_BITSIZEOF(optk_bits_t) - 1)
42 };
43 
44 
45 /*
46  * Direct bitset access methods.
47  */
48 #ifdef __cplusplus
49 
50 inline int
51 optk_bits_test(optk_bits_t set, int elt)
52 {
53  return (set & (1U << elt)) != 0;
54 }
55 
56 inline void
57 optk_bits_set(optk_bits_t *set, int elt)
58 {
59  *set |= (1U << elt);
60 }
61 
62 inline void
63 optk_bits_reset(optk_bits_t *set, int elt)
64 {
65  *set &= ~(1U << elt);
66 }
67 
68 inline void
69 optk_bits_flip(optk_bits_t *set, int elt)
70 {
71  *set ^= (1U << elt);
72 }
73 
74 inline optk_bits_t
75 optk_bits__range__(int start_elt, int stop_elt)
76 {
77  return ((1U << (stop_elt - start_elt) << 1) - 1) << start_elt;
78 }
79 
80 inline int
81 optk_bits_test_all_in_range(optk_bits_t set, int start_elt, int stop_elt)
82 {
83  return (start_elt <= stop_elt) ?
84  ((~set & optk_bits__range__(start_elt, stop_elt)) == 0) : 1;
85 }
86 
87 inline int
88 optk_bits_test_any_in_range(optk_bits_t set, int start_elt, int stop_elt)
89 {
90  return (start_elt <= stop_elt) ?
91  ((set & optk_bits__range__(start_elt, stop_elt)) != 0) : 0;
92 }
93 
94 inline void
95 optk_bits_set_range(optk_bits_t *set, int start_elt, int stop_elt)
96 {
97  if (start_elt <= stop_elt)
98  *set |= (((1U << (stop_elt - start_elt) << 1) - 1) << start_elt);
99 }
100 
101 inline void
102 optk_bits_reset_range(optk_bits_t *set, int start_elt, int stop_elt)
103 {
104  if (start_elt <= stop_elt)
105  *set &= ~(((1U << (stop_elt - start_elt) << 1) - 1) << start_elt);
106 }
107 
108 inline void
109 optk_bits_flip_range(optk_bits_t *set, int start_elt, int stop_elt)
110 {
111  if (start_elt <= stop_elt)
112  *set ^= (((1U << (stop_elt - start_elt) << 1) - 1) << start_elt);
113 }
114 
115 #else /* !__cplusplus */
116 
117 #define optk_bits_test(set, elt) \
118  (((set) & (1U << (elt))) != 0)
119 
120 #define optk_bits_set(set, elt) \
121  (*(set) |= (1U << (elt)))
122 
123 #define optk_bits_reset(set, elt) \
124  (*(set) &= ~(1U << (elt)))
125 
126 #define optk_bits_flip(set, elt) \
127  (*(set) ^= (1U << (elt)))
128 
129 #define optk_bits__range__(start_elt, stop_elt) \
130  (((1U << ((stop_elt) - (start_elt)) << 1) - 1) << (start_elt))
131 
132 #define optk_bits_test_all_in_range(set, start_elt, stop_elt) \
133  (((start_elt) <= (stop_elt)) \
134  ? (~(set) & optk_bits__range__(start_elt, stop_elt)) == 0 \
135  : 1)
136 
137 #define optk_bits_test_any_in_range(set, start_elt, stop_elt) \
138  (((start_elt) <= (stop_elt)) \
139  ? ((set) & optk_bits__range__(start_elt, stop_elt)) != 0 \
140  : 0)
141 
142 #define optk_bits_set_range(set, start_elt, stop_elt) \
143  (*(set) |= ((start_elt) <= (stop_elt)) \
144  ? optk_bits__range__(start_elt, stop_elt) \
145  : 0U)
146 
147 #define optk_bits_reset_range(set, start_elt, stop_elt) \
148  (*(set) &= ((start_elt) <= (stop_elt)) \
149  ? ~optk_bits__range__(start_elt, stop_elt) \
150  : ~0U)
151 
152 #define optk_bits_flip_range(set, start_elt, stop_elt) \
153  (*(set) ^= ((start_elt) <= (stop_elt)) \
154  ? optk_bits__range__(start_elt, stop_elt) \
155  : 0U)
156 
157 #endif /* __cplusplus */
158 
159 
160 /*
161  * Counts the number of elements in a bitset.
162  *
163  * The function returns the number of bits set to 1.
164  */
165 unsigned int
166 optk_bits_count(optk_bits_t set);
167 
168 /*
169  * Finds the first element in a bitset.
170  *
171  * The function returns the position of the first bit set to 1,
172  * or -1 if all bits are set to 0.
173  */
174 int
175 optk_bits_find_first(optk_bits_t set);
176 
177 /*
178  * Finds the next element in a bitset.
179  *
180  * The function returns the position of the next bit set to 1,
181  * or -1 if all the following bits are set to 0.
182  */
183 int
184 optk_bits_find_next(optk_bits_t set, int elt);
185 
186 /*
187  * Finds the last element in a bitset.
188  *
189  * The function returns the position of the last bit set to 1,
190  * or -1 if all bits are set to 0.
191  */
192 int
193 optk_bits_find_last(optk_bits_t set);
194 
195 /*
196  * Finds the previous element in a bitset.
197  *
198  * The function returns the position of the previous bit set to 1,
199  * or -1 if all the preceding bits are set to 0.
200  */
201 int
202 optk_bits_find_prev(optk_bits_t set, int elt);
203 
204 /*
205  * Converts a rangeset string to a bitset.
206  *
207  * A rangeset string is an arbitrary sequence of elements ("N") and
208  * ranges ("M-N" or "M-"), separated by ',' or ';'. Whitespace is
209  * allowed around lexical elements, and is ignored.
210  *
211  * Here are a few examples, assuming OPTK_BITSIZEOF(optk_bits_t) == 16:
212  * "0,3,5-7" => 0000000011101001
213  * "0-3,5,7-" => 1111111110101111
214  * "8-,4" => 1111111100010000
215  * "" => 0000000000000000
216  * "8-4" => 0000000000000000, errno = ERANGE
217  * "99" => 1000000000000000, errno = ERANGE
218  * "invalid" => 0000000000000000, errno = EINVAL
219  *
220  * If end_idx is not null, the function sets *end_idx to point to
221  * the character that stopped the scan. If the input is invalid and
222  * end_idx is not null, the function sets *end_idx to 0.
223  *
224  * The function returns the value of the converted bitset. If the
225  * input contains non-representable elements or ranges (e.g. elements
226  * larger than OPTK_BITS_ELT_MAX), the function sets errno to ERANGE.
227  * If the input is invalid, the function sets errno to EINVAL and
228  * returns 0 (i.e. the empty set).
229  */
230 optk_bits_t
231 optk_rangeset_string_to_bits(const char *str, size_t *end_idx);
232 
233 /*
234  * Converts a bitset to a rangeset string.
235  *
236  * The function converts the bitset to a rangeset string representation
237  * and attempts to store it in sbuf, if sbuf is large enough. Otherwise,
238  * it leaves sbuf intact.
239  *
240  * The function returns the length of the rangeset string representation.
241  */
242 size_t
243 optk_bits_to_rangeset_string(char *sbuf, size_t sbuf_size, optk_bits_t set);
244 
245 /*
246  * TODO:
247  * optk_rangeset_wstring_to_bits
248  * optk_bits_to_rangeset_wstring
249  */
250 
251 
252 #ifdef __cplusplus
253 } /* extern "C" */
254 #endif
255 
256 
257 #endif /* OPTK_BITS_H_ */