html_special(): move va_end() call outside the switch and make variables
[elinks.git] / src / util / bitfield.h
blob3257c8654f80a6a9420ea50ea81c16598c22915c
2 #ifndef EL__UTIL_BITFIELD_H
3 #define EL__UTIL_BITFIELD_H
5 #include <string.h>
7 #include "util/memory.h"
9 /* Bitfield operations: */
11 struct bitfield {
12 unsigned int bitsize; /* Number of bits in the bitfield. */
13 unsigned char bits[1]; /* Strawberry bitfields forever. */
16 #define foreach_bitfield_set(bit, bitfield) \
17 for ((bit) = 0; (bit) < (bitfield)->bitsize; (bit)++) \
18 if (test_bitfield_bit(bitfield, bit))
20 #define foreachback_bitfield_set(bit, bitfield) \
21 for ((bit) = (bitfield)->bitsize; (bit) > 0;) \
22 if (test_bitfield_bit(bitfield, --bit))
24 #define foreach_bitfield_cleared(bit, bitfield) \
25 for ((bit) = 0; (bit) < (bitfield)->bitsize; (bit)++) \
26 if (!test_bitfield_bit(bitfield, bit))
28 /* By shifting when getting the bit offset it is ensured that only one bit is
29 * set in the resulting value. Idea from libbt by Kevin Smathers. */
30 #define get_bitfield_bit_offset(bit) ((size_t) (0x80 >> ((bit) % 8)))
31 #define get_bitfield_byte_offset(bit) ((size_t) ((bit) / 8))
32 /* +7 to round up to nearest byte. */
33 #define get_bitfield_byte_size(bits) ((size_t) (((bits) + 7) / 8))
35 /* Allocate a bitfield containing @bits number of bits. */
36 static inline struct bitfield *
37 init_bitfield(size_t bits)
39 size_t size = get_bitfield_byte_size(bits);
40 struct bitfield *bitfield;
42 bitfield = mem_calloc(1, offsetof(struct bitfield, bits) + size);
43 if (bitfield) bitfield->bitsize = bits;
45 return bitfield;
48 /* Update @bitfield with the @size bytes from the @bits string in @bits. */
49 static inline void
50 copy_bitfield(struct bitfield *bitfield,
51 const unsigned char *bits, unsigned int bytesize)
53 /* Only for exact size? */
54 if (bytesize <= get_bitfield_byte_size(bitfield->bitsize))
55 memcpy(bitfield->bits, bits, bytesize);
58 /* Test whether @bit is set in the bitfield. */
59 static inline int
60 test_bitfield_bit(struct bitfield *bitfield, unsigned int bit)
62 size_t byte_offset, bit_offset;
64 if (bit >= bitfield->bitsize)
65 return 0;
67 byte_offset = get_bitfield_byte_offset(bit);
68 bit_offset = get_bitfield_bit_offset(bit);
70 return !!(bitfield->bits[byte_offset] & bit_offset);
73 /* Set @bit in the bitfield. */
74 static inline void
75 set_bitfield_bit(struct bitfield *bitfield, unsigned int bit)
77 size_t byte_offset, bit_offset;
79 if (bit >= bitfield->bitsize)
80 return;
82 byte_offset = get_bitfield_byte_offset(bit);
83 bit_offset = get_bitfield_bit_offset(bit);
85 bitfield->bits[byte_offset] |= bit_offset;
88 /* Unset @bit in the bitfield. */
89 static inline void
90 clear_bitfield_bit(struct bitfield *bitfield, unsigned int bit)
92 size_t byte_offset, bit_offset;
94 if (bit >= bitfield->bitsize)
95 return;
97 byte_offset = get_bitfield_byte_offset(bit);
98 bit_offset = get_bitfield_bit_offset(bit);
100 bitfield->bits[byte_offset] &= ~bit_offset;
103 static inline unsigned int
104 get_bitfield_set_count(struct bitfield *bitfield)
106 unsigned int bit, count = 0;
108 foreach_bitfield_set (bit, bitfield)
109 count++;
111 return count;
114 static inline unsigned int
115 get_bitfield_cleared_count(struct bitfield *bitfield)
117 unsigned int bit, count = 0;
119 foreach_bitfield_cleared (bit, bitfield)
120 count++;
122 return count;
125 static inline unsigned int
126 bitfield_is_set(struct bitfield *bitfield)
128 unsigned int bit;
130 foreach_bitfield_cleared (bit, bitfield)
131 return 0;
133 return 1;
136 static inline unsigned int
137 bitfield_is_cleared(struct bitfield *bitfield)
139 unsigned int bit;
141 foreach_bitfield_set (bit, bitfield)
142 return 0;
144 return 1;
147 #endif