1258945Sroberto/* 2258945Sroberto * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") 3258945Sroberto * Copyright (C) 1999-2001 Internet Software Consortium. 4258945Sroberto * 5258945Sroberto * Permission to use, copy, modify, and/or distribute this software for any 6258945Sroberto * purpose with or without fee is hereby granted, provided that the above 7258945Sroberto * copyright notice and this permission notice appear in all copies. 8258945Sroberto * 9258945Sroberto * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10258945Sroberto * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11258945Sroberto * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12258945Sroberto * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13258945Sroberto * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14258945Sroberto * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15258945Sroberto * PERFORMANCE OF THIS SOFTWARE. 16258945Sroberto */ 17258945Sroberto 18258945Sroberto/* $Id: bitstring.c,v 1.17 2007/06/19 23:47:17 tbox Exp $ */ 19258945Sroberto 20258945Sroberto/*! \file */ 21258945Sroberto 22258945Sroberto#include <config.h> 23258945Sroberto 24258945Sroberto#include <stddef.h> 25258945Sroberto 26258945Sroberto#include <isc/magic.h> 27258945Sroberto#include <isc/bitstring.h> 28258945Sroberto#include <isc/util.h> 29258945Sroberto 30258945Sroberto#define DIV8(x) ((x) >> 3) 31258945Sroberto#define MOD8(x) ((x) & 0x00000007U) 32258945Sroberto#define OCTETS(n) (((n) + 7) >> 3) 33258945Sroberto#define PADDED(n) ((((n) + 7) >> 3) << 3) 34258945Sroberto#define BITSET(bs, n) (((bs)->data[DIV8(n)] & \ 35258945Sroberto (1 << (7 - MOD8(n)))) != 0) 36258945Sroberto#define SETBIT(bs, n) (bs)->data[DIV8(n)] |= (1 << (7 - MOD8(n))) 37258945Sroberto#define CLEARBIT(bs, n) (bs)->data[DIV8(n)] &= ~(1 << (7 - MOD8(n))) 38258945Sroberto 39258945Sroberto#define BITSTRING_MAGIC ISC_MAGIC('B', 'S', 't', 'r') 40258945Sroberto#define VALID_BITSTRING(b) ISC_MAGIC_VALID(b, BITSTRING_MAGIC) 41258945Sroberto 42258945Srobertovoid 43258945Srobertoisc_bitstring_init(isc_bitstring_t *bitstring, unsigned char *data, 44258945Sroberto unsigned int length, unsigned int size, isc_boolean_t lsb0) 45258945Sroberto{ 46258945Sroberto /* 47258945Sroberto * Make 'bitstring' refer to the bitstring of 'size' bits starting 48258945Sroberto * at 'data'. 'length' bits of the bitstring are valid. If 'lsb0' 49258945Sroberto * is set then, bit 0 refers to the least significant bit of the 50258945Sroberto * bitstring. Otherwise bit 0 is the most significant bit. 51258945Sroberto */ 52258945Sroberto 53258945Sroberto REQUIRE(bitstring != NULL); 54258945Sroberto REQUIRE(data != NULL); 55258945Sroberto REQUIRE(length <= size); 56258945Sroberto 57258945Sroberto bitstring->magic = BITSTRING_MAGIC; 58258945Sroberto bitstring->data = data; 59258945Sroberto bitstring->length = length; 60258945Sroberto bitstring->size = size; 61258945Sroberto bitstring->lsb0 = lsb0; 62258945Sroberto} 63258945Sroberto 64258945Srobertovoid 65258945Srobertoisc_bitstring_invalidate(isc_bitstring_t *bitstring) { 66258945Sroberto 67258945Sroberto /* 68258945Sroberto * Invalidate 'bitstring'. 69258945Sroberto */ 70258945Sroberto 71258945Sroberto REQUIRE(VALID_BITSTRING(bitstring)); 72258945Sroberto 73258945Sroberto bitstring->magic = 0; 74258945Sroberto bitstring->data = NULL; 75258945Sroberto bitstring->length = 0; 76258945Sroberto bitstring->size = 0; 77258945Sroberto bitstring->lsb0 = ISC_FALSE; 78258945Sroberto} 79258945Sroberto 80258945Srobertovoid 81258945Srobertoisc_bitstring_copy(isc_bitstring_t *source, unsigned int sbitpos, 82258945Sroberto isc_bitstring_t *target, unsigned int tbitpos, 83258945Sroberto unsigned int n) 84258945Sroberto{ 85258945Sroberto unsigned int tlast; 86258945Sroberto 87258945Sroberto /* 88258945Sroberto * Starting at bit 'sbitpos', copy 'n' bits from 'source' to 89258945Sroberto * the 'n' bits of 'target' starting at 'tbitpos'. 90258945Sroberto */ 91258945Sroberto 92258945Sroberto REQUIRE(VALID_BITSTRING(source)); 93258945Sroberto REQUIRE(VALID_BITSTRING(target)); 94258945Sroberto REQUIRE(source->lsb0 == target->lsb0); 95258945Sroberto if (source->lsb0) { 96258945Sroberto REQUIRE(sbitpos <= source->length); 97258945Sroberto sbitpos = PADDED(source->size) - sbitpos; 98258945Sroberto REQUIRE(sbitpos >= n); 99258945Sroberto sbitpos -= n; 100258945Sroberto } else 101258945Sroberto REQUIRE(sbitpos + n <= source->length); 102258945Sroberto tlast = tbitpos + n; 103258945Sroberto if (target->lsb0) { 104258945Sroberto REQUIRE(tbitpos <= target->length); 105258945Sroberto tbitpos = PADDED(target->size) - tbitpos; 106258945Sroberto REQUIRE(tbitpos >= n); 107258945Sroberto tbitpos -= n; 108258945Sroberto } else 109258945Sroberto REQUIRE(tlast <= target->size); 110258945Sroberto 111258945Sroberto if (tlast > target->length) 112258945Sroberto target->length = tlast; 113258945Sroberto 114258945Sroberto /* 115258945Sroberto * This is far from optimal... 116258945Sroberto */ 117258945Sroberto 118258945Sroberto while (n > 0) { 119258945Sroberto if (BITSET(source, sbitpos)) 120258945Sroberto SETBIT(target, tbitpos); 121258945Sroberto else 122258945Sroberto CLEARBIT(target, tbitpos); 123258945Sroberto sbitpos++; 124258945Sroberto tbitpos++; 125258945Sroberto n--; 126258945Sroberto } 127258945Sroberto} 128