Menu

BitArray.h

Go to the documentation of this file.
00001 /*******************************************************************************
00002  *
00003  * Copyright (c) 2010 Philipp Werner <philipp.werner@st.ovgu.de>
00004  * All rights reserved.
00005  *
00006  *    Redistribution and use in source and binary forms, with or without
00007  *    modification, are permitted provided that the following conditions
00008  *    are met:
00009  *
00010  *    * Redistributions of source code must retain the above copyright
00011  *      notice, this list of conditions and the following disclaimer.
00012  *
00013  *    * Redistributions in binary form must reproduce the above copyright
00014  *      notice, this list of conditions and the following disclaimer in
00015  *      the documentation and/or other materials provided with the
00016  *      distribution.
00017  *
00018  *    * Neither the name of the copyright holders nor the names of
00019  *      contributors may be used to endorse or promote products derived
00020  *      from this software without specific prior written permission.
00021  *
00022  *
00023  *    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
00024  *    IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
00025  *    TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00026  *    PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
00027  *    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00028  *    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
00029  *    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00030  *    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00031  *    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00032  *    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00033  *    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00034  *
00035  *
00036  * $Id$
00037  *
00038  ******************************************************************************/
00039 
00040 #ifndef __BITARRAY_H_21D62F9B61AF9F__
00041 #define __BITARRAY_H_21D62F9B61AF9F__
00042 
00043 #include <stdint.h>
00044 #include <string.h>
00045 #include "mw/afp/shared/div_round_up.h"
00046 #include "object/Allocator.h"
00047 #include "mw/afp/Config.h"
00048 
00049 namespace famouso {
00050     namespace mw {
00051         namespace afp {
00052             namespace defrag {
00053                 namespace detail {
00054 
00059                     class Bit {
00060                             uint8_t & byte;
00061                             uint8_t mask;
00062                         public:
00063 
00069                             Bit(uint8_t & byte, uint8_t mask) :
00070                                     byte(byte), mask(mask) {
00071                             }
00072 
00074                             void set() {
00075                                 byte |= mask;
00076                             }
00077 
00079                             void clear() {
00080                                 byte &= ~mask;
00081                             }
00082 
00084                             bool get() const {
00085                                 return byte & mask;
00086                             }
00087 
00089                             bool value() const {
00090                                 return get();
00091                             }
00092 
00094                             Bit & operator=(bool value) {
00095                                 if (value)
00096                                     set();
00097                                 else
00098                                     clear();
00099                                 return *this;
00100                             }
00101                     };
00102 
00103 
00104                     /*
00105                      *  \brief  BitArray of constant length
00106                      *  \tparam N   Number of bits (> 0)
00107                      *  \tparam Allocator   unused
00108                      */
00109                     template <size_t N, class Allocator = object::Allocator>
00110                     class BitArray {
00111                             enum { array_length = (N - 1) / 8 + 1 };
00112                             uint8_t array[array_length];
00113                         public:
00114 
00121                             BitArray(bool init_value = false) {
00122                                 memset(array, init_value ? 0xff : 0, array_length);
00123                             }
00124 
00131                             Bit operator[](size_t bit_idx) {
00132                                 FAMOUSO_ASSERT(bit_idx < N);
00133                                 return Bit(array[bit_idx / 8], 1 << (bit_idx % 8));
00134                             }
00135 
00142                             const Bit operator[](size_t bit_idx) const {
00143                                 return (*const_cast<BitArray *>(this))[bit_idx];
00144                             }
00145 
00147                             size_t size() const {
00148                                 return N;
00149                             }
00150 
00155                             bool resize(size_t count) {
00156                                 return false;
00157                             }
00158                     };
00159 
00160                     /*
00161                      *  \brief  BitArray with dynamic length
00162                      *  \tparam Allocator   Allocator to use for array
00163                      */
00164                     template <class Allocator>
00165                     class BitArray<afp::dynamic, Allocator> {
00166                             size_t bit_count;
00167                             uint8_t * array;
00168                             bool init_value;
00169                         public:
00170 
00180                             BitArray(bool init_value = false) :
00181                                     bit_count(0), array(0), init_value(init_value) {
00182                             }
00183 
00190                             Bit operator[](size_t bit_idx) {
00191                                 FAMOUSO_ASSERT(bit_idx < bit_count);
00192                                 return Bit(array[bit_idx / 8], 1 << (bit_idx % 8));
00193                             }
00194 
00201                             const Bit operator[](size_t bit_idx) const {
00202                                 return (*const_cast<BitArray *>(this))[bit_idx];
00203                             }
00204 
00206                             size_t size() const {
00207                                 return bit_count;
00208                             }
00209 
00215                             bool resize(size_t new_bit_count) {
00216                                 size_t old_len = shared::div_round_up(bit_count, 8);
00217                                 size_t new_len = shared::div_round_up(new_bit_count, 8);
00218 
00219                                 uint8_t * new_el = Allocator::alloc(new_len);
00220                                 if (!new_el)
00221                                     return false;
00222 
00223                                 uint8_t init_byte = init_value ? 0xff : 0;
00224                                 if (array) {
00225                                     if (new_len > old_len) {
00226                                         memcpy(new_el, array, old_len);
00227                                         memset(new_el + old_len, init_byte, new_len - old_len);
00228                                     } else {
00229                                         memcpy(new_el, array, new_len);
00230                                         uint8_t last_byte_mask = new_bit_count % 8;
00231                                         if (last_byte_mask) {
00232                                             last_byte_mask = 0xff << (last_byte_mask);
00233                                             new_el[new_len-1] = (new_el[new_len-1] & ~last_byte_mask) | (init_byte & last_byte_mask);
00234                                         }
00235                                     }
00236                                     Allocator::free(array);
00237                                 } else {
00238                                     memset(new_el, init_byte, new_len);
00239                                 }
00240 
00241                                 array = new_el;
00242                                 bit_count = new_bit_count;
00243 
00244                                 return true;
00245                             }
00246                     };
00247 
00248 
00249                 } // namespace detail
00250             } // namespace defrag
00251         } // namespace afp
00252     } // namespace mw
00253 } // namespace famouso
00254 
00255 
00256 #endif // __BITARRAY_H_21D62F9B61AF9F__
00257