36 #include "mysys_priv.h"
37 #include <my_bitmap.h>
41 void create_last_word_mask(
MY_BITMAP *map)
44 unsigned int const used= 1
U + ((map->n_bits-1
U) & 0x7U);
50 unsigned char const mask= (~((1 << used) - 1)) & 255;
58 unsigned char *ptr= (
unsigned char*)&map->last_word_mask;
60 map->last_word_ptr= map->bitmap + no_words_in_map(map)-1;
61 switch (no_bytes_in_map(map) & 3) {
63 map->last_word_mask= ~0
U;
67 map->last_word_mask= ~0
U;
72 map->last_word_mask= 0
U;
77 map->last_word_mask= 0
U;
84 static inline void bitmap_lock(
MY_BITMAP *map __attribute__((unused)))
91 static inline void bitmap_unlock(
MY_BITMAP *map __attribute__((unused)))
98 static inline uint get_first_set(uint32 value, uint word_pos)
100 uchar *byte_ptr= (uchar*)&value;
102 uint byte_pos, bit_pos;
104 for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++)
106 byte_value= *byte_ptr;
109 for (bit_pos=0; ; bit_pos++)
110 if (byte_value & (1 << bit_pos))
111 return (word_pos*32) + (byte_pos*8) + bit_pos;
118 static inline uint get_first_not_set(uint32 value, uint word_pos)
120 uchar *byte_ptr= (uchar*)&value;
122 uint byte_pos, bit_pos;
124 for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++)
126 byte_value= *byte_ptr;
127 if (byte_value != 0xFF)
129 for (bit_pos=0; ; bit_pos++)
130 if (!(byte_value & (1 << bit_pos)))
131 return (word_pos*32) + (byte_pos*8) + bit_pos;
138 my_bool bitmap_init(
MY_BITMAP *map, my_bitmap_map *
buf, uint n_bits,
139 my_bool thread_safe __attribute__((unused)))
141 DBUG_ENTER(
"bitmap_init");
144 uint size_in_bytes= bitmap_buffer_size(n_bits);
149 size_in_bytes= ALIGN_SIZE(size_in_bytes);
154 if (!(buf= (my_bitmap_map*) my_malloc(size_in_bytes+extra, MYF(MY_WME))))
167 DBUG_ASSERT(thread_safe == 0);
174 create_last_word_mask(map);
175 bitmap_clear_all(map);
182 DBUG_ENTER(
"bitmap_free");
188 my_free(map->bitmap);
208 my_bool bitmap_fast_test_and_set(
MY_BITMAP *map, uint bitmap_bit)
210 uchar *value= ((uchar*) map->bitmap) + (bitmap_bit / 8);
211 uchar bit= 1 << ((bitmap_bit) & 7);
212 uchar res= (*value) & bit;
231 my_bool bitmap_test_and_set(
MY_BITMAP *map, uint bitmap_bit)
234 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
236 res= bitmap_fast_test_and_set(map, bitmap_bit);
254 my_bool bitmap_fast_test_and_clear(
MY_BITMAP *map, uint bitmap_bit)
256 uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8);
257 uchar bit= 1 << ((bitmap_bit) & 7);
258 uchar res= (*byte) & bit;
264 my_bool bitmap_test_and_clear(
MY_BITMAP *map, uint bitmap_bit)
267 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
269 res= bitmap_fast_test_and_clear(map, bitmap_bit);
278 DBUG_ASSERT(map->bitmap);
279 if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE)
280 bitmap_set_bit(map, bit_found);
285 void bitmap_set_prefix(
MY_BITMAP *map, uint prefix_size)
287 uint prefix_bytes, prefix_bits, d;
288 uchar *m= (uchar *)map->bitmap;
290 DBUG_ASSERT(map->bitmap &&
291 (prefix_size <= map->n_bits || prefix_size == (uint) ~0));
292 set_if_smaller(prefix_size, map->n_bits);
293 if ((prefix_bytes= prefix_size / 8))
294 memset(m, 0xff, prefix_bytes);
296 if ((prefix_bits= prefix_size & 7))
297 *(m++)= (1 << prefix_bits)-1;
298 if ((d= no_bytes_in_map(map)-prefix_bytes))
303 my_bool bitmap_is_prefix(
const MY_BITMAP *map, uint prefix_size)
305 uint prefix_bits= prefix_size % 32;
306 my_bitmap_map *word_ptr= map->bitmap, last_word;
307 my_bitmap_map *end_prefix= word_ptr + prefix_size / 32;
308 DBUG_ASSERT(word_ptr && prefix_size <= map->n_bits);
311 for (; word_ptr < end_prefix; word_ptr++)
312 if (*word_ptr != 0xFFFFFFFF)
315 last_word= *map->last_word_ptr & ~map->last_word_mask;
320 if (word_ptr == map->last_word_ptr)
321 return uint4korr((uchar*)&last_word) == (uint32)((1 << prefix_bits) - 1);
322 else if (uint4korr((uchar*)word_ptr) != (uint32)((1 << prefix_bits) - 1))
328 for (; word_ptr < map->last_word_ptr; word_ptr++)
341 return word_ptr > map->last_word_ptr || last_word == 0;
345 my_bool bitmap_is_set_all(
const MY_BITMAP *map)
347 my_bitmap_map *data_ptr= map->bitmap;
348 my_bitmap_map *end= map->last_word_ptr;
350 for (; data_ptr < end; data_ptr++)
351 if (*data_ptr != 0xFFFFFFFF)
353 if ((*map->last_word_ptr | map->last_word_mask) != 0xFFFFFFFF)
359 my_bool bitmap_is_clear_all(
const MY_BITMAP *map)
361 my_bitmap_map *data_ptr= map->bitmap;
362 my_bitmap_map *end= map->last_word_ptr;
364 for (; data_ptr < end; data_ptr++)
367 if (*map->last_word_ptr & ~map->last_word_mask)
376 my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
378 DBUG_ASSERT(map1->bitmap && map2->bitmap &&
379 map1->n_bits==map2->n_bits);
381 end= map1->last_word_ptr;
382 for (; m1 < end; m1++, m2++)
386 if ((*map1->last_word_ptr & ~map1->last_word_mask) &
387 ~(*map2->last_word_ptr & ~map2->last_word_mask))
396 my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
398 DBUG_ASSERT(map1->bitmap && map2->bitmap &&
399 map1->n_bits==map2->n_bits);
401 end= map1->last_word_ptr;
402 for (; m1 < end; m1++, m2++)
406 if ((*map1->last_word_ptr & ~map1->last_word_mask) &
407 (*map2->last_word_ptr & ~map2->last_word_mask))
415 my_bitmap_map *
to= map->bitmap, *from= map2->bitmap, *end;
416 uint len= no_words_in_map(map), len2 = no_words_in_map(map2);
418 DBUG_ASSERT(map->bitmap && map2->bitmap);
420 end= to + MY_MIN(len, len2);
421 for (; to < end; to++, from++)
425 map->bitmap[len2 - 1] &= ~map2->last_word_mask;
430 for (; to < end; to++)
456 void bitmap_set_above(
MY_BITMAP *map, uint from_byte, uint use_bit)
458 uchar use_byte= use_bit ? 0xff : 0;
459 uchar *to= (uchar *)map->bitmap + from_byte;
460 uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8;
462 for (; to < end; to++)
469 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
470 DBUG_ASSERT(map->bitmap && map2->bitmap &&
471 map->n_bits==map2->n_bits);
472 end= map->last_word_ptr;
474 for (; to <= end; to++, from++)
481 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
482 DBUG_ASSERT(map->bitmap && map2->bitmap &&
483 map->n_bits==map2->n_bits);
484 end= map->last_word_ptr;
486 for (; to <= end; to++, from++)
493 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
494 DBUG_ASSERT(map->bitmap && map2->bitmap &&
495 map->n_bits==map2->n_bits);
496 end= map->last_word_ptr;
498 for (; to <= end; to++, from++)
505 my_bitmap_map *to= map->bitmap, *end;
506 DBUG_ASSERT(map->bitmap);
507 end= map->last_word_ptr;
509 for (; to <= end; to++)
514 uint bitmap_bits_set(
const MY_BITMAP *map)
516 my_bitmap_map *data_ptr= map->bitmap;
517 my_bitmap_map *end= map->last_word_ptr;
519 DBUG_ASSERT(map->bitmap);
521 for (; data_ptr < end; data_ptr++)
522 res+= my_count_bits_uint32(*data_ptr);
525 res+= my_count_bits_uint32(*map->last_word_ptr & ~map->last_word_mask);
532 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
533 DBUG_ASSERT(map->bitmap && map2->bitmap &&
534 map->n_bits==map2->n_bits);
535 end= map->last_word_ptr;
537 for (; to <= end; to++, from++)
542 uint bitmap_get_first_set(
const MY_BITMAP *map)
545 my_bitmap_map *data_ptr, *end= map->last_word_ptr;
547 DBUG_ASSERT(map->bitmap);
548 data_ptr= map->bitmap;
550 for (word_pos=0; data_ptr < end; data_ptr++, word_pos++)
552 return get_first_set(*data_ptr, word_pos);
554 return get_first_set(*map->last_word_ptr & ~map->last_word_mask, word_pos);
567 uint bitmap_get_next_set(
const MY_BITMAP *map, uint bitmap_bit)
569 uint word_pos, byte_to_mask,
i;
570 my_bitmap_map first_word;
571 unsigned char *ptr= (
unsigned char*) &first_word;
572 my_bitmap_map *data_ptr, *end= map->last_word_ptr;
574 DBUG_ASSERT(map->bitmap);
578 if (bitmap_bit >= map->n_bits)
580 word_pos= bitmap_bit / 32;
581 data_ptr= map->bitmap + word_pos;
582 first_word= *data_ptr;
585 byte_to_mask= (bitmap_bit % 32) / 8;
586 for (i= 0; i < byte_to_mask; i++)
588 ptr[byte_to_mask]&= 0xFF
U << (bitmap_bit & 7);
591 return get_first_set(first_word & ~map->last_word_mask, word_pos);
594 return get_first_set(first_word, word_pos);
596 for (data_ptr++, word_pos++; data_ptr < end; data_ptr++, word_pos++)
598 return get_first_set(*data_ptr, word_pos);
600 return get_first_set(*end & ~map->last_word_mask, word_pos);
604 uint bitmap_get_first(
const MY_BITMAP *map)
607 my_bitmap_map *data_ptr, *end= map->last_word_ptr;
609 DBUG_ASSERT(map->bitmap);
610 data_ptr= map->bitmap;
612 for (word_pos=0; data_ptr < end; data_ptr++, word_pos++)
613 if (*data_ptr != 0xFFFFFFFF)
614 return get_first_not_set(*data_ptr, word_pos);
616 return get_first_not_set(*map->last_word_ptr | map->last_word_mask, word_pos);
620 uint bitmap_lock_set_next(
MY_BITMAP *map)
624 bit_found= bitmap_set_next(map);
630 void bitmap_lock_clear_bit(
MY_BITMAP *map, uint bitmap_bit)
633 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
634 bitmap_clear_bit(map, bitmap_bit);