#ifndef L2_BITMAP_H | |||||
#define L2_BITMAP_H | |||||
#include <stdlib.h> | |||||
#include <stdint.h> | |||||
typedef long long int l2_bitmap_entry; | |||||
struct l2_bitmap { | |||||
l2_bitmap_entry *tables; | |||||
size_t tableslen; | |||||
size_t currtable; | |||||
l2_bitmap_entry *dirs; | |||||
size_t dirslen; | |||||
size_t currdir; | |||||
}; | |||||
void l2_bitmap_init(struct l2_bitmap *bm); | |||||
void l2_bitmap_free(struct l2_bitmap *bm); | |||||
int l2_bitmap_get(struct l2_bitmap *bm, size_t id); | |||||
size_t l2_bitmap_set_next(struct l2_bitmap *bm); | |||||
void l2_bitmap_unset(struct l2_bitmap *bm, size_t id); | |||||
#endif |
#ifndef L2_BITSET_H | |||||
#define L2_BITSET_H | |||||
#include <stdlib.h> | |||||
#include <stdint.h> | |||||
typedef long long int l2_bitset_entry; | |||||
struct l2_bitset { | |||||
l2_bitset_entry *tables; | |||||
size_t tableslen; | |||||
size_t currtable; | |||||
l2_bitset_entry *dirs; | |||||
size_t dirslen; | |||||
size_t currdir; | |||||
}; | |||||
void l2_bitset_init(struct l2_bitset *bs); | |||||
void l2_bitset_free(struct l2_bitset *bs); | |||||
int l2_bitset_get(struct l2_bitset *bs, size_t id); | |||||
size_t l2_bitset_set_next(struct l2_bitset *bs); | |||||
void l2_bitset_unset(struct l2_bitset *bs, size_t id); | |||||
#endif |
#include "bitmap.h" | |||||
#include <string.h> | |||||
#include <strings.h> | |||||
#include <limits.h> | |||||
#include <stdio.h> | |||||
#define ENTSIZ (sizeof(l2_bitmap_entry) * CHAR_BIT) | |||||
static l2_bitmap_entry first_unset_bit(l2_bitmap_entry n) { | |||||
return ~n & (n + 1); | |||||
} | |||||
#if 0 && defined(__GLIBC__) && ( \ | |||||
(__GLIBC__>= 2 && __GLIBC_MINOR__ >= 27) || \ | |||||
_GNU_SOURCE) | |||||
#define first_set ffsll | |||||
#else | |||||
static int first_set(l2_bitmap_entry n) { | |||||
if (n == 0) { | |||||
return 0; | |||||
} | |||||
int num = 1; | |||||
while ((n & 1) == 0) { | |||||
n >>= 1; | |||||
num += 1; | |||||
} | |||||
return num; | |||||
} | |||||
#endif | |||||
static void expand_tables(struct l2_bitmap *bm) { | |||||
while (bm->currtable >= bm->tableslen) { | |||||
bm->tables = realloc(bm->tables, bm->tableslen * 2 * sizeof(*bm->tables)); | |||||
memset(bm->tables + bm->tableslen, 0, sizeof(*bm->tables) * bm->tableslen); | |||||
bm->tableslen *= 2; | |||||
} | |||||
} | |||||
void l2_bitmap_init(struct l2_bitmap *bm) { | |||||
bm->tableslen = 4; | |||||
bm->tables = calloc(bm->tableslen, sizeof(*bm->tables)); | |||||
bm->currtable = 0; | |||||
bm->dirslen = 1; | |||||
bm->dirs = calloc(bm->dirslen, sizeof(*bm->dirs)); | |||||
bm->currdir = 0; | |||||
} | |||||
void l2_bitmap_free(struct l2_bitmap *bm) { | |||||
free(bm->tables); | |||||
free(bm->dirs); | |||||
} | |||||
int l2_bitmap_get(struct l2_bitmap *bm, size_t id) { | |||||
size_t tblidx = id / ENTSIZ; | |||||
size_t tblbit = id % ENTSIZ; | |||||
if (tblidx >= bm->tableslen) { | |||||
return 0; | |||||
} | |||||
return !!(bm->tables[tblidx] & (l2_bitmap_entry)1 << tblbit); | |||||
} | |||||
size_t l2_bitmap_set_next(struct l2_bitmap *bm) { | |||||
l2_bitmap_entry *table = &bm->tables[bm->currtable]; | |||||
l2_bitmap_entry bit = first_unset_bit(*table); | |||||
*table |= bit; | |||||
size_t ret = bm->currtable * ENTSIZ + first_set(bit) - 1; | |||||
// Still free space? | |||||
if (*table != ~(l2_bitmap_entry)0) { | |||||
return ret; | |||||
} | |||||
// Ok, this entry is full then... | |||||
l2_bitmap_entry *dir = &bm->dirs[bm->currdir]; | |||||
*dir |= (l2_bitmap_entry)1 << (bm->currtable % ENTSIZ); | |||||
// Is there still space in this directory? | |||||
if (*dir != ~(l2_bitmap_entry)0) { | |||||
bm->currtable = bm->currdir * ENTSIZ + first_set(first_unset_bit(*dir)) - 1; | |||||
expand_tables(bm); | |||||
return ret; | |||||
} | |||||
// Is there a directory with free space? | |||||
for (size_t i = 0; i < bm->dirslen; ++i) { | |||||
dir = &bm->dirs[i]; | |||||
if (*dir == ~(l2_bitmap_entry)0) { | |||||
continue; | |||||
} | |||||
bm->currdir = i; | |||||
bm->currtable = bm->currdir * ENTSIZ + first_set(first_unset_bit(*dir)) - 1; | |||||
expand_tables(bm); | |||||
return ret; | |||||
} | |||||
// Ok, we gotta make a new dir then | |||||
bm->currdir = bm->dirslen; | |||||
bm->currtable = bm->currdir * ENTSIZ; | |||||
bm->dirs = realloc(bm->dirs, bm->dirslen * 2 * sizeof(*bm->dirs)); | |||||
memset(bm->dirs + bm->dirslen, 0, sizeof(*bm->dirs) * bm->dirslen); | |||||
bm->dirslen *= 2; | |||||
expand_tables(bm); | |||||
return ret; | |||||
} | |||||
void l2_bitmap_unset(struct l2_bitmap *bm, size_t id) { | |||||
size_t tblidx = id / ENTSIZ; | |||||
size_t tblbit = id % ENTSIZ; | |||||
size_t diridx = id / (ENTSIZ * ENTSIZ); | |||||
size_t dirbit = (id / ENTSIZ) % ENTSIZ; | |||||
if (tblidx >= bm->tableslen) { | |||||
return; | |||||
} | |||||
bm->tables[tblidx] &= ~((l2_bitmap_entry)1 << tblbit); | |||||
bm->dirs[diridx] &= ~((l2_bitmap_entry)1 << dirbit); | |||||
} |
#include "bitset.h" | |||||
#include <string.h> | |||||
#include <strings.h> | |||||
#include <limits.h> | |||||
#include <stdio.h> | |||||
#define ENTSIZ (sizeof(l2_bitset_entry) * CHAR_BIT) | |||||
static l2_bitset_entry first_unset_bit(l2_bitset_entry n) { | |||||
return ~n & (n + 1); | |||||
} | |||||
#if 0 && defined(__GLIBC__) && ( \ | |||||
(__GLIBC__>= 2 && __GLIBC_MINOR__ >= 27) || \ | |||||
_GNU_SOURCE) | |||||
#define first_set ffsll | |||||
#else | |||||
static int first_set(l2_bitset_entry n) { | |||||
if (n == 0) { | |||||
return 0; | |||||
} | |||||
int num = 1; | |||||
while ((n & 1) == 0) { | |||||
n >>= 1; | |||||
num += 1; | |||||
} | |||||
return num; | |||||
} | |||||
#endif | |||||
static void expand_tables(struct l2_bitset *bs) { | |||||
while (bs->currtable >= bs->tableslen) { | |||||
bs->tables = realloc(bs->tables, bs->tableslen * 2 * sizeof(*bs->tables)); | |||||
memset(bs->tables + bs->tableslen, 0, sizeof(*bs->tables) * bs->tableslen); | |||||
bs->tableslen *= 2; | |||||
} | |||||
} | |||||
void l2_bitset_init(struct l2_bitset *bs) { | |||||
bs->tableslen = 4; | |||||
bs->tables = calloc(bs->tableslen, sizeof(*bs->tables)); | |||||
bs->currtable = 0; | |||||
bs->dirslen = 1; | |||||
bs->dirs = calloc(bs->dirslen, sizeof(*bs->dirs)); | |||||
bs->currdir = 0; | |||||
} | |||||
void l2_bitset_free(struct l2_bitset *bs) { | |||||
free(bs->tables); | |||||
free(bs->dirs); | |||||
} | |||||
int l2_bitset_get(struct l2_bitset *bs, size_t id) { | |||||
size_t tblidx = id / ENTSIZ; | |||||
size_t tblbit = id % ENTSIZ; | |||||
if (tblidx >= bs->tableslen) { | |||||
return 0; | |||||
} | |||||
return !!(bs->tables[tblidx] & (l2_bitset_entry)1 << tblbit); | |||||
} | |||||
size_t l2_bitset_set_next(struct l2_bitset *bs) { | |||||
l2_bitset_entry *table = &bs->tables[bs->currtable]; | |||||
l2_bitset_entry bit = first_unset_bit(*table); | |||||
*table |= bit; | |||||
size_t ret = bs->currtable * ENTSIZ + first_set(bit) - 1; | |||||
// Still free space? | |||||
if (*table != ~(l2_bitset_entry)0) { | |||||
return ret; | |||||
} | |||||
// Ok, this entry is full then... | |||||
l2_bitset_entry *dir = &bs->dirs[bs->currdir]; | |||||
*dir |= (l2_bitset_entry)1 << (bs->currtable % ENTSIZ); | |||||
// Is there still space in this directory? | |||||
if (*dir != ~(l2_bitset_entry)0) { | |||||
bs->currtable = bs->currdir * ENTSIZ + first_set(first_unset_bit(*dir)) - 1; | |||||
expand_tables(bs); | |||||
return ret; | |||||
} | |||||
// Is there a directory with free space? | |||||
for (size_t i = 0; i < bs->dirslen; ++i) { | |||||
dir = &bs->dirs[i]; | |||||
if (*dir == ~(l2_bitset_entry)0) { | |||||
continue; | |||||
} | |||||
bs->currdir = i; | |||||
bs->currtable = bs->currdir * ENTSIZ + first_set(first_unset_bit(*dir)) - 1; | |||||
expand_tables(bs); | |||||
return ret; | |||||
} | |||||
// Ok, we gotta make a new dir then | |||||
bs->currdir = bs->dirslen; | |||||
bs->currtable = bs->currdir * ENTSIZ; | |||||
bs->dirs = realloc(bs->dirs, bs->dirslen * 2 * sizeof(*bs->dirs)); | |||||
memset(bs->dirs + bs->dirslen, 0, sizeof(*bs->dirs) * bs->dirslen); | |||||
bs->dirslen *= 2; | |||||
expand_tables(bs); | |||||
return ret; | |||||
} | |||||
void l2_bitset_unset(struct l2_bitset *bs, size_t id) { | |||||
size_t tblidx = id / ENTSIZ; | |||||
size_t tblbit = id % ENTSIZ; | |||||
size_t diridx = id / (ENTSIZ * ENTSIZ); | |||||
size_t dirbit = (id / ENTSIZ) % ENTSIZ; | |||||
if (tblidx >= bs->tableslen) { | |||||
return; | |||||
} | |||||
bs->tables[tblidx] &= ~((l2_bitset_entry)1 << tblbit); | |||||
bs->dirs[diridx] &= ~((l2_bitset_entry)1 << dirbit); | |||||
} |