Commit 3e6b7f2b authored by unknown's avatar unknown
Browse files

Merge mronstrom@bk-internal.mysql.com:/home/bk/mysql-5.1

into mysql.com:/Users/mikron/wl1682


sql/field.cc:
  Auto merged
sql/field.h:
  Auto merged
sql/ha_innodb.cc:
  Auto merged
sql/ha_innodb.h:
  Auto merged
sql/ha_ndbcluster.cc:
  Auto merged
sql/ha_ndbcluster.h:
  Auto merged
sql/handler.cc:
  Auto merged
sql/handler.h:
  Auto merged
sql/item.cc:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/opt_range.cc:
  Auto merged
sql/sql_acl.cc:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_bitmap.h:
  Auto merged
sql/sql_class.h:
  Auto merged
sql/sql_insert.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_table.cc:
  Auto merged
sql/sql_update.cc:
  Auto merged
sql/table.cc:
  Auto merged
sql/unireg.cc:
  Auto merged
parents 0de78e66 5985904e
Loading
Loading
Loading
Loading
+44 −11
Original line number Diff line number Diff line
@@ -21,10 +21,13 @@

#define MY_BIT_NONE (~(uint) 0)


typedef struct st_bitmap
{
  uchar *bitmap;
  uint bitmap_size; /* number of bytes occupied by the above */
  uint bitmap_size; /* number of bits occupied by the above */
  uint32 last_word_mask;
  uint32 *last_word_ptr;
  /*
     mutex will be acquired for the duration of each bitmap operation if
     thread_safe flag in bitmap_init was set.  Otherwise, we optimize by not
@@ -38,30 +41,60 @@ typedef struct st_bitmap
#ifdef	__cplusplus
extern "C" {
#endif
extern my_bool bitmap_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2);
extern my_bool bitmap_init(MY_BITMAP *map, uchar *buf, uint bitmap_size, my_bool thread_safe);
extern my_bool bitmap_is_clear_all(const MY_BITMAP *map);
extern my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size);
extern my_bool bitmap_is_set(const MY_BITMAP *map, uint bitmap_bit);
extern my_bool bitmap_is_set_all(const MY_BITMAP *map);
extern my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2);
extern uint bitmap_set_next(MY_BITMAP *map);
extern uint bitmap_get_first(const MY_BITMAP *map);
extern uint bitmap_get_first_set(const MY_BITMAP *map);
extern uint bitmap_bits_set(const MY_BITMAP *map);
extern void bitmap_clear_all(MY_BITMAP *map);
extern void bitmap_clear_bit(MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_free(MY_BITMAP *map);
extern void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2);
extern void bitmap_set_all(MY_BITMAP *map);
extern void bitmap_set_bit(MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size);
extern void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2);
extern void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2);
extern void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2);

extern uint bitmap_lock_set_next(MY_BITMAP *map);
extern void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit);
#ifdef NOT_USED
extern uint bitmap_lock_bits_set(const MY_BITMAP *map);
extern my_bool bitmap_lock_is_set_all(const MY_BITMAP *map);
extern uint bitmap_lock_get_first(const MY_BITMAP *map);
extern uint bitmap_lock_get_first_set(const MY_BITMAP *map);
extern my_bool bitmap_lock_is_subset(const MY_BITMAP *map1,
                                     const MY_BITMAP *map2);
extern my_bool bitmap_lock_is_prefix(const MY_BITMAP *map, uint prefix_size);
extern my_bool bitmap_lock_is_set(const MY_BITMAP *map, uint bitmap_bit);
extern my_bool bitmap_lock_is_clear_all(const MY_BITMAP *map);
extern my_bool bitmap_lock_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2);
extern void bitmap_lock_set_all(MY_BITMAP *map);
extern void bitmap_lock_clear_all(MY_BITMAP *map);
extern void bitmap_lock_set_bit(MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_lock_flip_bit(MY_BITMAP *map, uint bitmap_bit);
extern void bitmap_lock_set_prefix(MY_BITMAP *map, uint prefix_size);
extern void bitmap_lock_intersect(MY_BITMAP *map, const MY_BITMAP *map2);
extern void bitmap_lock_subtract(MY_BITMAP *map, const MY_BITMAP *map2);
extern void bitmap_lock_union(MY_BITMAP *map, const MY_BITMAP *map2);
extern void bitmap_lock_xor(MY_BITMAP *map, const MY_BITMAP *map2);
extern void bitmap_lock_invert(MY_BITMAP *map);
#endif
/* Fast, not thread safe, bitmap functions */
#define bitmap_fast_set_bit(MAP, BIT) (MAP)->bitmap[(BIT) / 8] |= (1 << ((BIT) & 7))
#define bitmap_fast_clear_bit(MAP, BIT) (MAP)->bitmap[(BIT) / 8] &= ~ (1 << ((BIT) & 7))
#define bitmap_fast_is_set(MAP, BIT) (MAP)->bitmap[(BIT) / 8] & (1 << ((BIT) & 7))
#define no_bytes_in_map(map) ((map->bitmap_size + 7)/8)
#define no_words_in_map(map) ((map->bitmap_size + 31)/32)
#define bytes_word_aligned(bytes) (4*((bytes + 3)/4))
#define bitmap_set_bit(MAP, BIT) ((MAP)->bitmap[(BIT) / 8] |= (1 << ((BIT) & 7)))
#define bitmap_flip_bit(MAP, BIT) ((MAP)->bitmap[(BIT) / 8] ^= (1 << ((BIT) & 7)))
#define bitmap_clear_bit(MAP, BIT) ((MAP)->bitmap[(BIT) / 8] &= ~ (1 << ((BIT) & 7)))
#define bitmap_is_set(MAP, BIT) ((MAP)->bitmap[(BIT) / 8] & (1 << ((BIT) & 7)))
#define bitmap_cmp(MAP1, MAP2) \
  (memcmp((MAP1)->bitmap, (MAP2)->bitmap, 4*no_words_in_map((MAP1)))==0)
#define bitmap_clear_all(MAP) \
  memset((MAP)->bitmap, 0, 4*no_words_in_map((MAP))); \
  *(MAP)->last_word_ptr|= (MAP)->last_word_mask
#define bitmap_set_all(MAP) \
  (memset((MAP)->bitmap, 0xFF, 4*no_words_in_map((MAP))))

#ifdef	__cplusplus
}
+764 −167

