Browse Source

bitmap -> bitset

master
Martin Dørum 3 years ago
parent
commit
81b407fe4e
4 changed files with 150 additions and 150 deletions
  1. 0
    25
      include/lang2/bitmap.h
  2. 25
    0
      include/lang2/bitset.h
  3. 0
    125
      src/bitmap.c
  4. 125
    0
      src/bitset.c

+ 0
- 25
include/lang2/bitmap.h View File

@@ -1,25 +0,0 @@
#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

+ 25
- 0
include/lang2/bitset.h View File

@@ -0,0 +1,25 @@
#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

+ 0
- 125
src/bitmap.c View File

@@ -1,125 +0,0 @@
#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);
}

+ 125
- 0
src/bitset.c View File

@@ -0,0 +1,125 @@
#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);
}

Loading…
Cancel
Save