xref: /freebsd-13.1/include/bitstring.h (revision fc395092)
159deaec5SRodney W. Grimes /*
259deaec5SRodney W. Grimes  * Copyright (c) 1989, 1993
359deaec5SRodney W. Grimes  *	The Regents of the University of California.  All rights reserved.
459deaec5SRodney W. Grimes  *
559deaec5SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
659deaec5SRodney W. Grimes  * Paul Vixie.
759deaec5SRodney W. Grimes  *
859deaec5SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
959deaec5SRodney W. Grimes  * modification, are permitted provided that the following conditions
1059deaec5SRodney W. Grimes  * are met:
1159deaec5SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
1259deaec5SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
1359deaec5SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
1459deaec5SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
1559deaec5SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
1659deaec5SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
1759deaec5SRodney W. Grimes  *    must display the following acknowledgement:
1859deaec5SRodney W. Grimes  *	This product includes software developed by the University of
1959deaec5SRodney W. Grimes  *	California, Berkeley and its contributors.
2059deaec5SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
2159deaec5SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
2259deaec5SRodney W. Grimes  *    without specific prior written permission.
2359deaec5SRodney W. Grimes  *
2459deaec5SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2559deaec5SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2659deaec5SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2759deaec5SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2859deaec5SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2959deaec5SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3059deaec5SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3159deaec5SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3259deaec5SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3359deaec5SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3459deaec5SRodney W. Grimes  * SUCH DAMAGE.
3559deaec5SRodney W. Grimes  *
36*fc395092SDavid Malone  * $FreeBSD$
3759deaec5SRodney W. Grimes  */
3859deaec5SRodney W. Grimes 
3959deaec5SRodney W. Grimes #ifndef _BITSTRING_H_
4059deaec5SRodney W. Grimes #define	_BITSTRING_H_
4159deaec5SRodney W. Grimes 
4259deaec5SRodney W. Grimes typedef	unsigned char bitstr_t;
4359deaec5SRodney W. Grimes 
4459deaec5SRodney W. Grimes /* internal macros */
4559deaec5SRodney W. Grimes 				/* byte of the bitstring bit is in */
4659deaec5SRodney W. Grimes #define	_bit_byte(bit) \
4759deaec5SRodney W. Grimes 	((bit) >> 3)
4859deaec5SRodney W. Grimes 
4959deaec5SRodney W. Grimes 				/* mask for the bit within its byte */
5059deaec5SRodney W. Grimes #define	_bit_mask(bit) \
5159deaec5SRodney W. Grimes 	(1 << ((bit)&0x7))
5259deaec5SRodney W. Grimes 
5359deaec5SRodney W. Grimes /* external macros */
5459deaec5SRodney W. Grimes 				/* bytes in a bitstring of nbits bits */
5559deaec5SRodney W. Grimes #define	bitstr_size(nbits) \
56*fc395092SDavid Malone 	(((nbits) + 7) >> 3)
5759deaec5SRodney W. Grimes 
5859deaec5SRodney W. Grimes 				/* allocate a bitstring */
5959deaec5SRodney W. Grimes #define	bit_alloc(nbits) \
60*fc395092SDavid Malone 	(bitstr_t *)calloc((size_t)bitstr_size(nbits), sizeof(bitstr_t))
6159deaec5SRodney W. Grimes 
6259deaec5SRodney W. Grimes 				/* allocate a bitstring on the stack */
6359deaec5SRodney W. Grimes #define	bit_decl(name, nbits) \
64*fc395092SDavid Malone 	((name)[bitstr_size(nbits)])
6559deaec5SRodney W. Grimes 
6659deaec5SRodney W. Grimes 				/* is bit N of bitstring name set? */
6759deaec5SRodney W. Grimes #define	bit_test(name, bit) \
6859deaec5SRodney W. Grimes 	((name)[_bit_byte(bit)] & _bit_mask(bit))
6959deaec5SRodney W. Grimes 
7059deaec5SRodney W. Grimes 				/* set bit N of bitstring name */
7159deaec5SRodney W. Grimes #define	bit_set(name, bit) \
72*fc395092SDavid Malone 	((name)[_bit_byte(bit)] |= _bit_mask(bit))
7359deaec5SRodney W. Grimes 
7459deaec5SRodney W. Grimes 				/* clear bit N of bitstring name */
7559deaec5SRodney W. Grimes #define	bit_clear(name, bit) \
76*fc395092SDavid Malone 	((name)[_bit_byte(bit)] &= ~_bit_mask(bit))
7759deaec5SRodney W. Grimes 
7859deaec5SRodney W. Grimes 				/* clear bits start ... stop in bitstring */
79*fc395092SDavid Malone #define	bit_nclear(name, start, stop) do { \
80*fc395092SDavid Malone 	register bitstr_t *_name = (name); \
81*fc395092SDavid Malone 	register int _start = (start), _stop = (stop); \
8259deaec5SRodney W. Grimes 	register int _startbyte = _bit_byte(_start); \
8359deaec5SRodney W. Grimes 	register int _stopbyte = _bit_byte(_stop); \
8459deaec5SRodney W. Grimes 	if (_startbyte == _stopbyte) { \
8559deaec5SRodney W. Grimes 		_name[_startbyte] &= ((0xff >> (8 - (_start&0x7))) | \
8659deaec5SRodney W. Grimes 				      (0xff << ((_stop&0x7) + 1))); \
8759deaec5SRodney W. Grimes 	} else { \
8859deaec5SRodney W. Grimes 		_name[_startbyte] &= 0xff >> (8 - (_start&0x7)); \
8959deaec5SRodney W. Grimes 		while (++_startbyte < _stopbyte) \
9059deaec5SRodney W. Grimes 			_name[_startbyte] = 0; \
9159deaec5SRodney W. Grimes 		_name[_stopbyte] &= 0xff << ((_stop&0x7) + 1); \
9259deaec5SRodney W. Grimes 	} \
93*fc395092SDavid Malone } while (0)
9459deaec5SRodney W. Grimes 
9559deaec5SRodney W. Grimes 				/* set bits start ... stop in bitstring */
96*fc395092SDavid Malone #define	bit_nset(name, start, stop) do { \
97*fc395092SDavid Malone 	register bitstr_t *_name = (name); \
98*fc395092SDavid Malone 	register int _start = (start), _stop = (stop); \
9959deaec5SRodney W. Grimes 	register int _startbyte = _bit_byte(_start); \
10059deaec5SRodney W. Grimes 	register int _stopbyte = _bit_byte(_stop); \
10159deaec5SRodney W. Grimes 	if (_startbyte == _stopbyte) { \
10259deaec5SRodney W. Grimes 		_name[_startbyte] |= ((0xff << (_start&0x7)) & \
10359deaec5SRodney W. Grimes 				    (0xff >> (7 - (_stop&0x7)))); \
10459deaec5SRodney W. Grimes 	} else { \
10559deaec5SRodney W. Grimes 		_name[_startbyte] |= 0xff << ((_start)&0x7); \
10659deaec5SRodney W. Grimes 		while (++_startbyte < _stopbyte) \
10759deaec5SRodney W. Grimes 	    		_name[_startbyte] = 0xff; \
10859deaec5SRodney W. Grimes 		_name[_stopbyte] |= 0xff >> (7 - (_stop&0x7)); \
10959deaec5SRodney W. Grimes 	} \
110*fc395092SDavid Malone } while (0)
11159deaec5SRodney W. Grimes 
11259deaec5SRodney W. Grimes 				/* find first bit clear in name */
113*fc395092SDavid Malone #define	bit_ffc(name, nbits, value) do { \
114*fc395092SDavid Malone 	register bitstr_t *_name = (name); \
115*fc395092SDavid Malone 	register int _byte, _nbits = (nbits); \
116*fc395092SDavid Malone 	register int _stopbyte = _bit_byte(_nbits - 1), _value = -1; \
117*fc395092SDavid Malone 	if (_nbits > 0) \
11859deaec5SRodney W. Grimes 		for (_byte = 0; _byte <= _stopbyte; ++_byte) \
11959deaec5SRodney W. Grimes 			if (_name[_byte] != 0xff) { \
120*fc395092SDavid Malone 				bitstr_t _lb; \
12159deaec5SRodney W. Grimes 				_value = _byte << 3; \
122*fc395092SDavid Malone 				for (_lb = _name[_byte]; (_lb&0x1); \
123*fc395092SDavid Malone 				    ++_value, _lb >>= 1); \
12459deaec5SRodney W. Grimes 				break; \
12559deaec5SRodney W. Grimes 			} \
126*fc395092SDavid Malone 	if (_value >= nbits) \
127*fc395092SDavid Malone 		_value = -1; \
12859deaec5SRodney W. Grimes 	*(value) = _value; \
129*fc395092SDavid Malone } while (0)
13059deaec5SRodney W. Grimes 
13159deaec5SRodney W. Grimes 				/* find first bit set in name */
132*fc395092SDavid Malone #define	bit_ffs(name, nbits, value) do { \
133*fc395092SDavid Malone 	register bitstr_t *_name = (name); \
134*fc395092SDavid Malone 	register int _byte, _nbits = (nbits); \
135*fc395092SDavid Malone 	register int _stopbyte = _bit_byte(_nbits - 1), _value = -1; \
136*fc395092SDavid Malone 	if (_nbits > 0) \
13759deaec5SRodney W. Grimes 		for (_byte = 0; _byte <= _stopbyte; ++_byte) \
13859deaec5SRodney W. Grimes 			if (_name[_byte]) { \
139*fc395092SDavid Malone 				bitstr_t _lb; \
14059deaec5SRodney W. Grimes 				_value = _byte << 3; \
141*fc395092SDavid Malone 				for (_lb = _name[_byte]; !(_lb&0x1); \
142*fc395092SDavid Malone 				    ++_value, _lb >>= 1); \
14359deaec5SRodney W. Grimes 				break; \
14459deaec5SRodney W. Grimes 			} \
145*fc395092SDavid Malone 	if (_value >= nbits) \
146*fc395092SDavid Malone 		_value = -1; \
14759deaec5SRodney W. Grimes 	*(value) = _value; \
148*fc395092SDavid Malone } while (0)
14959deaec5SRodney W. Grimes 
15059deaec5SRodney W. Grimes #endif /* !_BITSTRING_H_ */
151