File changed.

Preview size limit exceeded, changes collapsed.

+1 −0
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
			sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
			slave.cc sql_repl.cc rpl_filter.cc \
                        sql_union.cc sql_derived.cc \
                        bitvector.cc \
			client.c sql_client.cc mini_client_errors.c pack.c\
			stacktrace.c repl_failsafe.h repl_failsafe.cc \
			sql_olap.cc sql_view.cc \

sql/bitvector.cc

0 → 100644
+347 −0
Original line number Diff line number Diff line
/* -*- Mode: C++ -*-

   Copyright (C) 2005 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include "mysql_priv.h"
#include <bitvector.h>

void bitvector::create_last_word_mask()
{

  /* Get the number of used bits (1..8) in the last byte */
  unsigned int const used= 1U + ((size()-1U) & 0x7U);

  /*
   * Create a mask with the upper 'unused' bits set and the lower 'used'
   * bits clear. The bits within each byte is stored in big-endian order.
   */
  unsigned char const mask= (~((1 << used) - 1)) & 255;
  unsigned int byte_no= ((bytes()-1)) & ~3U;
  last_word_ptr= (uint32*)&m_data[byte_no];

  /*
    The first bytes are to be set to zero since they represent real  bits
    in the bitvector. The last bytes are set to 0xFF since they  represent
    bytes not used by the bitvector. Finally the last byte contains  bits
    as set by the mask above.
  */

  unsigned char *ptr= (unsigned char*)&last_word_mask;
  switch (bytes()&3)
  {
  case 1:
    last_word_mask= ~0U;
    ptr[0]= mask;
    return;
  case 2:
    last_word_mask= ~0U;
    ptr[0]= 0;
    ptr[1]= mask;
    return;
  case 3:
    last_word_mask= 0U;
    ptr[2]= mask;
    ptr[3]= 0xFFU;
    return;
  case 0:
    last_word_mask= 0U;
    ptr[3]= mask;
    return;
  }
}

int bitvector::init(size_t size)
{
  DBUG_ASSERT(size < MYSQL_NO_BIT_FOUND);
  DBUG_ASSERT(size > 0);
  m_size= size;
  m_data= (uchar*)sql_alloc(byte_size_word_aligned(size));
  if (m_data)
  {
    create_last_word_mask();
    clear_all();
    return FALSE;
  }
  return TRUE;
}

