/****************************************************************************** ******************************************************************************* ** ** Copyright (C) 2005 Red Hat, Inc. All rights reserved. ** ** This copyrighted material is made available to anyone wishing to use, ** modify, copy, or redistribute it subject to the terms and conditions ** of the GNU General Public License v.2. ** ******************************************************************************* ******************************************************************************/ /* Basic bitmap manipulation */ #include #include #include #include #include #include #include "bitmap.h" #define BITMAP_SIZE(size, cpb) (size / cpb) #define BITMAP_BYTE_OFFSET(x, map) ((x % map->chunks_per_byte) \ * map->chunksize ) #define BITMAP_MASK(chunksize) ((2 << (chunksize - 1)) - 1) uint64_t jeff_bitmap_size(struct jeff_bmap *bmap) { return bmap->size; } int jeff_bitmap_create(struct jeff_bmap *bmap, uint64_t size, uint8_t chunksize) { if((((chunksize >> 1) << 1) != chunksize) && chunksize != 1) return -1; if(chunksize > 8) return -1; bmap->chunksize = chunksize; bmap->chunks_per_byte = 8 / chunksize; bmap->size = size; /* Have to add 1 to BITMAP_SIZE since it's 0-based and mallocs * must be 1-based */ bmap->mapsize = BITMAP_SIZE(size, bmap->chunks_per_byte)+1; if(!(bmap->map = (char*)malloc(sizeof(char) * bmap->mapsize))) return -ENOMEM; if(!memset(bmap->map, 0, sizeof(char) * bmap->mapsize)) { free(bmap->map); bmap->map = NULL; return -ENOMEM; } return 0; } int jeff_bitmap_set(struct jeff_bmap *bmap, uint64_t offset, uint8_t val) { char *byte = NULL; uint64_t b = offset; if(offset < bmap->size) { byte = bmap->map + BITMAP_SIZE(offset, bmap->chunks_per_byte); b = BITMAP_BYTE_OFFSET(offset, bmap); *byte |= (val & BITMAP_MASK(bmap->chunksize)) << b; return 0; } return -1; } int jeff_bitmap_get(struct jeff_bmap *bmap, uint64_t bit, uint8_t *val) { char *byte = NULL; uint64_t b = bit; if(bit < bmap->size) { byte = bmap->map + BITMAP_SIZE(bit, bmap->chunks_per_byte); b = BITMAP_BYTE_OFFSET(bit, bmap); *val = (*byte & (BITMAP_MASK(bmap->chunksize) << b )) >> b; return 0; } return -1; } int jeff_bitmap_clear(struct jeff_bmap *bmap, uint64_t offset) { char *byte = NULL; uint64_t b = offset; if(offset < bmap->size) { byte = bmap->map + BITMAP_SIZE(offset, bmap->chunks_per_byte); b = BITMAP_BYTE_OFFSET(offset, bmap); *byte &= ~(BITMAP_MASK(bmap->chunksize) << b); return 0; } return -1; } void jeff_bitmap_destroy(struct jeff_bmap *bmap) { if(bmap->map) free(bmap->map); bmap->size = 0; bmap->mapsize = 0; bmap->chunksize = 0; bmap->chunks_per_byte = 0; }