]> git.netwichtig.de Git - user/henk/code/inspircd.git/blobdiff - src/hashcomp.cpp
Tidyup
[user/henk/code/inspircd.git] / src / hashcomp.cpp
index 23d4928a627873607f3670c20df54828b26e4866..27c71defa6aeb0901086bce78235a5439aa49646 100644 (file)
@@ -480,22 +480,28 @@ irc::dynamicbitmask::dynamicbitmask() : bits_size(4)
         * 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))
@@ -506,7 +512,12 @@ irc::bitfield irc::dynamicbitmask::Allocate()
                }
        }
        /* 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];
@@ -522,12 +533,13 @@ irc::bitfield irc::dynamicbitmask::Allocate()
         */
        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
         */
@@ -546,7 +558,7 @@ bool irc::dynamicbitmask::Deallocate(irc::bitfield &pos)
         */
        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
@@ -557,6 +569,7 @@ bool irc::dynamicbitmask::Deallocate(irc::bitfield &pos)
 
 void irc::dynamicbitmask::Toggle(irc::bitfield &pos, bool state)
 {
+       /* Range check the value */
        if (pos.first < bits_size)
        {
                if (state)
@@ -568,3 +581,21 @@ void irc::dynamicbitmask::Toggle(irc::bitfield &pos, bool 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;
+}
+