Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

bit_array.h

Go to the documentation of this file.
00001 /*
00002  * $Id: inputevt.h 10580 2006-03-14 22:58:17Z cbiere $
00003  *
00004  * Copyright (c) 2006, Christian Biere
00005  *
00006  *----------------------------------------------------------------------
00007  * This file is part of gtk-gnutella.
00008  *
00009  *  gtk-gnutella is free software; you can redistribute it and/or modify
00010  *  it under the terms of the GNU General Public License as published by
00011  *  the Free Software Foundation; either version 2 of the License, or
00012  *  (at your option) any later version.
00013  *
00014  *  gtk-gnutella is distributed in the hope that it will be useful,
00015  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  *  GNU General Public License for more details.
00018  *
00019  *  You should have received a copy of the GNU General Public License
00020  *  along with gtk-gnutella; if not, write to the Free Software
00021  *  Foundation, Inc.:
00022  *      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00023  *----------------------------------------------------------------------
00024  */
00025 
00037 #ifndef _bit_array_h_
00038 #define _bit_array_h_
00039 
00040 #include "common.h"
00041 
00042 /*
00043  * Functions for handling arrays of bits. On BSD systems, the macros from
00044  * <bitstring.h> could be used for better efficiency. So far, the following
00045  * implementation does not eliminate loop overhead by handling all bits
00046  * of a "guchar" at once where possible.
00047  */
00048 
00049 typedef unsigned long bit_array_t;
00050 
00051 #if LONG_MAX == 0x7fffffffL
00052 #if CHAR_BIT == 8
00053 #define BIT_ARRAY_BITSHIFT  (2 + 3)
00054 #elif CHAR_BIT == 16
00055 #define BIT_ARRAY_BITSHIFT  (2 + 4)
00056 #else
00057 #error "Unsupported size of char"
00058 #endif  /* CHAR_BIT */
00059 #elif (ULONG_MAX >> 31) > 0xffffffffUL
00060 #if CHAR_BIT == 8
00061 #define BIT_ARRAY_BITSHIFT  (3 + 3)
00062 #elif CHAR_BIT == 16
00063 #define BIT_ARRAY_BITSHIFT  (3 + 4)
00064 #else
00065 #error "Unsupported size of char"
00066 #endif  /* CHAR_BIT */
00067 #endif  /* LONG_MAX */
00068 
00069 #define BIT_ARRAY_BITSIZE (CHAR_BIT * sizeof(bit_array_t))
00070 #define BIT_ARRAY_BITMASK (BIT_ARRAY_BITSIZE - 1)
00071 #define BIT_ARRAY_WORD(base, i) base[(i) >> BIT_ARRAY_BITSHIFT]
00072 #define BIT_ARRAY_BIT(base, i) (1UL << ((i) & BIT_ARRAY_BITMASK)) 
00073 
00080 #define BIT_ARRAY_SIZE(n) \
00081     ((n) / (CHAR_BIT * sizeof(bit_array_t)) + \
00082      ((n) % (CHAR_BIT * sizeof(bit_array_t)) ? 1 : 0))
00083 
00091  #define BIT_ARRAY_BYTE_SIZE(n) (BIT_ARRAY_SIZE(n) * sizeof (bit_array_t))
00092 
00102 static inline bit_array_t *
00103 bit_array_realloc(bit_array_t *base, size_t n)
00104 {
00105     size_t size;
00106 
00107     STATIC_ASSERT(0 == (BIT_ARRAY_BITSIZE & BIT_ARRAY_BITMASK));
00108     
00109     size = BIT_ARRAY_BYTE_SIZE(n);
00110     return g_realloc(base, size);
00111 }
00112 
00113 
00118 static inline void
00119 bit_array_set(bit_array_t *base, size_t i)
00120 {
00121     BIT_ARRAY_WORD(base, i) |= BIT_ARRAY_BIT(base, i);
00122 }
00123 
00128 static inline void 
00129 bit_array_clear(bit_array_t *base, size_t i)
00130 {
00131     BIT_ARRAY_WORD(base, i) &= ~BIT_ARRAY_BIT(base, i);
00132 }
00133 
00140 static inline gboolean
00141 bit_array_flip(bit_array_t *base, size_t i)
00142 {
00143     return BIT_ARRAY_WORD(base, i) ^= BIT_ARRAY_BIT(base, i);
00144 }
00145 
00151 static inline gboolean
00152 bit_array_get(const bit_array_t *base, size_t i)
00153 {
00154     return 0 != (BIT_ARRAY_WORD(base, i) & BIT_ARRAY_BIT(base, i));
00155 }
00156 
00166 static inline void 
00167 bit_array_clear_range(bit_array_t *base, size_t from, size_t to)
00168 {
00169     size_t i;
00170     
00171     g_assert(from <= to);
00172 
00173     for (i = from; i <= to; /* NOTHING */) {
00174         if (0 == (i & BIT_ARRAY_BITMASK)) {
00175             size_t n = (to - i) >> BIT_ARRAY_BITSHIFT;
00176 
00177             if (n != 0) {
00178                 size_t j = i >> BIT_ARRAY_BITSHIFT;
00179 
00180                 i += n * BIT_ARRAY_BITSIZE;
00181                 do {
00182                     base[j++] = 0;
00183                 } while (--n != 0);
00184                 continue;
00185             }
00186         }
00187         bit_array_clear(base, i++);
00188     }
00189 }
00190 
00200 static inline void 
00201 bit_array_set_range(bit_array_t *base, size_t from, size_t to)
00202 {
00203     size_t i;
00204     
00205     g_assert(from <= to);
00206 
00207     for (i = from; i <= to; /* NOTHING */) {
00208         if (0 == (i & BIT_ARRAY_BITMASK)) {
00209             size_t n = (to - i) >> BIT_ARRAY_BITSHIFT;
00210 
00211             if (n != 0) {
00212                 size_t j = i >> BIT_ARRAY_BITSHIFT;
00213 
00214                 i += n * BIT_ARRAY_BITSIZE;
00215                 do {
00216                     base[j++] = (bit_array_t) -1;
00217                 } while (--n != 0);
00218                 continue;
00219             }
00220         }
00221         bit_array_set(base, i++);
00222     }
00223 }
00224 
00234 static inline size_t
00235 bit_array_first_clear(const bit_array_t *base, size_t from, size_t to)
00236 {
00237     size_t i;
00238 
00239     g_assert(from <= to);
00240 
00241     for (i = from; i <= to; i++) {
00242         if (!bit_array_get(base, i))
00243             return i;
00244     }
00245 
00246     for (i = from; i <= to; /* NOTHING */) {
00247         if (0 == (i & BIT_ARRAY_BITMASK)) {
00248             size_t n = (to - i) >> BIT_ARRAY_BITSHIFT;
00249 
00250             if (n != 0) {
00251                 size_t j = i >> BIT_ARRAY_BITSHIFT;
00252 
00253                 while (n-- > 0) {
00254                     if (base[j++] != (bit_array_t) -1) {
00255                         bit_array_t value = base[j - 1];
00256                         while (value & 0x1) {
00257                             value >>= 1;
00258                             i++;
00259                         }
00260                         return i;
00261                     }
00262                     i += BIT_ARRAY_BITSIZE;
00263                 }
00264             }
00265         }
00266         if (!bit_array_get(base, i))
00267             return i;
00268         i++;
00269     }
00270 
00271     return (size_t) -1;
00272 }
00273 
00274 #undef BIT_ARRAY_BIT
00275 #undef BIT_ARRAY_BITSIZE
00276 #undef BIT_ARRAY_BITMASK
00277 #undef BIT_ARRAY_BITSHIFT
00278 #undef BIT_ARRAY_WORD
00279 
00280 #endif /* _bit_array_h_ */
00281 /* vi: set ts=4 sw=4 cindent: */

Generated on Sat Jun 30 17:53:22 2007 for gtk-gnutella by  doxygen 1.3.9.1