uint bitvector::no_bits_set()
{
  uint no_bytes= bytes(), res=0, i;
  uchar *ptr= m_data;
  *last_word_ptr^=last_word_mask; //Reset last bits to zero
  for (i=0; i< no_bytes; i++, ptr++)
    res+=my_count_bits_ushort(*ptr);
  *last_word_ptr^=last_word_mask; //Set last bits to one again
  return res;
}

uint bitvector::get_first_bit_set()
{
  uchar *byte_ptr;
  uint32 *data_ptr= (uint32*)data(), bit_found,i,j,k;
  for (i=0; data_ptr <= last_word_ptr; data_ptr++, i++)
  {
    if (*data_ptr)
    {
      byte_ptr= (uchar*)data_ptr;
      for (j=0; j < 4; j++, byte_ptr++)
      {
        if (*byte_ptr)
        {
          for (k=0; k < 8; k++)
          {
            if (*byte_ptr & (1 << k))
            {
              bit_found= (i << 5) + (j << 3) + k;
              if (bit_found == m_size)
                return MYSQL_NO_BIT_FOUND;
              else
                return bit_found;
            }
          }
          DBUG_ASSERT(1);
        }
      }
      DBUG_ASSERT(1);
    }
  }
  return MYSQL_NO_BIT_FOUND;
}

uint bitvector::get_first_bit_clear()
{
  uchar *byte_ptr;
  uint32 *data_ptr= (uint32*)data(), bit_found,i,j,k;
  for (i=0; data_ptr <= last_word_ptr; data_ptr++, i++)
  {
    if (*data_ptr != 0xFFFFFFFF)
    {
      byte_ptr= (uchar*)data_ptr;
      for (j=0; j < 4; j++, byte_ptr++)
      {
        if (*byte_ptr != 0xFF)
        {
          for (k=0; k < 8; k++)
          {
            if (!(*byte_ptr & (1 << k)))
            {
              bit_found= (i << 5) + (j << 3) + k;
              if (bit_found == m_size)
                return MYSQL_NO_BIT_FOUND;
              else
                return bit_found;
            }
          }
          DBUG_ASSERT(1);
        }
      }
      DBUG_ASSERT(1);
    }
  }
  return MYSQL_NO_BIT_FOUND;
}

#ifdef TEST_BITVECTOR
uint get_rand_bit(uint bitsize)
{
  return (rand() % bitsize);
}

bool test_set_get_clear_bit(bitvector *bv, uint bitsize)
{
  uint i, test_bit;
  uint no_loops= bitsize > 128 ? 128 : bitsize;
  for (i=0; i < no_loops; i++)
  {
    test_bit= get_rand_bit(bitsize);
    bv->set_bit(test_bit);
    if (!bv->get_bit(test_bit))
      goto error1;
    bv->clear_bit(test_bit);
    if (bv->get_bit(test_bit))
      goto error2;
  }
  return FALSE;
error1:
  printf("Error in set bit, bit %u, bitsize = %u", test_bit, bitsize);
  return TRUE;
error2:
  printf("Error in clear bit, bit %u, bitsize = %u", test_bit, bitsize);
  return TRUE;
}

bool test_flip_bit(bitvector *bv, uint bitsize)
{
  uint i, test_bit;
  uint no_loops= bitsize > 128 ? 128 : bitsize;
  for (i=0; i < no_loops; i++)
  {
    test_bit= get_rand_bit(bitsize);
    bv->flip_bit(test_bit);
    if (!bv->get_bit(test_bit))
      goto error1;
    bv->flip_bit(test_bit);
    if (bv->get_bit(test_bit))
      goto error2;
  }
  return FALSE;
error1:
  printf("Error in flip bit 1, bit %u, bitsize = %u", test_bit, bitsize);
  return TRUE;
error2:
  printf("Error in flip bit 2, bit %u, bitsize = %u", test_bit, bitsize);
  return TRUE;
}

bool test_operators(bitvector *bv, uint bitsize)
{
  return FALSE;
}

bool test_get_all_bits(bitvector *bv, uint bitsize)
{
  uint i;
  bv->set_all();
  if (!bv->get_all_bits_set())
    goto error1;
  bv->clear_all();
  if (!bv->get_all_bits_clear())
    goto error2;
  for (i=0; i<bitsize;i++)
    bv->set_bit(i);
  if (!bv->get_all_bits_set())
    goto error3;
  for (i=0; i<bitsize;i++)
    bv->clear_bit(i);
  if (!bv->get_all_bits_clear())
    goto error4;
  return FALSE;
error1:
  printf("Error in set_all, bitsize = %u", bitsize);
  return TRUE;
error2:
  printf("Error in clear_all, bitsize = %u", bitsize);
  return TRUE;
error3:
  printf("Error in bitwise set all, bitsize = %u", bitsize);
  return TRUE;
error4:
  printf("Error in bitwise clear all, bitsize = %u", bitsize);
  return TRUE;
}

