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), m_pDynamicMap(0), m_DynamicMapSize(0), m_nMaxBit(0),
25  m_nFirstSetBit(~0U), m_nFirstClearBit(0), m_nLastSetBit(~0U),
26  m_nLastClearBit(0)
27 {
28 }
29 
34  m_nFirstClearBit(other.m_nFirstClearBit),
35  m_nLastSetBit(other.m_nLastSetBit), m_nLastClearBit(other.m_nLastClearBit)
36 {
37  m_pDynamicMap = new uint8_t[m_DynamicMapSize];
38  MemoryCopy(m_pDynamicMap, other.m_pDynamicMap, m_DynamicMapSize);
39 }
40 
42 {
43  m_StaticMap = other.m_StaticMap;
44 
46  {
47  uint8_t *pMap = new uint8_t[other.m_DynamicMapSize];
48  ByteSet(pMap, 0, other.m_DynamicMapSize);
49  if (m_DynamicMapSize)
50  delete[] m_pDynamicMap;
51  m_pDynamicMap = pMap;
53  }
54 
55  if (other.m_DynamicMapSize)
56  MemoryCopy(m_pDynamicMap, other.m_pDynamicMap, other.m_DynamicMapSize);
57  m_nMaxBit = other.m_nMaxBit;
59  m_nFirstClearBit = other.m_nFirstClearBit;
60  m_nLastSetBit = other.m_nLastSetBit;
61  m_nLastClearBit = other.m_nLastClearBit;
62 
63  return *this;
64 }
65 
67 {
68  if (m_pDynamicMap)
69  delete[] m_pDynamicMap;
70 }
71 
72 void ExtensibleBitmap::set(size_t n)
73 {
74  // Check if the bit we'll set becomes the first set bit
75  if ((n < m_nFirstSetBit) || (m_nFirstSetBit == ~0U))
76  m_nFirstSetBit = n;
77  // Check if the bit we'll set becomes the last set bit
78  if ((n > m_nLastSetBit) || (m_nLastSetBit == ~0U))
79  m_nLastSetBit = n;
80  // Check if the bit we'll set replaces the first clear bit
81  if (n == m_nFirstClearBit)
82  {
83  do
84  {
85  m_nFirstClearBit++;
86  } while (test(m_nFirstClearBit));
87  }
88 
89  /*if(n == m_nLastClearBit)
90  {
91  for(size_t i = n;i;i--)
92  {
93  if(!test(i))
94  {
95  m_nLastClearBit = i;
96  break;
97  }
98  }
99  }*/
100 
101  if (n < sizeof(uintptr_t) * 8)
102  {
103  m_StaticMap |= (1UL << n);
104  return;
105  }
106 
107  n -= sizeof(uintptr_t) * 8;
108 
109  // Check we have enough space to handle the bit.
110  if (n / 8 >= m_DynamicMapSize)
111  {
112  // Add another 8 bytes as a performance hint.
113  size_t sz = n / 8 + 8;
114  uint8_t *pMap = new uint8_t[sz];
115  ByteSet(pMap, 0, sz);
116  if (m_DynamicMapSize)
117  {
118  MemoryCopy(pMap, m_pDynamicMap, m_DynamicMapSize);
119  delete[] m_pDynamicMap;
120  }
121  m_pDynamicMap = pMap;
122  m_DynamicMapSize = sz;
123  }
124 
125  m_pDynamicMap[n / 8] |= (1UL << (n % 8));
126  if (n > m_nMaxBit)
127  m_nMaxBit = n;
128 }
129 
131 {
132  // Check if the bit we'll clear becomes the first clear bit
133  if (n < m_nFirstClearBit)
134  m_nFirstClearBit = n;
135  // Check if the bit we'll clear replaces the first set bit
136  if (n == m_nFirstSetBit)
137  {
138  for (size_t i = n; i <= sizeof(uintptr_t) * 8 + m_nMaxBit; i++)
139  {
140  if (test(i))
141  {
142  m_nFirstSetBit = i;
143  break;
144  }
145  }
146 
147  if (n == m_nFirstSetBit)
148  {
149  m_nFirstSetBit = ~0U;
150  }
151  }
152  // Check if the bit we'll clear replaces the last set bit
153  if (n == m_nLastSetBit)
154  {
155  // In case we won't find any set bit, this assures any bit set later
156  // will become the last set bit
157  m_nLastSetBit = 0;
158  for (size_t i = n; i; i--)
159  {
160  if (test(i))
161  {
162  m_nLastSetBit = i;
163  break;
164  }
165  }
166 
167  if (n == m_nLastSetBit)
168  {
169  m_nLastSetBit = ~0U;
170  }
171  }
172 
173  if (n < sizeof(uintptr_t) * 8)
174  {
175  m_StaticMap &= ~(1UL << n);
176  return;
177  }
178 
179  n -= sizeof(uintptr_t) * 8;
180 
181  // If its outside the range of possible set bits, it must be clear already.
182  if (n > m_nMaxBit || !m_pDynamicMap)
183  return;
184  m_pDynamicMap[n / 8] &= ~(1UL << (n % 8));
185 }
186 
187 bool ExtensibleBitmap::test(size_t n) const
188 {
189  if (n < sizeof(uintptr_t) * 8)
190  return (m_StaticMap & (1UL << n));
191 
192  n -= sizeof(uintptr_t) * 8;
193 
194  // If its outside the range of possible set bits, it must be clear.
195  if (n > m_nMaxBit || !m_pDynamicMap)
196  return false;
197  return (m_pDynamicMap[n / 8] & (1UL << (n % 8)));
198 }
bool test(size_t n) const
ExtensibleBitmap & operator=(const ExtensibleBitmap &other)
void set(size_t n)
uint8_t * m_pDynamicMap
void clear(size_t n)