forked from fantaisie-software/purebasic
-
Notifications
You must be signed in to change notification settings - Fork 1
/
bitset.c
121 lines (106 loc) · 3 KB
/
bitset.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/* bitset - a set of bits
* Copyright (c) 2003 Michael B. Allen <mba2000 ioplex.com>
*
* The MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <limits.h>
#include <errno.h>
#include "mba/msgno.h"
#include "mba/bitset.h"
#define bitset_elem(ptr,bit) ((unsigned char *)(ptr))[(bit)/CHAR_BIT]
#define bitset_mask(bit) (1U << ((bit) % CHAR_BIT))
int
bitset_isset(void *ptr, int bit)
{
return (bitset_elem(ptr,bit) & bitset_mask(bit)) != 0;
}
int
bitset_set(void *ptr, int bit)
{
unsigned char *b = (unsigned char *)ptr + (bit / CHAR_BIT);
unsigned char m = bitset_mask(bit);
if ((*b & m)) return 0;
*b |= m;
return 1;
}
int
bitset_unset(void *ptr, int bit)
{
unsigned char *b = (unsigned char *)ptr + (bit / CHAR_BIT);
unsigned char m = bitset_mask(bit);
if ((*b & m) == 0) return 0;
*b &= ~m;
return 1;
}
void
bitset_toggle(void *ptr, int bit)
{
bitset_elem(ptr,bit) ^= bitset_mask(bit);
}
int
bitset_find_first(void *ptr, void *plim, int val)
{
unsigned char *start = ptr;
unsigned char *bs;
int cond = val ? 0x00 : 0xFF;
for (bs = start; bs < (unsigned char *)plim; bs++) {
if ((*bs & 0xFF) != cond) {
int b = *bs & 0xFF;
/* Index of the first bit that is 0 if
* val is 0 or 1 if val is 1.
*/
if (!val) {
b = ~b;
}
b = b & -b;
switch (b) {
case 1: b = 0; break;
case 2: b = 1; break;
case 4: b = 2; break;
case 8: b = 3; break;
case 16: b = 4; break;
case 32: b = 5; break;
case 64: b = 6; break;
case 128: b = 7; break;
}
return b + (bs - start) * 8;
}
}
PMNO(errno = ENOENT);
return -1;
}
void
bitset_iterate(iter_t *iter)
{
iter->i1 = 0;
}
int
bitset_next(void *ptr, void *plim, iter_t *iter)
{
unsigned char *b = (unsigned char *)ptr + iter->i1 / 8;
int ret = -1;
if (b < (unsigned char *)plim) {
unsigned long mask = 1 << (iter->i1 % 8);
iter->i1++;
ret = (*b & mask) != 0;
}
return ret;
}