bool test_compare_operators(bitvector *bv, uint bitsize)
{
  return FALSE;
}

bool test_count_bits_set(bitvector *bv, uint bitsize)
{
  uint i, bit_count=0, test_bit;
  uint no_loops= bitsize > 128 ? 128 : bitsize;
  for (i=0; i < no_loops; i++)
  {
    test_bit=get_rand_bit(bitsize);
    if (!bv->get_bit(test_bit))
    {
      bv->set_bit(test_bit);
      bit_count++;
    }
  }
  if (bit_count==0 && bitsize > 0)
    goto error1;
  if (bv->no_bits_set() != bit_count)
    goto error2;
  return FALSE;
error1:
  printf("No bits set  bitsize = %u", bitsize);
  return TRUE;
error2:
  printf("Wrong count of bits set, bitsize = %u", bitsize);
  return TRUE;
}

bool test_get_first_bit(bitvector *bv, uint bitsize)
{
  return FALSE;
}

bool test_get_next_bit(bitvector *bv, uint bitsize)
{
  return FALSE;
}

bool do_test(uint bitsize)
{
  bitvector *bv;
  bv = new bitvector;
  bv->init(bitsize);
  if (test_set_get_clear_bit(bv,bitsize))
    goto error;
  bv->clear_all();
  if (test_flip_bit(bv,bitsize))
    goto error;
  bv->clear_all();
  if (test_operators(bv,bitsize))
    goto error;
  bv->clear_all();
  if (test_get_all_bits(bv, bitsize))
    goto error;
  bv->clear_all();
  if (test_compare_operators(bv,bitsize))
    goto error;
  bv->clear_all();
  if (test_count_bits_set(bv,bitsize))
    goto error;
  bv->clear_all();
  if (test_get_first_bit(bv,bitsize))
    goto error;
  bv->clear_all();
  if (test_get_next_bit(bv,bitsize))
    goto error;
  delete bv;
  return FALSE;
error:
  delete bv;
  printf("\n");
  return TRUE;
}

int main()
{
  int i;
  for (i= 1; i < 4096; i++)
    if (do_test(i))
      return -1;
  printf("OK\n");
  return 0;
}
/*
Compile by using the below on a compiled clone

g++ -DHAVE_CONFIG_H -I. -I. -I.. -I../include -I../regex -I.  -I../include
-g -fno-omit-frame-pointer -fno-common -felide-constructors -fno-exceptions
-fno-rtti   -fno-implicit-templates -fno-exceptions -fno-rtti
-DUSE_MYSYS_NEW -DDEFINE_CXA_PURE_VIRTUAL -DHAVE_DARWIN_THREADS
-D_P1003_1B_VISIBLE -DTEST_BITVECTOR -DSIGNAL_WITH_VIO_CLOSE
-DSIGNALS_DONT_BREAK_READ -DIGNORE_SIGHUP_SIGQUIT  -o bitvector.o
-c bitvector.cc
g++ -o bitvector bitvector.o -L../mysys -lmysys -L../dbug -L../strings
-lmystrings -ldbug
*/
#endif
+127 −76
Original line number Diff line number Diff line
@@ -68,64 +68,28 @@ namespace
    inlining code.
*/

class bitvector
/* Number returned when no bit found */
#define MYSQL_NO_BIT_FOUND 1 << 20
class bitvector :public Sql_alloc
{
private:
  /* Helper classes */
  struct flip_bit_op
  { 
    void operator()(byte* p, byte m) { *p^= m; }
  };

  struct set_bit_op
  { 
    void operator()(byte* p, byte m) { *p|= m; }
  };

  struct clear_bit_op
  { 
    void operator()(byte* p, byte m) { *p&= ~m; }
  };

  struct test_bit_op
  { 
    bool operator()(byte* p, byte m) { return *p & m; }
  };

  /* Compute the number of bytes required to store 'bits' bits in an array. */
  static inline size_t byte_size(size_t bits)
  { 
    int const byte_bits = sizeof(byte) * CHAR_BIT;
    uint const byte_bits = sizeof(byte) * CHAR_BIT;
    return (bits + (byte_bits-1)) / byte_bits; 
  }

