grafthistory: support curl
[elinks/elinks-j605.git] / src / util / bitfield.h
blob0c8d7cd12caf636278e14273d02bc116fc7f4fa1
1 #ifndef EL__UTIL_BITFIELD_H
2 #define EL__UTIL_BITFIELD_H
4 #include <string.h>
6 #include "util/memory.h"
8 /* Bitfield operations: */
10 struct bitfield {
11 unsigned int bitsize; /* Number of bits in the bitfield. */
12 unsigned char bits[1]; /* Strawberry bitfields forever. */
15 #define foreach_bitfield_set(bit, bitfield) \
16 for ((bit) = 0; (bit) < (bitfield)->bitsize; (bit)++) \
17 if (test_bitfield_bit(bitfield, bit))
19 #define foreachback_bitfield_set(bit, bitfield) \
20 for ((bit) = (bitfield)->bitsize; (bit) > 0;) \
21 if (test_bitfield_bit(bitfield, --bit))
23 #define foreach_bitfield_cleared(bit, bitfield) \
24 for ((bit) = 0; (bit) < (bitfield)->bitsize; (bit)++) \
25 if (!test_bitfield_bit(bitfield, bit))
27 /* By shifting when getting the bit offset it is ensured that only one bit is
28 * set in the resulting value. Idea from libbt by Kevin Smathers. */
29 #define get_bitfield_bit_offset(bit) ((size_t) (0x80 >> ((bit) % 8)))
30 #define get_bitfield_byte_offset(bit) ((size_t) ((bit) / 8))
31 /* +7 to round up to nearest byte. */
32 #define get_bitfield_byte_size(bits) ((size_t) (((bits) + 7) / 8))
34 /* Allocate a bitfield containing @bits number of bits. */
35 static inline struct bitfield *
36 init_bitfield(size_t bits)
38 size_t size = get_bitfield_byte_size(bits);
39 struct bitfield *bitfield;
41 bitfield = mem_calloc(1, offsetof(struct bitfield, bits) + size);
42 if (bitfield) bitfield->bitsize = bits;
44 return bitfield;
47 /* Update @bitfield with the @size bytes from the @bits string in @bits. */
48 static inline void
49 copy_bitfield(struct bitfield *bitfield,
50 const unsigned char *bits, unsigned int bytesize)
52 /* Only for exact size? */
53 if (bytesize <= get_bitfield_byte_size(bitfield->bitsize))
54 memcpy(bitfield->bits, bits, bytesize);
57 /* Test whether @bit is set in the bitfield. */
58 static inline int
59 test_bitfield_bit(struct bitfield *bitfield, unsigned int bit)
61 size_t byte_offset, bit_offset;
63 if (bit >= bitfield->bitsize)
64 return 0;
66 byte_offset = get_bitfield_byte_offset(bit);
67 bit_offset = get_bitfield_bit_offset(bit);
69 return !!(bitfield->bits[byte_offset] & bit_offset);
72 /* Set @bit in the bitfield. */
73 static inline void
74 set_bitfield_bit(struct bitfield *bitfield, unsigned int bit)
76 size_t byte_offset, bit_offset;
78 if (bit >= bitfield->bitsize)
79 return;
81 byte_offset = get_bitfield_byte_offset(bit);
82 bit_offset = get_bitfield_bit_offset(bit);
84 bitfield->bits[byte_offset] |= bit_offset;
87 /* Unset @bit in the bitfield. */
88 static inline void
89 clear_bitfield_bit(struct bitfield *bitfield, unsigned int bit)
91 size_t byte_offset, bit_offset;
93 if (bit >= bitfield->bitsize)
94 return;
96 byte_offset = get_bitfield_byte_offset(bit);
97 bit_offset = get_bitfield_bit_offset(bit);
99 bitfield->bits[byte_offset] &= ~bit_offset;
102 static inline unsigned int
103 get_bitfield_set_count(struct bitfield *bitfield)
105 unsigned int bit, count = 0;
107 foreach_bitfield_set (bit, bitfield)
108 count++;
110 return count;
113 static inline unsigned int
114 get_bitfield_cleared_count(struct bitfield *bitfield)
116 unsigned int bit, count = 0;
118 foreach_bitfield_cleared (bit, bitfield)
119 count++;
121 return count;
124 static inline unsigned int
125 bitfield_is_set(struct bitfield *bitfield)
127 unsigned int bit;
129 foreach_bitfield_cleared (bit, bitfield)
130 return 0;
132 return 1;
135 static inline unsigned int
136 bitfield_is_cleared(struct bitfield *bitfield)
138 unsigned int bit;
140 foreach_bitfield_set (bit, bitfield)
141 return 0;
143 return 1;
146 #endif