00001 /* 00002 00003 The BLAH library, a container library 00004 Copyright (C) 1997-2004 The CDG Team <cdg@nats.informatik.uni-hamburg.de> 00005 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 2 of the License, or 00009 (at your option) any later version. 00010 00011 This program is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program; if not, write to the Free Software 00018 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00019 00020 Contact: blah@nats.informatik.uni-hamburg.de 00021 00022 $Id: bitvector.c,v 1.5 2004/02/19 15:27:35 engelman Exp $ 00023 00024 */ 00025 00026 /* ---------------------------------------------------------------------- 00027 * @defgroup ByteVector ByteVectors 00028 * Implementation of a vector of bits. 00029 * 00030 * A bitvector is a special case of a vector which is more memory efficient than 00031 * a generic vector and more time efficient than a bitstring. 00032 * @{ 00033 */ 00034 00035 /* ---INCLUDES-------------------------------------------------------- */ 00036 #include <stdio.h> 00037 #include <string.h> 00038 #include "blah.h" 00039 00040 /* ------------------------------------------------------------------- */ 00041 #define RESIZEFACTOR 2 00042 00043 /* -- TYPE DEFINITIONS ----------------------------------------------- */ 00044 /* ---------------------------------------------------------------------- 00045 * internal representation of a bit vector 00046 */ 00047 struct ByteVectorStruct 00048 { 00049 #ifdef BITVECTOR_DEBUG 00050 int magic; /**< identification string */ 00051 #endif 00052 int count; /**< number of entries */ 00053 int capacity; /**< capacity of table */ 00054 char *entries; /**< table of entries */ 00055 }; 00056 00057 /* -- VARIABLES ------------------------------------------------------ */ 00058 /* ------------------------------------------------------------------- */ 00059 #ifdef BITVECTOR_DEBUG 00060 static int magic_constant=8755156; 00061 #endif 00062 00063 /* -- FUNCTIONS ------------------------------------------------------ */ 00064 #ifdef BITVECTOR_DEBUG 00065 static void check_magic_function(ByteVector v, char *file, int no) 00066 { 00067 if (!v) 00068 { 00069 fprintf(stderr, "%s:%d: ByteVector must not be NULL\n", file, no); 00070 abort(); 00071 } 00072 if (v->magic!=magic_constant) 00073 { 00074 fprintf(stderr, "%s:%d: not a ByteVector\n", file, no); 00075 abort(); 00076 } 00077 } 00078 #define check_magic(v) check_magic_function(v, __FILE__, __LINE__) 00079 #else /* #ifdef BITVECTOR_DEBUG */ 00080 #define check_magic(v) 00081 #endif /* #ifdef BITVECTOR_DEBUG */ 00082 00083 /* ---------------------------------------------------------------------- 00084 * doubles capacity of ByteVector. 00085 * 00086 * @param v the bitvector that has to be resized. 00087 * @returns the bitvector after increasing its capacity. 00088 */ 00089 static void resize(ByteVector v) 00090 { 00091 check_magic(v); 00092 00093 v->capacity=(int)(RESIZEFACTOR*v->capacity); 00094 v->entries=(char *)memRealloc(v->entries, sizeof(char)*v->capacity); 00095 memset(&v->entries[v->count], 0, (v->capacity-v->count)*sizeof(char)); 00096 } 00097 00098 /* ---------------------------------------------------------------------- 00099 * creates a new empty bitvector with an initial capacity. 00100 * 00101 * Specifying a correct or nearly correct capacity slightly improves the 00102 * efficiency. The bitvector roughly needs capacity bytes. 00103 * 00104 * @param capacity the capacity of the new vector to be created. 00105 * @returns a new and empty bit vector of the specified capacity. 00106 */ 00107 ByteVector bvNew(int capacity) 00108 { 00109 ByteVector v; 00110 00111 if (capacity<8) { capacity=8; } 00112 v=(ByteVector)memMalloc(sizeof(ByteVectorStruct)); 00113 #ifdef BITVECTOR_DEBUG 00114 v->magic=magic_constant; 00115 #endif 00116 v->count=0; 00117 v->capacity=capacity; 00118 v->entries=(char *)memMalloc(sizeof(char)*capacity); 00119 00120 memset(v->entries, 0, capacity*sizeof(char)); 00121 00122 return(v); 00123 } 00124 00125 /* ---------------------------------------------------------------------- 00126 * deletes a bitvector and frees the associated memory. 00127 * 00128 * note that nothing user-defined is stored in a bitvector. 00129 * therefore, the user does not need to free anything himself. 00130 * 00131 * @param v the bitvector that has to be deleted. 00132 */ 00133 void bvDelete(ByteVector v) 00134 { 00135 check_magic(s); 00136 00137 memFree(v->entries); 00138 memFree(v); 00139 } 00140 00141 /* ---------------------------------------------------------------------- 00142 * adds a new element to the end of the ByteVector. 00143 * 00144 * automatically increases the capacity of the ByteVector if necessary 00145 * 00146 * @param v the vector to which the new element has to be added. 00147 * @param element the element that has to be added to the end of the bitvector v 00148 * @returns index of the vector 00149 */ 00150 int bvAddElement(ByteVector v, char element) 00151 { 00152 check_magic(v); 00153 00154 /* The number of entries exceeds the capacity. Resize the table. */ 00155 while (v->count>=v->capacity) { resize(v); } 00156 00157 v->entries[v->count]=element; 00158 return v->count++; 00159 } 00160 00161 /* ---------------------------------------------------------------------- 00162 * sets the element at the specific index to a new element. 00163 * 00164 * if necessary the bitVector automatically increases its capacity. 00165 * 00166 * @param v the bitvector in which the specified element has to be set to a new element. 00167 * @param index the index of the element that has to be set. 00168 * @returns the old element or \a False at the specified index. 00169 */ 00170 char bvElement(ByteVector v, int index) 00171 { 00172 check_magic(v); 00173 00174 if (index>=0 && index<v->count) { return v->entries[index]; } 00175 00176 fprintf(stderr, "ERROR: bvElement: index %d out of range\n", index); 00177 abort(); 00178 } 00179 00180 /* ---------------------------------------------------------------------- 00181 * removes element at the specified index. 00182 * 00183 * size decreases and all later elements move one position to the front. 00184 * inefficient method, not recommended. 00185 * 00186 * @param v the bitvector from which the element has to be removed. 00187 * @param index the index at which the element to be removed is present. 00188 * @returns old element at the specifed index. 00189 */ 00190 char bvRemoveElement(ByteVector v, int index) 00191 { 00192 char p; 00193 00194 check_magic(v); 00195 00196 if (index<0 || index>=v->count) 00197 { 00198 fprintf(stderr, 00199 "ERROR: bvRemoveElement: index %d out of range\n", 00200 index); 00201 abort(); 00202 } 00203 00204 p=v->entries[index]; 00205 /* TODO: check boundaries */ 00206 if (v->count-index>1) 00207 { 00208 memmove(&v->entries[index], 00209 &v->entries[index+1], 00210 (v->count-index)*sizeof(char)); 00211 } 00212 v->count--; 00213 return p; 00214 } 00215 00216 /* ---------------------------------------------------------------------- 00217 * inserts a new element at the given index. 00218 * 00219 * if necessary the bitvector automatically increases its capacity. 00220 * inefficient method,not recommended. 00221 * 00222 * @param v the bitvector into which the new element has to be inserted. 00223 * @param element the new element that has to be inserted into the bitvector v. 00224 * @param index the index at which the new element has to be inserted in the bitvector v. 00225 * @returns the old element at the index. 00226 */ 00227 char bvInsertElement(ByteVector v, char element, int index) 00228 { 00229 char p; 00230 00231 check_magic(v); 00232 00233 if (index<0) 00234 { 00235 fprintf(stderr, 00236 "ERROR: bvInsertElement: index %d out of range\n", 00237 index); 00238 abort(); 00239 } 00240 00241 /* 00242 * v->capacity==index is too small because index is counted 00243 * from zero. 00244 */ 00245 while (v->capacity<=index) { resize(v); } 00246 00247 /* 00248 * if v->count==v->capacity then the vector is 00249 * completely full; v->count>v->capacity shouldn't be possible. 00250 */ 00251 if (v->count>=v->capacity) { resize(v); } 00252 00253 if (v->count-index>0) 00254 { 00255 memmove(&v->entries[index+1], 00256 &v->entries[index], 00257 (v->count-index)*sizeof(char)); 00258 } 00259 00260 p=v->entries[index]; 00261 v->entries[index]=element; 00262 v->count=max(v->count+1, index+1); 00263 00264 return p; 00265 } 00266 00267 /* ---------------------------------------------------------------------- 00268 * sets element at the given index. 00269 * 00270 * if necessary the vector automatically increases its capacity. 00271 * 00272 * @param v the vector in which the element has to be set at the apecified index. 00273 * @param element the element that has to be set in the bitvector. 00274 * @param index the index at which the element to be set is present. 00275 * @returns The old element at the index. 00276 */ 00277 char bvSetElement(ByteVector v, char element, int index) 00278 { 00279 char p; 00280 00281 check_magic(v); 00282 00283 if (index<0) 00284 { 00285 fprintf(stderr, 00286 "ERROR: bvSetElement: index %d out of range\n", 00287 index); 00288 abort(); 00289 } 00290 00291 /* TODO: check boundaries */ 00292 while (v->capacity<=index) { resize(v); } 00293 00294 p=v->entries[index]; 00295 v->entries[index]=element; 00296 v->count=max(v->count, index+1); 00297 return p; 00298 } 00299 00300 /* ---------------------------------------------------------------------- 00301 * computes AND to the element at the given index. 00302 * 00303 * if necessary the vector automatically increases its capacity. 00304 * 00305 * @param v the vector in which the element has to be set at the apecified index. 00306 * @param element the element that has to be set in the bitvector. 00307 * @param index the index at which the element to be set is present. 00308 * @returns The new value at the index. 00309 */ 00310 char bvAndElement(ByteVector v, char element, int index) 00311 { 00312 check_magic(v); 00313 00314 if (index < 0) { 00315 fprintf(stderr, "ERROR: bvSetElement: index %d out of range\n", index); 00316 abort(); 00317 } 00318 00319 /* TODO: check boundaries */ 00320 while (v->capacity <= index) { 00321 resize(v); 00322 } 00323 00324 return (v->entries[index] &= element); 00325 } 00326 00327 /* ---------------------------------------------------------------------- 00328 * computes OR to the element at the given index. 00329 * 00330 * if necessary the vector automatically increases its capacity. 00331 * 00332 * @param v the vector in which the element has to be set at the apecified index. 00333 * @param element the element that has to be set in the bitvector. 00334 * @param index the index at which the element to be set is present. 00335 * @returns The new value at the index. 00336 */ 00337 char bvOrElement(ByteVector v, char element, int index) 00338 { 00339 check_magic(v); 00340 00341 if (index < 0) { 00342 fprintf(stderr, "ERROR: bvSetElement: index %d out of range\n", index); 00343 abort(); 00344 } 00345 00346 /* TODO: check boundaries */ 00347 while (v->capacity <= index) { 00348 resize(v); 00349 } 00350 00351 return (v->entries[index] |= element); 00352 } 00353 00354 /* ---------------------------------------------------------------------- 00355 * computes NOT to the element at the given index. 00356 * 00357 * if necessary the vector automatically increases its capacity. 00358 * 00359 * @param v the vector in which the element has to be set at the apecified index. 00360 * @param index the index at which the element to be set is present. 00361 * @returns The new value at the index. 00362 */ 00363 char bvNotElement(ByteVector v, int index) 00364 { 00365 check_magic(v); 00366 00367 if (index < 0) { 00368 fprintf(stderr, "ERROR: bvSetElement: index %d out of range\n", index); 00369 abort(); 00370 } 00371 00372 /* TODO: check boundaries */ 00373 while (v->capacity <= index) { 00374 resize(v); 00375 } 00376 00377 return (v->entries[index] = ~v->entries[index]); 00378 } 00379 00380 /* ---------------------------------------------------------------------- 00381 * sets all the elements between index \a from and \a to (excluding to) to a new value. 00382 * 00383 * if necesaary the bit vector automatically increases in capacity. 00384 * 00385 * @param v the bitvector in which the elements have to be set. 00386 * @param element the value of the bits at the corresponding indices. 00387 * @param from the source index from which all the elements in the bitvector have to be set. 00388 * @param to the destination index until which all the elements in the bitvector have to be set. 00389 * @returns the bitvector v after setting all the elements at the specified indices. 00390 * 00391 */ 00392 void bvSetElements(ByteVector v, char element, int from, int to) 00393 { 00394 check_magic(v); 00395 00396 if (from<0 || to<0) 00397 { 00398 fprintf(stderr, 00399 "ERROR: bvSetElement: index %d out of range\n", 00400 from<0 ? from : to); 00401 abort(); 00402 } 00403 00404 if (from>to) { int tmp=from; from=to; to=tmp; } 00405 00406 /* TODO: check boundaries */ 00407 /* to is excluded, so v->capacity==to is enough */ 00408 while (v->capacity<to) { resize(v); } 00409 00410 memset(&v->entries[from], element, (to-from)*sizeof(char)); 00411 v->count=max(v->count, to); 00412 } 00413 00414 /* ---------------------------------------------------------------------- 00415 * sets all the elements to a new value. 00416 * 00417 * the size increases to the current capacity of the bit vector. 00418 * 00419 * @param v the bitvector in which all the elements have to be set. 00420 * @param element the elements at the specified indices. 00421 * 00422 * @returns the bitvector after setting all the elements. 00423 */ 00424 void bvSetAllElements(ByteVector v, char element) 00425 { 00426 memset(v->entries, element, v->capacity*sizeof(char)); 00427 v->count=v->capacity; 00428 } 00429 00430 /* ---------------------------------------------------------------------- 00431 * finds the current capacity of bitvector. 00432 * 00433 * @param v the bitvector whose capacity has to be retrieved. 00434 * @returns the capacity of the bitvector v. 00435 */ 00436 int bvCapacity(ByteVector v) 00437 { 00438 check_magic(v); 00439 00440 return v->capacity; 00441 } 00442 00443 /* ---------------------------------------------------------------------- 00444 * finds the number of entries(size) in the bitvector. 00445 * 00446 * @param v the bitvector whose size has to be retrieved. 00447 * @returns the size of the bitvector v. 00448 */ 00449 int bvSize(ByteVector v) 00450 { 00451 check_magic(v); 00452 00453 return v->count; 00454 } 00455 00456 /* ---------------------------------------------------------------------- 00457 * finds if the bit vector is empty or not. 00458 * 00459 * @param v the bitvector for which emptiness is checked. 00460 * @returns \a TRUE if bitvector is empty and \a FALSE otherwise. 00461 */ 00462 char bvIsEmpty(ByteVector v) 00463 { 00464 check_magic(v); 00465 00466 return v->count==0 ? TRUE : FALSE; 00467 } 00468 00469 /* ---------------------------------------------------------------------- 00470 * creates an exact copy of the specified bitvector. 00471 * 00472 * @param v the bitvector for which cloning has to be performed. 00473 * @returns a complete independent \a CLONE of the bit vector v. 00474 */ 00475 ByteVector bvClone(ByteVector v) 00476 { 00477 ByteVector new; 00478 00479 check_magic(v); 00480 00481 new=bvNew(bvCapacity(v)); 00482 bvCopy(new, v); 00483 return new; 00484 } 00485 00486 /* ---------------------------------------------------------------------- 00487 * 00488 * copies entries of one bitvector to another. 00489 * 00490 * copying is done from bitVector \a src to the bitvector \a dst. 00491 * \a dst vector automatically increases its capacity. 00492 * @param src source index or the index from which copying has to be initiated. 00493 * @param dst destination index or the index until which the copying has to be done. 00494 * @returns the new \a dst vector with the elements copied into it. 00495 */ 00496 ByteVector bvCopy(ByteVector dst, ByteVector src) 00497 { 00498 if (dst->capacity<src->capacity) 00499 { 00500 dst->entries=(char *)memRealloc(dst->entries, sizeof(char)*src->capacity); 00501 } 00502 00503 memcpy(dst->entries, src->entries, sizeof(char)*src->capacity); 00504 00505 dst->count=src->count; 00506 dst->capacity=src->capacity; 00507 00508 return dst; 00509 } 00510 00511 /* ---------------------------------------------------------------------- */ 00512 /* ---------------------------------------------------------------------- */ 00513 /** @} */