Add idmap_from_range constructor
authorDenis Kenzior <denkenz@gmail.com>
Thu, 7 Jan 2010 19:20:48 +0000 (13:20 -0600)
committerDenis Kenzior <denkenz@gmail.com>
Thu, 7 Jan 2010 19:20:48 +0000 (13:20 -0600)
src/idmap.c
src/idmap.h

index f56c8e5..a42bf11 100644 (file)
@@ -36,6 +36,8 @@
 struct idmap {
        unsigned long *bits;
        unsigned int size;
+       unsigned int min;
+       unsigned int max;
 };
 
 static inline int ffz(unsigned long word)
@@ -97,35 +99,43 @@ found_middle:
        return result + ffz(tmp);
 }
 
-struct idmap *idmap_new(unsigned int size)
+struct idmap *idmap_new_from_range(unsigned int min, unsigned int max)
 {
        struct idmap *ret = g_new0(struct idmap, 1);
+       unsigned int size = max - min + 1;
 
        ret->bits = g_new0(unsigned long,
                                (size + BITS_PER_LONG - 1) / BITS_PER_LONG);
        ret->size = size;
+       ret->min = min;
+       ret->max = max;
 
        return ret;
 }
 
+struct idmap *idmap_new(unsigned int size)
+{
+       return idmap_new_from_range(1, size);
+}
+
 void idmap_free(struct idmap *idmap)
 {
        g_free(idmap->bits);
        g_free(idmap);
 }
 
-void idmap_put(struct idmap *idmap, unsigned int bit)
+void idmap_put(struct idmap *idmap, unsigned int id)
 {
-       unsigned int offset = (bit - 1) / BITS_PER_LONG;
+       unsigned int offset = (id - idmap->min) / BITS_PER_LONG;
 
-       bit -= 1;
+       id -= idmap->min;
 
-       if (bit > idmap->size)
+       if (id > idmap->size)
                return;
 
-       bit %= BITS_PER_LONG;
+       id %= BITS_PER_LONG;
 
-       idmap->bits[offset] &= ~(1 << bit);
+       idmap->bits[offset] &= ~(1 << id);
 }
 
 unsigned int idmap_alloc(struct idmap *idmap)
@@ -141,18 +151,21 @@ unsigned int idmap_alloc(struct idmap *idmap)
        offset = bit / BITS_PER_LONG;
        idmap->bits[offset] |= 1 << (bit % BITS_PER_LONG);
 
-       return bit + 1;
+       return bit + idmap->min;
 }
 
 /*
- * Allocate the next bit skipping the first last bits
+ * Allocate the next bit skipping the ids up to and including last.  If there
+ * is no free ids until the max id is encountered, the counter is wrapped back
+ * to min and the search starts again.
  */
 unsigned int idmap_alloc_next(struct idmap *idmap, unsigned int last)
 {
        unsigned int bit;
        unsigned int offset;
 
-       bit = find_next_zero_bit(idmap->bits, idmap->size, last);
+       bit = find_next_zero_bit(idmap->bits, idmap->size,
+                                       last - idmap->min + 1);
 
        if (bit >= idmap->size)
                return idmap_alloc(idmap);
@@ -160,5 +173,15 @@ unsigned int idmap_alloc_next(struct idmap *idmap, unsigned int last)
        offset = bit / BITS_PER_LONG;
        idmap->bits[offset] |= 1 << (bit % BITS_PER_LONG);
 
-       return bit + 1;
+       return bit + idmap->min;
+}
+
+unsigned int idmap_get_min(struct idmap *idmap)
+{
+       return idmap->min;
+}
+
+unsigned int idmap_get_max(struct idmap *idmap)
+{
+       return idmap->max;
 }
index 6f66ffc..73e226e 100644 (file)
@@ -26,3 +26,6 @@ void idmap_free(struct idmap *idmap);
 void idmap_put(struct idmap *idmap, unsigned int bit);
 unsigned int idmap_alloc(struct idmap *idmap);
 unsigned int idmap_alloc_next(struct idmap *idmap, unsigned int last);
+struct idmap *idmap_new_from_range(unsigned int min, unsigned int max);
+unsigned int idmap_get_min(struct idmap *idmap);
+unsigned int idmap_get_max(struct idmap *idmap);