1
7
8
14
15
#
ifndef _INCLUDE__UTIL__BIT_ARRAY_H_
16
#
define _INCLUDE__UTIL__BIT_ARRAY_H_
17
18
#
include <util/string.h>
19
#
include <base/exception.h>
20
#
include <base/stdint.h>
21
22
namespace
Genode {
23
24
class
Bit_array_base;
25
template
<
unsigned
>
class
Bit_array;
26
}
27
28
29
class
Genode::
Bit_array_base
30
{
31
public
:
32
33
class
Invalid_bit_count :
public
Exception
{
}
;
34
class
Invalid_index_access :
public
Exception
{
}
;
35
class
Invalid_clear :
public
Exception
{
}
;
36
class
Invalid_set :
public
Exception
{
}
;
37
38
private
:
39
40
enum
{
41
BITS_PER_BYTE =
8UL
,
42
BITS_PER_WORD
=
sizeof
(
addr_t)
*
BITS_PER_BYTE
43
}
;
44
45
unsigned
_bit_cnt;
46
unsigned
_word_cnt;
47
addr_t *
_words;
48
49
addr_t
_word(
addr_t
index
)
const
{
50
return
index /
BITS_PER_WORD
;
}
51
52
void
_check_range(
addr_t const
index
,
53
addr_t const
width
)
const
54
{
55
if
(
(
index >=
_word_cnt *
BITS_PER_WORD)
||
56
width >
_word_cnt *
BITS_PER_WORD ||
57
_word_cnt *
BITS_PER_WORD -
width <
index)
58
throw
Invalid_index_access(
)
;
59
}
60
61
addr_t
_mask(
addr_t const
index
,
addr_t const
width
,
62
addr_t &
rest
)
const
63
{
64
addr_t const
shift =
index -
_word(
index)
*
BITS_PER_WORD;
65
66
rest =
width +
shift >
BITS_PER_WORD ?
67
width +
shift -
BITS_PER_WORD : 0;
68
69
return
(
width >=
BITS_PER_WORD)
?
~
0UL <<
shift
70
: (
(
1UL <<
width)
-
1)
<<
shift
;
71
}
72
73
void
_set(
addr_t
index
,
addr_t
width
,
bool
free
)
74
{
75
_check_range(
index,
width)
;
76
77
addr_t rest,
word,
mask;
78
do
{
79
word =
_word(
index)
;
80
mask =
_mask(
index,
width,
rest)
;
81
82
if
(
free)
{
83
if
(
(
_words[word] &
mask)
!=
mask)
84
throw
Invalid_clear(
)
;
85
_words[word]
&=
~
mask;
86
}
else
{
87
if
(
_words[word] &
mask)
88
throw
Invalid_set(
)
;
89
_words[word]
|=
mask;
90
}
91
92
index =
(
_word(
index)
+
1)
*
BITS_PER_WORD;
93
width =
rest;
94
}
while
(
rest)
;
95
}
96
97
public
:
98
99
Bit_array_base(
unsigned
bits
,
addr_t *
addr
,
bool
clear
)
100
:
_bit_cnt(
bits)
,
101
_word_cnt(
_bit_cnt /
BITS_PER_WORD)
,
102
_words(
addr)
103
{
104
if
(
!
bits ||
bits %
BITS_PER_WORD)
throw
Invalid_bit_count(
)
;
105
106
if
(
clear)
memset(
_words,
0,
sizeof
(
addr_t)
*
_word_cnt)
;
107
}
108
109
113
bool
get(
addr_t
index
,
addr_t
width
)
const
114
{
115
_check_range(
index,
width)
;
116
117
bool used =
false;
118
addr_t rest,
mask;
119
do
{
120
mask =
_mask(
index,
width,
rest)
;
121
used =
_words[_word(
index)
]
&
mask;
122
index =
(
_word(
index)
+
1)
*
BITS_PER_WORD;
123
width =
rest;
124
}
while
(
!
used &&
rest)
;
125
126
return
used
;
127
}
128
129
void
set(
addr_t const
index
,
addr_t const
width
)
{
130
_set(
index,
width,
false)
;
}
131
132
void
clear(
addr_t const
index
,
addr_t const
width
)
{
133
_set(
index,
width,
true)
;
}
134
}
;
135
136
137
template
<
unsigned
BITS
>
138
class
Genode::
Bit_array :
public
Bit_array_base
139
{
140
private
:
141
142
static
constexpr
size_t _WORDS =
BITS /
BITS_PER_WORD;
143
144
static_assert(
BITS %
BITS_PER_WORD ==
0
,
145
"Count of bits need to be word aligned!"
)
;
146
147
addr_t _array[_WORDS]
;
148
149
public
:
150
151
Bit_array(
)
:
Bit_array_base(
BITS,
_array,
true)
{
}
152
}
;
153
154
#
endif