  /* Tidy the last byte (by clearing the unused bits) of the bitvector to make
   * comparison easy.  This code is assuming that we're working with 8-bit
   * bytes.
   */
  void tidy_last_byte()
  static inline size_t byte_size_word_aligned(size_t bits)
  {
    byte* const last_byte= m_data + bytes() - 1;

    /* Get the number of used bits (1..8) in the last byte */
    unsigned int const used= 1U + ((size()-1U) & 0x7U);

    /* Create a mask with the upper 'unused' bits clear and the lower 'used'
     * bits set. The bits within each byte is stored in big-endian order.
     */
    unsigned int const mask= ((1 << used) - 1);

    /* Mask the last byte */
    *last_byte&= mask;
    return ((bits + 31) >> 5) << 2;
  }

  template <class ReturnType, class Func>
  inline ReturnType apply_to_byte(size_t const pos, Func op) const
  void create_last_word_mask();

  inline void tidy_last_word()
  {
    /* Here I'm assuming that we're working with 8-bit bytes. */
    ptrdiff_t const byte_pos= pos >> 3;
    byte const mask= (1 << (pos & 0x7U));
    return op(&m_data[byte_pos], mask);
    *last_word_ptr|= last_word_mask;
  }

public:
@@ -135,8 +99,11 @@ class bitvector
  }

  explicit bitvector(size_t size, bool value= false) 
    : m_size(size), m_data(my_malloc(byte_size(size), MYF(0)))
    : m_size(size),
      m_data((uchar*)sql_alloc(byte_size_word_aligned(size)))
  {
    DBUG_ASSERT(size < MYSQL_NO_BIT_FOUND);
    create_last_word_mask();
    if (value)
      set_all();
    else
@@ -147,43 +114,76 @@ class bitvector
   * number of *bits* in the bitvector. 
   */
  explicit bitvector(byte const* data, size_t size)
    : m_size(size), m_data(my_malloc(byte_size(size), MYF(0)))
    : m_size(size),
      m_data((uchar*)sql_alloc(byte_size_word_aligned(size)))
  {
    /* std::copy(data, data + byte_size(size), m_data); */
    DBUG_ASSERT(size < MYSQL_NO_BIT_FOUND);
    create_last_word_mask();
    memcpy(m_data, data, byte_size(size));
    tidy_last_byte();
    tidy_last_word();
  }

  bitvector(bitvector const& other) 
    : m_size(other.size()), m_data(my_malloc(other.bytes(), MYF(0)))
    : m_size(other.size()),
      m_data((uchar*)sql_alloc(other.bytes()))
  {
    /* std::copy(other.m_data, other.m_data + other.bytes(), m_data); */
    DBUG_ASSERT(m_size < MYSQL_NO_BIT_FOUND);
    create_last_word_mask();
    memcpy(m_data, other.data(), other.bytes());
    tidy_last_byte();           /* Just a precaution */
    tidy_last_word();
  }

  /* Assignment operator */
  bitvector& operator=(bitvector other)
  ~bitvector() {}

  /*
    Allocate memory to the bitvector and create last word mask
    and clear all bits in the bitvector.
  */
  int init(size_t size);

  /* Get number of bits set in the bitvector */
  uint no_bits_set();
  /* Get first bit set/clear in bitvector */
  uint get_first_bit_set();
  uint get_first_bit_clear();
  

  /* Swap the guts of this instance with another instance. */
  void swap(bitvector& other)
  {
    swap(other);
    my_swap(m_size, other.m_size);
    my_swap(m_data, other.m_data);
  }

  bitvector &operator=(const bitvector &rhs)
  {
    DBUG_ASSERT(rhs.size() == size());
    memcpy(m_data, rhs.data(), byte_size_word_aligned(m_size));
    return *this;
  }

  ~bitvector() 
  bool get_all_bits_set()
  {
    if (m_data)
      my_free(m_data, MYF(0));
    uint32 *data_ptr= (uint32*)&m_data[0];
    for (; data_ptr <= last_word_ptr; data_ptr++)
      if (*data_ptr != 0xFFFFFFFF)
        return FALSE;
    return TRUE;
  }

  /* Swap the guts of this instance with another instance. */
  void swap(bitvector& other)
  bool get_all_bits_clear()
  {
    my_swap(m_size, other.m_size);
    my_swap(m_data, other.m_data);
    uint32 *data_ptr= (uint32*)m_data;
    if (*last_word_ptr != last_word_mask)
      return FALSE;
    for (; data_ptr < last_word_ptr; data_ptr++)
      if (*data_ptr)
        return FALSE;
    return TRUE;
  }

  /* A pointer to the bytes representing the bits */
  byte const *data() const { return m_data; }
  uchar const *data() const { return m_data; }

  /* The size of the data in *bytes* */
  size_t bytes() const { return byte_size(m_size); }
@@ -194,47 +194,55 @@ class bitvector
  /* Set all bits in the vector */
  void set_all()
  { 
    /* std::fill_n(m_data, bytes(), 255); */
    memset(m_data, 255, bytes()); 
    tidy_last_byte();
    memset(m_data, 255, byte_size_word_aligned(m_size)); 
  }

  /* Set a bit to a value */
  void set_bit(size_t pos)
  {
    apply_to_byte<void>(pos, set_bit_op());
    DBUG_ASSERT(pos < m_size);
    m_data[pos>>3]|= (uchar)(1 << (pos & 0x7U));
  }

  /* Reset (clear) all bits in the vector */
  void clear_all()
  { 
    /* std::fill_n(m_data, bytes(), 0); */
    memset(m_data, 0, bytes()); 
    tidy_last_byte();
    tidy_last_word();
  }

  /* Reset one bit in the vector */
  void clear_bit(size_t pos)
  {
    apply_to_byte<void>(pos, clear_bit_op());
    DBUG_ASSERT(pos < m_size);
    m_data[pos>>3]&= ~(uchar)(1 << (pos & 0x7U));
  }

  void flip_bit(size_t pos)
  {
    apply_to_byte<void>(pos, flip_bit_op());
    DBUG_ASSERT(pos < m_size);
    m_data[pos>>3]^= (uchar)(1 << (pos & 0x7U));
  }

  bool get_bit(size_t pos) const
  {
    return apply_to_byte<bool>(pos, test_bit_op());
    DBUG_ASSERT(pos < m_size);
    /*
      !! provides the most effective implementation of conversion to
      bool
    */
    uchar *byte_word= m_data + (pos >> 3);
    uchar mask= 1 << (pos & 0x7U);
    bool ret_value= !!(*byte_word & mask);
    return ret_value;
  };

  bool operator==(bitvector const& rhs) const
  {
    if (size() != rhs.size())
      return false;
    /* This works since I have ensured that the last byte of the array contain
     * sensible data.
    /* This works since I have ensured that the last byte of the array
     * contain sensible data.
     */
    if (memcmp(data(), rhs.data(), bytes()) != 0)
      return false;
@@ -246,9 +254,52 @@ class bitvector
    return !(*this == rhs);
  }

  bitvector &operator&=(bitvector const& rhs)
  {
    DBUG_ASSERT(size() == rhs.size());
    uint32 *data_ptr=(uint32*)data(), *rhs_data_ptr=(uint32*)rhs.data();
    uint32 *last_ptr= last_word_ptr;
    for (; data_ptr <= last_ptr; data_ptr++, rhs_data_ptr++)
      *data_ptr&=*rhs_data_ptr;
    return *this;
  }

  bitvector &operator|=(bitvector const& rhs)
  {
    DBUG_ASSERT(size() == rhs.size());
    uint32 *data_ptr=(uint32*)data(), *rhs_data_ptr=(uint32*)rhs.data();
    uint32 *last_ptr= last_word_ptr;
    for (; data_ptr <= last_ptr; data_ptr++, rhs_data_ptr++)
      *data_ptr|=*rhs_data_ptr;
    return *this;
  }

  bitvector &operator^=(bitvector const& rhs)
  {
    DBUG_ASSERT(size() == rhs.size());
    uint32 *data_ptr=(uint32*)data(), *rhs_data_ptr=(uint32*)rhs.data();
    uint32 *last_ptr= last_word_ptr;
    for (; data_ptr <= last_ptr; data_ptr++, rhs_data_ptr++)
      *data_ptr^=*rhs_data_ptr;
    tidy_last_word();
    return *this;
  }

  bitvector &operator~()
  {
    uint32 *data_ptr= (uint32*)data();
    uint32 *last_ptr= last_word_ptr;
    for (; data_ptr <= last_ptr; data_ptr++)
      *data_ptr^=0xFFFFFFFF;
    tidy_last_word();
    return *this;
  }

private:
  size_t m_size;
  byte *m_data;
  uint32 last_word_mask;
  uchar *m_data;
  uint32 *last_word_ptr;
};

#endif /* BITVECTOR_H */
Loading