The Pedigree Project 0.1
ExtensibleBitmap.cc
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include "pedigree/kernel/utilities/ExtensibleBitmap.h"
21#include "pedigree/kernel/utilities/utility.h"
22
24 : m_StaticMap(0),
25 m_pDynamicMap(0),
26 m_DynamicMapSize(0),
27 m_nMaxBit(0),
28 m_nFirstSetBit(~0U),
29 m_nFirstClearBit(0),
30 m_nLastSetBit(~0U),
31 m_nLastClearBit(0) {}
32
34 : m_StaticMap(other.m_StaticMap),
35 m_pDynamicMap(0),
36 m_DynamicMapSize(other.m_DynamicMapSize),
37 m_nMaxBit(other.m_nMaxBit),
38 m_nFirstSetBit(other.m_nFirstSetBit),
39 m_nFirstClearBit(other.m_nFirstClearBit),
40 m_nLastSetBit(other.m_nLastSetBit),
41 m_nLastClearBit(other.m_nLastClearBit) {
42 if (m_DynamicMapSize) {
43 m_pDynamicMap = new uint8_t[m_DynamicMapSize];
44 MemoryCopy(m_pDynamicMap, other.m_pDynamicMap, m_DynamicMapSize);
45 }
46}
47
49 if (this == &other) {
50 return *this;
51 }
52
53 m_StaticMap = other.m_StaticMap;
54
55 if (m_DynamicMapSize < other.m_DynamicMapSize) {
56 uint8_t* pMap = new uint8_t[other.m_DynamicMapSize];
57 delete[] m_pDynamicMap;
58 m_pDynamicMap = pMap;
59 m_DynamicMapSize = other.m_DynamicMapSize;
60 }
61
62 if (other.m_DynamicMapSize) {
63 MemoryCopy(m_pDynamicMap, other.m_pDynamicMap, other.m_DynamicMapSize);
64 } else if (m_pDynamicMap) {
66 }
67 m_nMaxBit = other.m_nMaxBit;
68 m_nFirstSetBit = other.m_nFirstSetBit;
69 m_nFirstClearBit = other.m_nFirstClearBit;
70 m_nLastSetBit = other.m_nLastSetBit;
71 m_nLastClearBit = other.m_nLastClearBit;
72
73 return *this;
74}
75
80
81void ExtensibleBitmap::set(size_t n) {
82 // Check if the bit we'll set becomes the first set bit
83 if ((n < m_nFirstSetBit) || (m_nFirstSetBit == ~0U))
85 // Check if the bit we'll set becomes the last set bit
86 if ((n > m_nLastSetBit) || (m_nLastSetBit == ~0U))
87 m_nLastSetBit = n;
88 // Check if the bit we'll set replaces the first clear bit
89 if (n == m_nFirstClearBit) {
90 do {
91 m_nFirstClearBit++;
92 } while (test(m_nFirstClearBit));
93 }
94
95 /*if(n == m_nLastClearBit)
96 {
97 for(size_t i = n;i;i--)
98 {
99 if(!test(i))
100 {
101 m_nLastClearBit = i;
102 break;
103 }
104 }
105 }*/
106
107 if (n < sizeof(uintptr_t) * 8) {
108 m_StaticMap |= (1UL << n);
109 return;
110 }
111
112 n -= sizeof(uintptr_t) * 8;
113
114 // Check we have enough space to handle the bit.
115 if (n / 8 >= m_DynamicMapSize) {
116 // Double the size of the map to avoid so many allocations/copies/zeroes
117 // ... unless the bit itself is well beyond that range!
118 size_t sz = max(n / 8 + 8, m_DynamicMapSize * 2);
119 uint8_t* pMap = new uint8_t[sz];
120 uint8_t* oldMap = m_pDynamicMap;
121 if (m_DynamicMapSize && oldMap) {
122 MemoryCopy(pMap, oldMap, m_DynamicMapSize);
123 }
124 // zero out the rest of the new memory now
125 ByteSet(pMap + m_DynamicMapSize, 0, sz - m_DynamicMapSize);
126 m_pDynamicMap = pMap;
127 if (oldMap) {
128 delete[] oldMap;
129 }
130 m_DynamicMapSize = sz;
131 }
132
133 m_pDynamicMap[n / 8] |= (1UL << (n % 8));
134 if (n > m_nMaxBit)
135 m_nMaxBit = n;
136}
137
139 if (!test(n)) {
140 return;
141 }
142
143 if (n < sizeof(uintptr_t) * 8) {
144 m_StaticMap &= ~(1UL << n);
145 } else {
146 const size_t dynamicBit = n - sizeof(uintptr_t) * 8;
147 m_pDynamicMap[dynamicBit / 8] &= ~(1UL << (dynamicBit % 8));
148 }
149
150 // Check if the bit we'll clear becomes the first clear bit
151 if (n < m_nFirstClearBit) {
152 m_nFirstClearBit = n;
153 }
154 // Check if the bit we'll clear replaces the first set bit
155 if (n == m_nFirstSetBit) {
156 m_nFirstSetBit = ~0U;
157 for (size_t i = n + 1; i <= m_nLastSetBit; ++i) {
158 if (test(i)) {
159 m_nFirstSetBit = i;
160 break;
161 }
162 }
163 }
164 // Check if the bit we'll clear replaces the last set bit
165 if (n == m_nLastSetBit) {
166 m_nLastSetBit = ~0U;
167 for (size_t i = n; i > 0;) {
168 --i;
169 if (test(i)) {
170 m_nLastSetBit = i;
171 break;
172 }
173 }
174 }
175}
176
177bool ExtensibleBitmap::test(size_t n) const {
178 if (n < sizeof(uintptr_t) * 8)
179 return (m_StaticMap & (1UL << n));
180
181 n -= sizeof(uintptr_t) * 8;
182
183 // If its outside the range of possible set bits, it must be clear.
184 if (n > m_nMaxBit || !m_pDynamicMap)
185 return false;
186 return (m_pDynamicMap[n / 8] & (1UL << (n % 8)));
187}
bool test(size_t n) const
void clear(size_t n)
void set(size_t n)
ExtensibleBitmap & operator=(const ExtensibleBitmap &other)