1135446Strhodes/* 2193149Sdougb * Copyright (C) 2004, 2005, 2007 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1999-2001 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18234010Sdougb/* $Id: bitstring.c,v 1.17 2007/06/19 23:47:17 tbox Exp $ */ 19135446Strhodes 20170222Sdougb/*! \file */ 21170222Sdougb 22135446Strhodes#include <config.h> 23135446Strhodes 24135446Strhodes#include <stddef.h> 25135446Strhodes 26135446Strhodes#include <isc/magic.h> 27135446Strhodes#include <isc/bitstring.h> 28135446Strhodes#include <isc/util.h> 29135446Strhodes 30135446Strhodes#define DIV8(x) ((x) >> 3) 31135446Strhodes#define MOD8(x) ((x) & 0x00000007U) 32135446Strhodes#define OCTETS(n) (((n) + 7) >> 3) 33135446Strhodes#define PADDED(n) ((((n) + 7) >> 3) << 3) 34135446Strhodes#define BITSET(bs, n) (((bs)->data[DIV8(n)] & \ 35135446Strhodes (1 << (7 - MOD8(n)))) != 0) 36135446Strhodes#define SETBIT(bs, n) (bs)->data[DIV8(n)] |= (1 << (7 - MOD8(n))) 37135446Strhodes#define CLEARBIT(bs, n) (bs)->data[DIV8(n)] &= ~(1 << (7 - MOD8(n))) 38135446Strhodes 39135446Strhodes#define BITSTRING_MAGIC ISC_MAGIC('B', 'S', 't', 'r') 40135446Strhodes#define VALID_BITSTRING(b) ISC_MAGIC_VALID(b, BITSTRING_MAGIC) 41135446Strhodes 42135446Strhodesvoid 43135446Strhodesisc_bitstring_init(isc_bitstring_t *bitstring, unsigned char *data, 44135446Strhodes unsigned int length, unsigned int size, isc_boolean_t lsb0) 45135446Strhodes{ 46135446Strhodes /* 47135446Strhodes * Make 'bitstring' refer to the bitstring of 'size' bits starting 48135446Strhodes * at 'data'. 'length' bits of the bitstring are valid. If 'lsb0' 49135446Strhodes * is set then, bit 0 refers to the least significant bit of the 50135446Strhodes * bitstring. Otherwise bit 0 is the most significant bit. 51135446Strhodes */ 52135446Strhodes 53135446Strhodes REQUIRE(bitstring != NULL); 54135446Strhodes REQUIRE(data != NULL); 55135446Strhodes REQUIRE(length <= size); 56135446Strhodes 57135446Strhodes bitstring->magic = BITSTRING_MAGIC; 58135446Strhodes bitstring->data = data; 59135446Strhodes bitstring->length = length; 60135446Strhodes bitstring->size = size; 61135446Strhodes bitstring->lsb0 = lsb0; 62135446Strhodes} 63135446Strhodes 64135446Strhodesvoid 65135446Strhodesisc_bitstring_invalidate(isc_bitstring_t *bitstring) { 66135446Strhodes 67135446Strhodes /* 68135446Strhodes * Invalidate 'bitstring'. 69135446Strhodes */ 70135446Strhodes 71135446Strhodes REQUIRE(VALID_BITSTRING(bitstring)); 72135446Strhodes 73135446Strhodes bitstring->magic = 0; 74135446Strhodes bitstring->data = NULL; 75135446Strhodes bitstring->length = 0; 76135446Strhodes bitstring->size = 0; 77135446Strhodes bitstring->lsb0 = ISC_FALSE; 78135446Strhodes} 79135446Strhodes 80135446Strhodesvoid 81135446Strhodesisc_bitstring_copy(isc_bitstring_t *source, unsigned int sbitpos, 82135446Strhodes isc_bitstring_t *target, unsigned int tbitpos, 83135446Strhodes unsigned int n) 84135446Strhodes{ 85135446Strhodes unsigned int tlast; 86135446Strhodes 87135446Strhodes /* 88135446Strhodes * Starting at bit 'sbitpos', copy 'n' bits from 'source' to 89135446Strhodes * the 'n' bits of 'target' starting at 'tbitpos'. 90135446Strhodes */ 91135446Strhodes 92135446Strhodes REQUIRE(VALID_BITSTRING(source)); 93135446Strhodes REQUIRE(VALID_BITSTRING(target)); 94135446Strhodes REQUIRE(source->lsb0 == target->lsb0); 95135446Strhodes if (source->lsb0) { 96135446Strhodes REQUIRE(sbitpos <= source->length); 97135446Strhodes sbitpos = PADDED(source->size) - sbitpos; 98135446Strhodes REQUIRE(sbitpos >= n); 99135446Strhodes sbitpos -= n; 100135446Strhodes } else 101135446Strhodes REQUIRE(sbitpos + n <= source->length); 102135446Strhodes tlast = tbitpos + n; 103135446Strhodes if (target->lsb0) { 104135446Strhodes REQUIRE(tbitpos <= target->length); 105135446Strhodes tbitpos = PADDED(target->size) - tbitpos; 106135446Strhodes REQUIRE(tbitpos >= n); 107135446Strhodes tbitpos -= n; 108135446Strhodes } else 109135446Strhodes REQUIRE(tlast <= target->size); 110135446Strhodes 111135446Strhodes if (tlast > target->length) 112135446Strhodes target->length = tlast; 113135446Strhodes 114135446Strhodes /* 115135446Strhodes * This is far from optimal... 116135446Strhodes */ 117135446Strhodes 118135446Strhodes while (n > 0) { 119135446Strhodes if (BITSET(source, sbitpos)) 120135446Strhodes SETBIT(target, tbitpos); 121135446Strhodes else 122135446Strhodes CLEARBIT(target, tbitpos); 123135446Strhodes sbitpos++; 124135446Strhodes tbitpos++; 125135446Strhodes n--; 126135446Strhodes } 127135446Strhodes} 128