* allocating less than 4 bytes.
*/
bits = new unsigned char[bits_size];
- freebits = new unsigned char[bits_size];
memset(bits, 0, bits_size);
- memset(freebits, 0, bits_size);
}
irc::dynamicbitmask::~dynamicbitmask()
{
/* Tidy up the entire used memory on delete */
delete[] bits;
- delete[] freebits;
}
irc::bitfield irc::dynamicbitmask::Allocate()
{
- for (size_t i = 0; i < bits_size; i++)
+ /* Yeah, this isnt too efficient, however a module or the core
+ * should only be allocating bitfields on load, the Toggle and
+ * Get methods are O(1) as these are called much more often.
+ */
+ unsigned char* freebits = this->GetFreeBits();
+ for (unsigned char i = 0; i < bits_size; i++)
{
+ /* Yes, this is right. You'll notice we terminate the loop when !current_pos,
+ * this is because we logic shift our bit off the end of unsigned char, and its
+ * lost, making the loop counter 0 when we're done.
+ */
for (unsigned char current_pos = 1; current_pos; current_pos = current_pos << 1)
{
if (!(freebits[i] & current_pos))
}
}
/* We dont have any free space left, increase by one */
- int old_bits_size = bits_size;
+
+ if (bits_size == 255)
+ /* Oh dear, cant grow it any further */
+ throw std::bad_alloc();
+
+ unsigned char old_bits_size = bits_size;
bits_size++;
/* Allocate new bitfield space */
unsigned char* temp_bits = new unsigned char[bits_size];
*/
bits = temp_bits;
freebits = temp_freebits;
+ this->SetFreeBits(freebits);
/* Initialize the new byte on the end of
* the bitfields, pre-allocate the one bit
* for this allocation
*/
bits[old_bits_size] = 0;
- bits[old_bits_size] = 1;
+ freebits[old_bits_size] = 1;
/* We already know where we just allocated
* the bitfield, so no loop needed
*/
*/
if (pos.first < bits_size)
{
- freebits[pos.first] &= ~pos.second;
+ this->GetFreeBits()[pos.first] &= ~pos.second;
return true;
}
/* They gave a bitfield outside of the
void irc::dynamicbitmask::Toggle(irc::bitfield &pos, bool state)
{
+ /* Range check the value */
if (pos.first < bits_size)
{
if (state)
}
}
+bool irc::dynamicbitmask::Get(irc::bitfield &pos)
+{
+ /* Range check the value */
+ if (pos.first < bits_size)
+ return (bits[pos.first] & pos.second);
+ else
+ /* We can't return false, otherwise we can't
+ * distinguish between failure and a cleared bit!
+ * Our only sensible choice is to throw (ew).
+ */
+ throw ModuleException("irc::dynamicbitmask::Get(): Invalid bitfield, out of range");
+}
+
+unsigned char irc::dynamicbitmask::GetSize()
+{
+ return bits_size;
+}
+