mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
e415ba0fb2
Moved some BSD string functions from Unireg
812 lines
19 KiB
C
812 lines
19 KiB
C
/* Copyright (C) 2000 MySQL AB
|
|
Copyright (c) 2000, 2011, Oracle and/or its affiliates.
|
|
Copyright (C) 2009- 2011 Monty Program 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; version 2 of the License.
|
|
|
|
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 */
|
|
|
|
/*
|
|
Handling of uchar arrays as large bitmaps.
|
|
|
|
API limitations (or, rather asserted safety assumptions,
|
|
to encourage correct programming)
|
|
|
|
* the internal size is a set of 32 bit words
|
|
* the number of bits specified in creation can be any number > 0
|
|
* there are THREAD safe versions of most calls called bitmap_lock_*
|
|
many of those are not used and not compiled normally but the code
|
|
already exist for them in an #ifdef:ed part. These can only be used
|
|
if THREAD was specified in bitmap_init
|
|
|
|
TODO:
|
|
Make assembler THREAD safe versions of these using test-and-set instructions
|
|
|
|
Original version created by Sergei Golubchik 2001 - 2004.
|
|
New version written and test program added and some changes to the interface
|
|
was made by Mikael Ronström 2005, with assistance of Tomas Ulin and Mats
|
|
Kindahl.
|
|
*/
|
|
|
|
#include "mysys_priv.h"
|
|
#include <my_bitmap.h>
|
|
#include <m_string.h>
|
|
#include <my_bit.h>
|
|
|
|
|
|
/* Create a mask of the significant bits for the last byte (1,3,7,..255) */
|
|
|
|
static inline uchar last_byte_mask(uint bits)
|
|
{
|
|
/* Get the number of used bits-1 (0..7) in the last byte */
|
|
unsigned int const used= (bits - 1U) & 7U;
|
|
/* Return bitmask for the significant bits */
|
|
return ((2U << used) - 1);
|
|
}
|
|
|
|
/*
|
|
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.
|
|
*/
|
|
|
|
static inline uchar invers_last_byte_mask(uint bits)
|
|
{
|
|
return last_byte_mask(bits) ^ 255;
|
|
}
|
|
|
|
|
|
void create_last_word_mask(MY_BITMAP *map)
|
|
{
|
|
unsigned char const mask= invers_last_byte_mask(map->n_bits);
|
|
|
|
/*
|
|
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*)&map->last_word_mask;
|
|
|
|
map->last_word_ptr= map->bitmap + no_words_in_map(map)-1;
|
|
switch (no_bytes_in_map(map) & 3) {
|
|
case 1:
|
|
map->last_word_mask= ~0U;
|
|
ptr[0]= mask;
|
|
return;
|
|
case 2:
|
|
map->last_word_mask= ~0U;
|
|
ptr[0]= 0;
|
|
ptr[1]= mask;
|
|
return;
|
|
case 3:
|
|
map->last_word_mask= 0U;
|
|
ptr[2]= mask;
|
|
ptr[3]= 0xFFU;
|
|
return;
|
|
case 0:
|
|
map->last_word_mask= 0U;
|
|
ptr[3]= mask;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused)))
|
|
{
|
|
#ifdef THREAD
|
|
if (map->mutex)
|
|
pthread_mutex_lock(map->mutex);
|
|
#endif
|
|
}
|
|
|
|
|
|
static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused)))
|
|
{
|
|
#ifdef THREAD
|
|
if (map->mutex)
|
|
pthread_mutex_unlock(map->mutex);
|
|
#endif
|
|
}
|
|
|
|
|
|
my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
|
|
my_bool thread_safe __attribute__((unused)))
|
|
{
|
|
DBUG_ENTER("bitmap_init");
|
|
if (!buf)
|
|
{
|
|
uint size_in_bytes= bitmap_buffer_size(n_bits);
|
|
uint extra= 0;
|
|
#ifdef THREAD
|
|
if (thread_safe)
|
|
{
|
|
size_in_bytes= ALIGN_SIZE(size_in_bytes);
|
|
extra= sizeof(pthread_mutex_t);
|
|
}
|
|
map->mutex= 0;
|
|
#endif
|
|
if (!(buf= (my_bitmap_map*) my_malloc(size_in_bytes+extra, MYF(MY_WME))))
|
|
DBUG_RETURN(1);
|
|
#ifdef THREAD
|
|
if (thread_safe)
|
|
{
|
|
map->mutex= (pthread_mutex_t *) ((char*) buf + size_in_bytes);
|
|
pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST);
|
|
}
|
|
#endif
|
|
}
|
|
#ifdef THREAD
|
|
else
|
|
{
|
|
DBUG_ASSERT(thread_safe == 0);
|
|
}
|
|
#endif
|
|
|
|
map->bitmap= buf;
|
|
map->n_bits= n_bits;
|
|
create_last_word_mask(map);
|
|
bitmap_clear_all(map);
|
|
DBUG_RETURN(0);
|
|
}
|
|
|
|
|
|
void bitmap_free(MY_BITMAP *map)
|
|
{
|
|
DBUG_ENTER("bitmap_free");
|
|
if (map->bitmap)
|
|
{
|
|
#ifdef THREAD
|
|
if (map->mutex)
|
|
pthread_mutex_destroy(map->mutex);
|
|
#endif
|
|
my_free((char*) map->bitmap, MYF(0));
|
|
map->bitmap=0;
|
|
}
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
|
|
|
|
/*
|
|
test if bit already set and set it if it was not (thread unsafe method)
|
|
|
|
SYNOPSIS
|
|
bitmap_fast_test_and_set()
|
|
MAP bit map struct
|
|
BIT bit number
|
|
|
|
RETURN
|
|
0 bit was not set
|
|
!=0 bit was set
|
|
*/
|
|
|
|
my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit)
|
|
{
|
|
uchar *value= ((uchar*) map->bitmap) + (bitmap_bit / 8);
|
|
uchar bit= 1 << ((bitmap_bit) & 7);
|
|
uchar res= (*value) & bit;
|
|
*value|= bit;
|
|
return res;
|
|
}
|
|
|
|
|
|
/*
|
|
test if bit already set and set it if it was not (thread safe method)
|
|
|
|
SYNOPSIS
|
|
bitmap_fast_test_and_set()
|
|
map bit map struct
|
|
bitmap_bit bit number
|
|
|
|
RETURN
|
|
0 bit was not set
|
|
!=0 bit was set
|
|
*/
|
|
|
|
my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit)
|
|
{
|
|
my_bool res;
|
|
DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
|
|
bitmap_lock(map);
|
|
res= bitmap_fast_test_and_set(map, bitmap_bit);
|
|
bitmap_unlock(map);
|
|
return res;
|
|
}
|
|
|
|
/*
|
|
test if bit already set and clear it if it was set(thread unsafe method)
|
|
|
|
SYNOPSIS
|
|
bitmap_fast_test_and_set()
|
|
MAP bit map struct
|
|
BIT bit number
|
|
|
|
RETURN
|
|
0 bit was not set
|
|
!=0 bit was set
|
|
*/
|
|
|
|
my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit)
|
|
{
|
|
uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8);
|
|
uchar bit= 1 << ((bitmap_bit) & 7);
|
|
uchar res= (*byte) & bit;
|
|
*byte&= ~bit;
|
|
return res;
|
|
}
|
|
|
|
|
|
my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit)
|
|
{
|
|
my_bool res;
|
|
DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
|
|
bitmap_lock(map);
|
|
res= bitmap_fast_test_and_clear(map, bitmap_bit);
|
|
bitmap_unlock(map);
|
|
return res;
|
|
}
|
|
|
|
|
|
uint bitmap_set_next(MY_BITMAP *map)
|
|
{
|
|
uint bit_found;
|
|
DBUG_ASSERT(map->bitmap);
|
|
if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE)
|
|
bitmap_set_bit(map, bit_found);
|
|
return bit_found;
|
|
}
|
|
|
|
|
|
void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
|
|
{
|
|
uint prefix_bytes, prefix_bits, d;
|
|
uchar *m= (uchar *)map->bitmap;
|
|
|
|
DBUG_ASSERT(map->bitmap &&
|
|
(prefix_size <= map->n_bits || prefix_size == (uint) ~0));
|
|
set_if_smaller(prefix_size, map->n_bits);
|
|
if ((prefix_bytes= prefix_size / 8))
|
|
memset(m, 0xff, prefix_bytes);
|
|
m+= prefix_bytes;
|
|
if ((prefix_bits= prefix_size & 7))
|
|
{
|
|
*m++= (1 << prefix_bits)-1;
|
|
prefix_bytes++;
|
|
}
|
|
if ((d= no_bytes_in_map(map)-prefix_bytes))
|
|
bzero(m, d);
|
|
}
|
|
|
|
|
|
my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size)
|
|
{
|
|
uint prefix_bits= prefix_size % 32;
|
|
my_bitmap_map *word_ptr= map->bitmap, last_word;
|
|
my_bitmap_map *end_prefix= word_ptr + prefix_size / 32;
|
|
DBUG_ASSERT(word_ptr && prefix_size <= map->n_bits);
|
|
|
|
/* 1: Words that should be filled with 1 */
|
|
for (; word_ptr < end_prefix; word_ptr++)
|
|
if (*word_ptr != 0xFFFFFFFF)
|
|
return FALSE;
|
|
|
|
last_word= *map->last_word_ptr & ~map->last_word_mask;
|
|
|
|
/* 2: Word which contains the end of the prefix (if any) */
|
|
if (prefix_bits)
|
|
{
|
|
if (word_ptr == map->last_word_ptr)
|
|
return uint4korr((uchar*)&last_word) == (uint32)((1 << prefix_bits) - 1);
|
|
if (uint4korr((uchar*)word_ptr) != (uint32)((1 << prefix_bits) - 1))
|
|
return FALSE;
|
|
word_ptr++;
|
|
}
|
|
|
|
/* 3: Words that should be filled with 0 */
|
|
for (; word_ptr < map->last_word_ptr; word_ptr++)
|
|
if (*word_ptr != 0)
|
|
return FALSE;
|
|
|
|
/*
|
|
We can end up here in two situations:
|
|
1) We went through the whole bitmap in step 1. This will happen if the
|
|
whole bitmap is filled with 1 and prefix_size is a multiple of 32
|
|
(i.e. the prefix does not end in the middle of a word).
|
|
In this case word_ptr will be larger than map->last_word_ptr.
|
|
2) We have gone through steps 1-3 and just need to check that also
|
|
the last word is 0.
|
|
*/
|
|
return word_ptr > map->last_word_ptr || last_word == 0;
|
|
}
|
|
|
|
|
|
my_bool bitmap_is_set_all(const MY_BITMAP *map)
|
|
{
|
|
my_bitmap_map *data_ptr= map->bitmap;
|
|
my_bitmap_map *end= map->last_word_ptr;
|
|
|
|
for (; data_ptr < end; data_ptr++)
|
|
if (*data_ptr != 0xFFFFFFFF)
|
|
return FALSE;
|
|
return (*data_ptr | map->last_word_mask) == 0xFFFFFFFF;
|
|
}
|
|
|
|
|
|
my_bool bitmap_is_clear_all(const MY_BITMAP *map)
|
|
{
|
|
my_bitmap_map *data_ptr= map->bitmap;
|
|
my_bitmap_map *end= map->last_word_ptr;
|
|
|
|
for (; data_ptr < end; data_ptr++)
|
|
if (*data_ptr)
|
|
return FALSE;
|
|
return (*data_ptr & ~map->last_word_mask) == 0;
|
|
}
|
|
|
|
/* Return TRUE if map1 is a subset of map2 */
|
|
|
|
my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
|
|
{
|
|
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
|
|
|
|
DBUG_ASSERT(map1->bitmap && map2->bitmap &&
|
|
map1->n_bits==map2->n_bits);
|
|
|
|
end= map1->last_word_ptr;
|
|
while (m1 < end)
|
|
{
|
|
if ((*m1++) & ~(*m2++))
|
|
return 0;
|
|
}
|
|
/* here both maps have the same number of bits - see assert above */
|
|
return ((*m1 & ~*m2 & ~map1->last_word_mask) ? 0 : 1);
|
|
}
|
|
|
|
/* True if bitmaps has any common bits */
|
|
|
|
my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2)
|
|
{
|
|
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
|
|
|
|
DBUG_ASSERT(map1->bitmap && map2->bitmap &&
|
|
map1->n_bits==map2->n_bits);
|
|
|
|
end= map1->last_word_ptr;
|
|
while (m1 < end)
|
|
{
|
|
if ((*m1++) & (*m2++))
|
|
return 1;
|
|
}
|
|
/* here both maps have the same number of bits - see assert above */
|
|
return ((*m1 & *m2 & ~map1->last_word_mask) ? 1 : 0);
|
|
}
|
|
|
|
|
|
void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
|
|
{
|
|
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
|
|
uint len= no_words_in_map(map), len2 = no_words_in_map(map2);
|
|
|
|
DBUG_ASSERT(map->bitmap && map2->bitmap);
|
|
|
|
end= to+min(len,len2);
|
|
while (to < end)
|
|
*to++ &= *from++;
|
|
|
|
if (len2 <= len)
|
|
{
|
|
to[-1]&= ~map2->last_word_mask; /* Clear last not relevant bits */
|
|
end+= len-len2;
|
|
while (to < end)
|
|
*to++= 0;
|
|
}
|
|
}
|
|
|
|
/* True if union of bitmaps have all bits set */
|
|
|
|
my_bool bitmap_union_is_set_all(const MY_BITMAP *map1, const MY_BITMAP *map2)
|
|
{
|
|
my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
|
|
|
|
DBUG_ASSERT(map1->bitmap && map2->bitmap &&
|
|
map1->n_bits==map2->n_bits);
|
|
end= map1->last_word_ptr;
|
|
while ( m1 < end)
|
|
if ((*m1++ | *m2++) != 0xFFFFFFFF)
|
|
return FALSE;
|
|
/* here both maps have the same number of bits - see assert above */
|
|
return ((*m1 | *m2 | map1->last_word_mask) != 0xFFFFFFFF);
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
Set/clear all bits above a bit.
|
|
|
|
SYNOPSIS
|
|
bitmap_set_above()
|
|
map RETURN The bitmap to change.
|
|
from_byte The bitmap buffer byte offset to start with.
|
|
use_bit The bit value (1/0) to use for all upper bits.
|
|
|
|
NOTE
|
|
You can only set/clear full bytes.
|
|
The function is meant for the situation that you copy a smaller bitmap
|
|
to a bigger bitmap. Bitmap lengths are always multiple of eigth (the
|
|
size of a byte). Using 'from_byte' saves multiplication and division
|
|
by eight during parameter passing.
|
|
|
|
RETURN
|
|
void
|
|
*/
|
|
|
|
void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit)
|
|
{
|
|
uchar use_byte= use_bit ? 0xff : 0;
|
|
uchar *to= (uchar *)map->bitmap + from_byte;
|
|
uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8;
|
|
|
|
while (to < end)
|
|
*to++= use_byte;
|
|
}
|
|
|
|
|
|
void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
|
|
{
|
|
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
|
|
DBUG_ASSERT(map->bitmap && map2->bitmap &&
|
|
map->n_bits==map2->n_bits);
|
|
|
|
end= map->last_word_ptr;
|
|
|
|
while (to <= end)
|
|
*to++ &= ~(*from++);
|
|
}
|
|
|
|
|
|
void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
|
|
{
|
|
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
|
|
|
|
DBUG_ASSERT(map->bitmap && map2->bitmap &&
|
|
map->n_bits==map2->n_bits);
|
|
end= map->last_word_ptr;
|
|
|
|
while (to <= end)
|
|
*to++ |= *from++;
|
|
}
|
|
|
|
|
|
void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2)
|
|
{
|
|
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end= map->last_word_ptr;
|
|
DBUG_ASSERT(map->bitmap && map2->bitmap &&
|
|
map->n_bits==map2->n_bits);
|
|
while (to <= end)
|
|
*to++ ^= *from++;
|
|
}
|
|
|
|
|
|
void bitmap_invert(MY_BITMAP *map)
|
|
{
|
|
my_bitmap_map *to= map->bitmap, *end;
|
|
|
|
DBUG_ASSERT(map->bitmap);
|
|
end= map->last_word_ptr;
|
|
|
|
while (to <= end)
|
|
*to++ ^= 0xFFFFFFFF;
|
|
}
|
|
|
|
|
|
uint bitmap_bits_set(const MY_BITMAP *map)
|
|
{
|
|
my_bitmap_map *data_ptr= map->bitmap;
|
|
my_bitmap_map *end= map->last_word_ptr;
|
|
uint res= 0;
|
|
DBUG_ASSERT(map->bitmap);
|
|
|
|
for (; data_ptr < end; data_ptr++)
|
|
res+= my_count_bits_uint32(*data_ptr);
|
|
|
|
/*Reset last bits to zero*/
|
|
res+= my_count_bits_uint32(*map->last_word_ptr & ~map->last_word_mask);
|
|
return res;
|
|
}
|
|
|
|
|
|
void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2)
|
|
{
|
|
my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
|
|
DBUG_ASSERT(map->bitmap && map2->bitmap &&
|
|
map->n_bits==map2->n_bits);
|
|
end= map->last_word_ptr;
|
|
|
|
while (to <= end)
|
|
*to++ = *from++;
|
|
}
|
|
|
|
|
|
uint bitmap_get_first_set(const MY_BITMAP *map)
|
|
{
|
|
uchar *byte_ptr;
|
|
uint i,j,k;
|
|
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
|
|
|
|
DBUG_ASSERT(map->bitmap);
|
|
data_ptr= map->bitmap;
|
|
|
|
for (i=0; data_ptr < end; data_ptr++, i++)
|
|
if (*data_ptr)
|
|
goto found;
|
|
if (!(*data_ptr & ~map->last_word_mask))
|
|
return MY_BIT_NONE;
|
|
|
|
found:
|
|
{
|
|
byte_ptr= (uchar*)data_ptr;
|
|
for (j=0; ; j++, byte_ptr++)
|
|
{
|
|
if (*byte_ptr)
|
|
{
|
|
for (k=0; ; k++)
|
|
{
|
|
if (*byte_ptr & (1 << k))
|
|
return (i*32) + (j*8) + k;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DBUG_ASSERT(0);
|
|
return MY_BIT_NONE; /* Impossible */
|
|
}
|
|
|
|
|
|
uint bitmap_get_first(const MY_BITMAP *map)
|
|
{
|
|
uchar *byte_ptr;
|
|
uint i,j,k;
|
|
my_bitmap_map *data_ptr, *end= map->last_word_ptr;
|
|
|
|
DBUG_ASSERT(map->bitmap);
|
|
data_ptr= map->bitmap;
|
|
*map->last_word_ptr|= map->last_word_mask;
|
|
|
|
for (i=0; data_ptr < end; data_ptr++, i++)
|
|
if (*data_ptr != 0xFFFFFFFF)
|
|
goto found;
|
|
if ((*data_ptr | map->last_word_mask) == 0xFFFFFFFF)
|
|
return MY_BIT_NONE;
|
|
|
|
found:
|
|
{
|
|
byte_ptr= (uchar*)data_ptr;
|
|
for (j=0; ; j++, byte_ptr++)
|
|
{
|
|
if (*byte_ptr != 0xFF)
|
|
{
|
|
for (k=0; ; k++)
|
|
{
|
|
if (!(*byte_ptr & (1 << k)))
|
|
return (i*32) + (j*8) + k;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
DBUG_ASSERT(0);
|
|
return MY_BIT_NONE; /* Impossible */
|
|
}
|
|
|
|
|
|
uint bitmap_lock_set_next(MY_BITMAP *map)
|
|
{
|
|
uint bit_found;
|
|
bitmap_lock(map);
|
|
bit_found= bitmap_set_next(map);
|
|
bitmap_unlock(map);
|
|
return bit_found;
|
|
}
|
|
|
|
|
|
void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit)
|
|
{
|
|
bitmap_lock(map);
|
|
DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
|
|
bitmap_clear_bit(map, bitmap_bit);
|
|
bitmap_unlock(map);
|
|
}
|
|
|
|
|
|
#ifdef NOT_USED
|
|
my_bool bitmap_lock_is_prefix(const MY_BITMAP *map, uint prefix_size)
|
|
{
|
|
my_bool res;
|
|
bitmap_lock((MY_BITMAP *)map);
|
|
res= bitmap_is_prefix(map, prefix_size);
|
|
bitmap_unlock((MY_BITMAP *)map);
|
|
return res;
|
|
}
|
|
|
|
|
|
void bitmap_lock_set_all(MY_BITMAP *map)
|
|
{
|
|
bitmap_lock(map);
|
|
bitmap_set_all(map);
|
|
bitmap_unlock(map);
|
|
}
|
|
|
|
|
|
void bitmap_lock_clear_all(MY_BITMAP *map)
|
|
{
|
|
bitmap_lock(map);
|
|
bitmap_clear_all(map);
|
|
bitmap_unlock(map);
|
|
}
|
|
|
|
|
|
void bitmap_lock_set_prefix(MY_BITMAP *map, uint prefix_size)
|
|
{
|
|
bitmap_lock(map);
|
|
bitmap_set_prefix(map, prefix_size);
|
|
bitmap_unlock(map);
|
|
}
|
|
|
|
|
|
my_bool bitmap_lock_is_clear_all(const MY_BITMAP *map)
|
|
{
|
|
uint res;
|
|
bitmap_lock((MY_BITMAP *)map);
|
|
res= bitmap_is_clear_all(map);
|
|
bitmap_unlock((MY_BITMAP *)map);
|
|
return res;
|
|
}
|
|
|
|
|
|
my_bool bitmap_lock_is_set_all(const MY_BITMAP *map)
|
|
{
|
|
uint res;
|
|
bitmap_lock((MY_BITMAP *)map);
|
|
res= bitmap_is_set_all(map);
|
|
bitmap_unlock((MY_BITMAP *)map);
|
|
return res;
|
|
}
|
|
|
|
|
|
my_bool bitmap_lock_is_set(const MY_BITMAP *map, uint bitmap_bit)
|
|
{
|
|
my_bool res;
|
|
DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
|
|
bitmap_lock((MY_BITMAP *)map);
|
|
res= bitmap_is_set(map, bitmap_bit);
|
|
bitmap_unlock((MY_BITMAP *)map);
|
|
return res;
|
|
}
|
|
|
|
|
|
my_bool bitmap_lock_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
|
|
{
|
|
uint res;
|
|
bitmap_lock((MY_BITMAP *)map1);
|
|
bitmap_lock((MY_BITMAP *)map2);
|
|
res= bitmap_is_subset(map1, map2);
|
|
bitmap_unlock((MY_BITMAP *)map2);
|
|
bitmap_unlock((MY_BITMAP *)map1);
|
|
return res;
|
|
}
|
|
|
|
|
|
my_bool bitmap_lock_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
|
|
{
|
|
uint res;
|
|
|
|
DBUG_ASSERT(map1->bitmap && map2->bitmap &&
|
|
map1->n_bits==map2->n_bits);
|
|
bitmap_lock((MY_BITMAP *)map1);
|
|
bitmap_lock((MY_BITMAP *)map2);
|
|
res= bitmap_cmp(map1, map2);
|
|
bitmap_unlock((MY_BITMAP *)map2);
|
|
bitmap_unlock((MY_BITMAP *)map1);
|
|
return res;
|
|
}
|
|
|
|
|
|
void bitmap_lock_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
|
|
{
|
|
bitmap_lock(map);
|
|
bitmap_lock((MY_BITMAP *)map2);
|
|
bitmap_intersect(map, map2);
|
|
bitmap_unlock((MY_BITMAP *)map2);
|
|
bitmap_unlock(map);
|
|
}
|
|
|
|
|
|
void bitmap_lock_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
|
|
{
|
|
bitmap_lock(map);
|
|
bitmap_lock((MY_BITMAP *)map2);
|
|
bitmap_subtract(map, map2);
|
|
bitmap_unlock((MY_BITMAP *)map2);
|
|
bitmap_unlock(map);
|
|
}
|
|
|
|
|
|
void bitmap_lock_union(MY_BITMAP *map, const MY_BITMAP *map2)
|
|
{
|
|
bitmap_lock(map);
|
|
bitmap_lock((MY_BITMAP *)map2);
|
|
bitmap_union(map, map2);
|
|
bitmap_unlock((MY_BITMAP *)map2);
|
|
bitmap_unlock(map);
|
|
}
|
|
|
|
|
|
/*
|
|
SYNOPSIS
|
|
bitmap_bits_set()
|
|
map
|
|
RETURN
|
|
Number of set bits in the bitmap.
|
|
*/
|
|
uint bitmap_lock_bits_set(const MY_BITMAP *map)
|
|
{
|
|
uint res;
|
|
bitmap_lock((MY_BITMAP *)map);
|
|
DBUG_ASSERT(map->bitmap);
|
|
res= bitmap_bits_set(map);
|
|
bitmap_unlock((MY_BITMAP *)map);
|
|
return res;
|
|
}
|
|
|
|
|
|
/*
|
|
SYNOPSIS
|
|
bitmap_get_first()
|
|
map
|
|
RETURN
|
|
Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set.
|
|
*/
|
|
uint bitmap_lock_get_first(const MY_BITMAP *map)
|
|
{
|
|
uint res;
|
|
bitmap_lock((MY_BITMAP*)map);
|
|
res= bitmap_get_first(map);
|
|
bitmap_unlock((MY_BITMAP*)map);
|
|
return res;
|
|
}
|
|
|
|
|
|
uint bitmap_lock_get_first_set(const MY_BITMAP *map)
|
|
{
|
|
uint res;
|
|
bitmap_lock((MY_BITMAP*)map);
|
|
res= bitmap_get_first_set(map);
|
|
bitmap_unlock((MY_BITMAP*)map);
|
|
return res;
|
|
}
|
|
|
|
|
|
void bitmap_lock_set_bit(MY_BITMAP *map, uint bitmap_bit)
|
|
{
|
|
DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
|
|
bitmap_lock(map);
|
|
bitmap_set_bit(map, bitmap_bit);
|
|
bitmap_unlock(map);
|
|
}
|
|
|
|
|
|
void bitmap_lock_flip_bit(MY_BITMAP *map, uint bitmap_bit)
|
|
{
|
|
DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
|
|
bitmap_lock(map);
|
|
bitmap_flip_bit(map, bitmap_bit);
|
|
bitmap_unlock(map);
|
|
}
|
|
#endif /* NOT_USED */
|