mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / mysys / my_bitmap.c
blobe4e4f61357cc8ba8f1bc3691b7a52b66dc1e016f
1 /*
2 Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 Handling of uchar arrays as large bitmaps.
21 API limitations (or, rather asserted safety assumptions,
22 to encourage correct programming)
24 * the internal size is a set of 32 bit words
25 * the number of bits specified in creation can be any number > 0
26 * there are THREAD safe versions of most calls called bitmap_lock_*
27 many of those are not used and not compiled normally but the code
28 already exist for them in an #ifdef:ed part. These can only be used
29 if THREAD was specified in bitmap_init
31 TODO:
32 Make assembler THREAD safe versions of these using test-and-set instructions
34 Original version created by Sergei Golubchik 2001 - 2004.
35 New version written and test program added and some changes to the interface
36 was made by Mikael Ronström 2005, with assistance of Tomas Ulin and Mats
37 Kindahl.
40 #include "mysys_priv.h"
41 #include <my_bitmap.h>
42 #include <m_string.h>
43 #include <my_bit.h>
45 void create_last_word_mask(MY_BITMAP *map)
47 /* Get the number of used bits (1..8) in the last byte */
48 unsigned int const used= 1U + ((map->n_bits-1U) & 0x7U);
51 Create a mask with the upper 'unused' bits set and the lower 'used'
52 bits clear. The bits within each byte is stored in big-endian order.
54 unsigned char const mask= (~((1 << used) - 1)) & 255;
57 The first bytes are to be set to zero since they represent real bits
58 in the bitvector. The last bytes are set to 0xFF since they represent
59 bytes not used by the bitvector. Finally the last byte contains bits
60 as set by the mask above.
62 unsigned char *ptr= (unsigned char*)&map->last_word_mask;
64 map->last_word_ptr= map->bitmap + no_words_in_map(map)-1;
65 switch (no_bytes_in_map(map) & 3) {
66 case 1:
67 map->last_word_mask= ~0U;
68 ptr[0]= mask;
69 return;
70 case 2:
71 map->last_word_mask= ~0U;
72 ptr[0]= 0;
73 ptr[1]= mask;
74 return;
75 case 3:
76 map->last_word_mask= 0U;
77 ptr[2]= mask;
78 ptr[3]= 0xFFU;
79 return;
80 case 0:
81 map->last_word_mask= 0U;
82 ptr[3]= mask;
83 return;
88 static inline void bitmap_lock(MY_BITMAP *map __attribute__((unused)))
90 #ifdef THREAD
91 if (map->mutex)
92 pthread_mutex_lock(map->mutex);
93 #endif
97 static inline void bitmap_unlock(MY_BITMAP *map __attribute__((unused)))
99 #ifdef THREAD
100 if (map->mutex)
101 pthread_mutex_unlock(map->mutex);
102 #endif
106 static inline uint get_first_set(uint32 value, uint word_pos)
108 uchar *byte_ptr= (uchar*)&value;
109 uchar byte_value;
110 uint byte_pos, bit_pos;
112 for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++)
114 byte_value= *byte_ptr;
115 if (byte_value)
117 for (bit_pos=0; ; bit_pos++)
118 if (byte_value & (1 << bit_pos))
119 return (word_pos*32) + (byte_pos*8) + bit_pos;
122 return MY_BIT_NONE;
126 static inline uint get_first_not_set(uint32 value, uint word_pos)
128 uchar *byte_ptr= (uchar*)&value;
129 uchar byte_value;
130 uint byte_pos, bit_pos;
132 for (byte_pos=0; byte_pos < 4; byte_pos++, byte_ptr++)
134 byte_value= *byte_ptr;
135 if (byte_value != 0xFF)
137 for (bit_pos=0; ; bit_pos++)
138 if (!(byte_value & (1 << bit_pos)))
139 return (word_pos*32) + (byte_pos*8) + bit_pos;
142 return MY_BIT_NONE;
146 my_bool bitmap_init(MY_BITMAP *map, my_bitmap_map *buf, uint n_bits,
147 my_bool thread_safe __attribute__((unused)))
149 DBUG_ENTER("bitmap_init");
150 if (!buf)
152 uint size_in_bytes= bitmap_buffer_size(n_bits);
153 uint extra= 0;
154 #ifdef THREAD
155 if (thread_safe)
157 size_in_bytes= ALIGN_SIZE(size_in_bytes);
158 extra= sizeof(pthread_mutex_t);
160 map->mutex= 0;
161 #endif
162 if (!(buf= (my_bitmap_map*) my_malloc(size_in_bytes+extra, MYF(MY_WME))))
163 DBUG_RETURN(1);
164 #ifdef THREAD
165 if (thread_safe)
167 map->mutex= (pthread_mutex_t *) ((char*) buf + size_in_bytes);
168 pthread_mutex_init(map->mutex, MY_MUTEX_INIT_FAST);
170 #endif
172 #ifdef THREAD
173 else
175 DBUG_ASSERT(thread_safe == 0);
177 #endif
179 map->bitmap= buf;
180 map->n_bits= n_bits;
181 create_last_word_mask(map);
182 bitmap_clear_all(map);
183 DBUG_RETURN(0);
187 void bitmap_free(MY_BITMAP *map)
189 DBUG_ENTER("bitmap_free");
190 if (map->bitmap)
192 #ifdef THREAD
193 if (map->mutex)
194 pthread_mutex_destroy(map->mutex);
195 #endif
196 my_free((char*) map->bitmap, MYF(0));
197 map->bitmap=0;
199 DBUG_VOID_RETURN;
204 test if bit already set and set it if it was not (thread unsafe method)
206 SYNOPSIS
207 bitmap_fast_test_and_set()
208 MAP bit map struct
209 BIT bit number
211 RETURN
212 0 bit was not set
213 !=0 bit was set
216 my_bool bitmap_fast_test_and_set(MY_BITMAP *map, uint bitmap_bit)
218 uchar *value= ((uchar*) map->bitmap) + (bitmap_bit / 8);
219 uchar bit= 1 << ((bitmap_bit) & 7);
220 uchar res= (*value) & bit;
221 *value|= bit;
222 return res;
227 test if bit already set and set it if it was not (thread safe method)
229 SYNOPSIS
230 bitmap_fast_test_and_set()
231 map bit map struct
232 bitmap_bit bit number
234 RETURN
235 0 bit was not set
236 !=0 bit was set
239 my_bool bitmap_test_and_set(MY_BITMAP *map, uint bitmap_bit)
241 my_bool res;
242 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
243 bitmap_lock(map);
244 res= bitmap_fast_test_and_set(map, bitmap_bit);
245 bitmap_unlock(map);
246 return res;
250 test if bit already set and clear it if it was set(thread unsafe method)
252 SYNOPSIS
253 bitmap_fast_test_and_set()
254 MAP bit map struct
255 BIT bit number
257 RETURN
258 0 bit was not set
259 !=0 bit was set
262 my_bool bitmap_fast_test_and_clear(MY_BITMAP *map, uint bitmap_bit)
264 uchar *byte= (uchar*) map->bitmap + (bitmap_bit / 8);
265 uchar bit= 1 << ((bitmap_bit) & 7);
266 uchar res= (*byte) & bit;
267 *byte&= ~bit;
268 return res;
272 my_bool bitmap_test_and_clear(MY_BITMAP *map, uint bitmap_bit)
274 my_bool res;
275 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
276 bitmap_lock(map);
277 res= bitmap_fast_test_and_clear(map, bitmap_bit);
278 bitmap_unlock(map);
279 return res;
283 uint bitmap_set_next(MY_BITMAP *map)
285 uint bit_found;
286 DBUG_ASSERT(map->bitmap);
287 if ((bit_found= bitmap_get_first(map)) != MY_BIT_NONE)
288 bitmap_set_bit(map, bit_found);
289 return bit_found;
293 void bitmap_set_prefix(MY_BITMAP *map, uint prefix_size)
295 uint prefix_bytes, prefix_bits, d;
296 uchar *m= (uchar *)map->bitmap;
298 DBUG_ASSERT(map->bitmap &&
299 (prefix_size <= map->n_bits || prefix_size == (uint) ~0));
300 set_if_smaller(prefix_size, map->n_bits);
301 if ((prefix_bytes= prefix_size / 8))
302 memset(m, 0xff, prefix_bytes);
303 m+= prefix_bytes;
304 if ((prefix_bits= prefix_size & 7))
305 *(m++)= (1 << prefix_bits)-1;
306 if ((d= no_bytes_in_map(map)-prefix_bytes))
307 bzero(m, d);
311 my_bool bitmap_is_prefix(const MY_BITMAP *map, uint prefix_size)
313 uint prefix_bits= prefix_size % 32;
314 my_bitmap_map *word_ptr= map->bitmap, last_word;
315 my_bitmap_map *end_prefix= word_ptr + prefix_size / 32;
316 DBUG_ASSERT(word_ptr && prefix_size <= map->n_bits);
318 /* 1: Words that should be filled with 1 */
319 for (; word_ptr < end_prefix; word_ptr++)
320 if (*word_ptr != 0xFFFFFFFF)
321 return FALSE;
323 last_word= *map->last_word_ptr & ~map->last_word_mask;
325 /* 2: Word which contains the end of the prefix (if any) */
326 if (prefix_bits)
328 if (word_ptr == map->last_word_ptr)
329 return uint4korr((uchar*)&last_word) == (uint32)((1 << prefix_bits) - 1);
330 else if (uint4korr((uchar*)word_ptr) != (uint32)((1 << prefix_bits) - 1))
331 return FALSE;
332 word_ptr++;
335 /* 3: Words that should be filled with 0 */
336 for (; word_ptr < map->last_word_ptr; word_ptr++)
337 if (*word_ptr != 0)
338 return FALSE;
341 We can end up here in two situations:
342 1) We went through the whole bitmap in step 1. This will happen if the
343 whole bitmap is filled with 1 and prefix_size is a multiple of 32
344 (i.e. the prefix does not end in the middle of a word).
345 In this case word_ptr will be larger than map->last_word_ptr.
346 2) We have gone through steps 1-3 and just need to check that also
347 the last word is 0.
349 return word_ptr > map->last_word_ptr || last_word == 0;
353 my_bool bitmap_is_set_all(const MY_BITMAP *map)
355 my_bitmap_map *data_ptr= map->bitmap;
356 my_bitmap_map *end= map->last_word_ptr;
358 for (; data_ptr < end; data_ptr++)
359 if (*data_ptr != 0xFFFFFFFF)
360 return FALSE;
361 if ((*map->last_word_ptr | map->last_word_mask) != 0xFFFFFFFF)
362 return FALSE;
363 return TRUE;
367 my_bool bitmap_is_clear_all(const MY_BITMAP *map)
369 my_bitmap_map *data_ptr= map->bitmap;
370 my_bitmap_map *end= map->last_word_ptr;
372 for (; data_ptr < end; data_ptr++)
373 if (*data_ptr)
374 return FALSE;
375 if (*map->last_word_ptr & ~map->last_word_mask)
376 return FALSE;
377 return TRUE;
380 /* Return TRUE if map1 is a subset of map2 */
382 my_bool bitmap_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
384 my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
386 DBUG_ASSERT(map1->bitmap && map2->bitmap &&
387 map1->n_bits==map2->n_bits);
389 end= map1->last_word_ptr;
390 for (; m1 < end; m1++, m2++)
391 if (*m1 & ~(*m2))
392 return FALSE;
394 if ((*map1->last_word_ptr & ~map1->last_word_mask) &
395 ~(*map2->last_word_ptr & ~map2->last_word_mask))
396 return FALSE;
397 return TRUE;
400 /* True if bitmaps has any common bits */
402 my_bool bitmap_is_overlapping(const MY_BITMAP *map1, const MY_BITMAP *map2)
404 my_bitmap_map *m1= map1->bitmap, *m2= map2->bitmap, *end;
406 DBUG_ASSERT(map1->bitmap && map2->bitmap &&
407 map1->n_bits==map2->n_bits);
409 end= map1->last_word_ptr;
410 for (; m1 < end; m1++, m2++)
411 if (*m1 & *m2)
412 return TRUE;
414 if ((*map1->last_word_ptr & ~map1->last_word_mask) &
415 (*map2->last_word_ptr & ~map2->last_word_mask))
416 return TRUE;
417 return FALSE;
421 void bitmap_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
423 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
424 uint len= no_words_in_map(map), len2 = no_words_in_map(map2);
426 DBUG_ASSERT(map->bitmap && map2->bitmap);
428 end= to+min(len,len2);
429 for (; to < end; to++, from++)
430 *to &= *from;
432 if (len >= len2)
433 map->bitmap[len2 - 1] &= ~map2->last_word_mask;
435 if (len2 < len)
437 end+=len-len2;
438 for (; to < end; to++)
439 *to= 0;
445 Set/clear all bits above a bit.
447 SYNOPSIS
448 bitmap_set_above()
449 map RETURN The bitmap to change.
450 from_byte The bitmap buffer byte offset to start with.
451 use_bit The bit value (1/0) to use for all upper bits.
453 NOTE
454 You can only set/clear full bytes.
455 The function is meant for the situation that you copy a smaller bitmap
456 to a bigger bitmap. Bitmap lengths are always multiple of eigth (the
457 size of a byte). Using 'from_byte' saves multiplication and division
458 by eight during parameter passing.
460 RETURN
461 void
464 void bitmap_set_above(MY_BITMAP *map, uint from_byte, uint use_bit)
466 uchar use_byte= use_bit ? 0xff : 0;
467 uchar *to= (uchar *)map->bitmap + from_byte;
468 uchar *end= (uchar *)map->bitmap + (map->n_bits+7)/8;
470 for (; to < end; to++)
471 *to= use_byte;
475 void bitmap_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
477 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
478 DBUG_ASSERT(map->bitmap && map2->bitmap &&
479 map->n_bits==map2->n_bits);
480 end= map->last_word_ptr;
482 for (; to <= end; to++, from++)
483 *to &= ~(*from);
487 void bitmap_union(MY_BITMAP *map, const MY_BITMAP *map2)
489 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
490 DBUG_ASSERT(map->bitmap && map2->bitmap &&
491 map->n_bits==map2->n_bits);
492 end= map->last_word_ptr;
494 for (; to <= end; to++, from++)
495 *to |= *from;
499 void bitmap_xor(MY_BITMAP *map, const MY_BITMAP *map2)
501 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
502 DBUG_ASSERT(map->bitmap && map2->bitmap &&
503 map->n_bits==map2->n_bits);
504 end= map->last_word_ptr;
506 for (; to <= end; to++, from++)
507 *to ^= *from;
511 void bitmap_invert(MY_BITMAP *map)
513 my_bitmap_map *to= map->bitmap, *end;
514 DBUG_ASSERT(map->bitmap);
515 end= map->last_word_ptr;
517 for (; to <= end; to++)
518 *to ^= 0xFFFFFFFF;
522 uint bitmap_bits_set(const MY_BITMAP *map)
524 my_bitmap_map *data_ptr= map->bitmap;
525 my_bitmap_map *end= map->last_word_ptr;
526 uint res= 0;
527 DBUG_ASSERT(map->bitmap);
529 for (; data_ptr < end; data_ptr++)
530 res+= my_count_bits_uint32(*data_ptr);
532 /*Reset last bits to zero*/
533 res+= my_count_bits_uint32(*map->last_word_ptr & ~map->last_word_mask);
534 return res;
538 void bitmap_copy(MY_BITMAP *map, const MY_BITMAP *map2)
540 my_bitmap_map *to= map->bitmap, *from= map2->bitmap, *end;
541 DBUG_ASSERT(map->bitmap && map2->bitmap &&
542 map->n_bits==map2->n_bits);
543 end= map->last_word_ptr;
545 for (; to <= end; to++, from++)
546 *to = *from;
550 uint bitmap_get_first_set(const MY_BITMAP *map)
552 uint word_pos;
553 my_bitmap_map *data_ptr, *end= map->last_word_ptr;
555 DBUG_ASSERT(map->bitmap);
556 data_ptr= map->bitmap;
558 for (word_pos=0; data_ptr < end; data_ptr++, word_pos++)
559 if (*data_ptr)
560 return get_first_set(*data_ptr, word_pos);
562 return get_first_set(*map->last_word_ptr & ~map->last_word_mask, word_pos);
566 uint bitmap_get_first(const MY_BITMAP *map)
568 uint word_pos;
569 my_bitmap_map *data_ptr, *end= map->last_word_ptr;
571 DBUG_ASSERT(map->bitmap);
572 data_ptr= map->bitmap;
574 for (word_pos=0; data_ptr < end; data_ptr++, word_pos++)
575 if (*data_ptr != 0xFFFFFFFF)
576 return get_first_not_set(*data_ptr, word_pos);
578 return get_first_not_set(*map->last_word_ptr | map->last_word_mask, word_pos);
582 uint bitmap_lock_set_next(MY_BITMAP *map)
584 uint bit_found;
585 bitmap_lock(map);
586 bit_found= bitmap_set_next(map);
587 bitmap_unlock(map);
588 return bit_found;
592 void bitmap_lock_clear_bit(MY_BITMAP *map, uint bitmap_bit)
594 bitmap_lock(map);
595 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
596 bitmap_clear_bit(map, bitmap_bit);
597 bitmap_unlock(map);
601 #ifdef NOT_USED
602 my_bool bitmap_lock_is_prefix(const MY_BITMAP *map, uint prefix_size)
604 my_bool res;
605 bitmap_lock((MY_BITMAP *)map);
606 res= bitmap_is_prefix(map, prefix_size);
607 bitmap_unlock((MY_BITMAP *)map);
608 return res;
612 void bitmap_lock_set_all(MY_BITMAP *map)
614 bitmap_lock(map);
615 bitmap_set_all(map);
616 bitmap_unlock(map);
620 void bitmap_lock_clear_all(MY_BITMAP *map)
622 bitmap_lock(map);
623 bitmap_clear_all(map);
624 bitmap_unlock(map);
628 void bitmap_lock_set_prefix(MY_BITMAP *map, uint prefix_size)
630 bitmap_lock(map);
631 bitmap_set_prefix(map, prefix_size);
632 bitmap_unlock(map);
636 my_bool bitmap_lock_is_clear_all(const MY_BITMAP *map)
638 uint res;
639 bitmap_lock((MY_BITMAP *)map);
640 res= bitmap_is_clear_all(map);
641 bitmap_unlock((MY_BITMAP *)map);
642 return res;
646 my_bool bitmap_lock_is_set_all(const MY_BITMAP *map)
648 uint res;
649 bitmap_lock((MY_BITMAP *)map);
650 res= bitmap_is_set_all(map);
651 bitmap_unlock((MY_BITMAP *)map);
652 return res;
656 my_bool bitmap_lock_is_set(const MY_BITMAP *map, uint bitmap_bit)
658 my_bool res;
659 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
660 bitmap_lock((MY_BITMAP *)map);
661 res= bitmap_is_set(map, bitmap_bit);
662 bitmap_unlock((MY_BITMAP *)map);
663 return res;
667 my_bool bitmap_lock_is_subset(const MY_BITMAP *map1, const MY_BITMAP *map2)
669 uint res;
670 bitmap_lock((MY_BITMAP *)map1);
671 bitmap_lock((MY_BITMAP *)map2);
672 res= bitmap_is_subset(map1, map2);
673 bitmap_unlock((MY_BITMAP *)map2);
674 bitmap_unlock((MY_BITMAP *)map1);
675 return res;
679 my_bool bitmap_lock_cmp(const MY_BITMAP *map1, const MY_BITMAP *map2)
681 uint res;
683 DBUG_ASSERT(map1->bitmap && map2->bitmap &&
684 map1->n_bits==map2->n_bits);
685 bitmap_lock((MY_BITMAP *)map1);
686 bitmap_lock((MY_BITMAP *)map2);
687 res= bitmap_cmp(map1, map2);
688 bitmap_unlock((MY_BITMAP *)map2);
689 bitmap_unlock((MY_BITMAP *)map1);
690 return res;
694 void bitmap_lock_intersect(MY_BITMAP *map, const MY_BITMAP *map2)
696 bitmap_lock(map);
697 bitmap_lock((MY_BITMAP *)map2);
698 bitmap_intersect(map, map2);
699 bitmap_unlock((MY_BITMAP *)map2);
700 bitmap_unlock(map);
704 void bitmap_lock_subtract(MY_BITMAP *map, const MY_BITMAP *map2)
706 bitmap_lock(map);
707 bitmap_lock((MY_BITMAP *)map2);
708 bitmap_subtract(map, map2);
709 bitmap_unlock((MY_BITMAP *)map2);
710 bitmap_unlock(map);
714 void bitmap_lock_union(MY_BITMAP *map, const MY_BITMAP *map2)
716 bitmap_lock(map);
717 bitmap_lock((MY_BITMAP *)map2);
718 bitmap_union(map, map2);
719 bitmap_unlock((MY_BITMAP *)map2);
720 bitmap_unlock(map);
725 SYNOPSIS
726 bitmap_bits_set()
728 RETURN
729 Number of set bits in the bitmap.
731 uint bitmap_lock_bits_set(const MY_BITMAP *map)
733 uint res;
734 bitmap_lock((MY_BITMAP *)map);
735 DBUG_ASSERT(map->bitmap);
736 res= bitmap_bits_set(map);
737 bitmap_unlock((MY_BITMAP *)map);
738 return res;
743 SYNOPSIS
744 bitmap_get_first()
746 RETURN
747 Number of first unset bit in the bitmap or MY_BIT_NONE if all bits are set.
749 uint bitmap_lock_get_first(const MY_BITMAP *map)
751 uint res;
752 bitmap_lock((MY_BITMAP*)map);
753 res= bitmap_get_first(map);
754 bitmap_unlock((MY_BITMAP*)map);
755 return res;
759 uint bitmap_lock_get_first_set(const MY_BITMAP *map)
761 uint res;
762 bitmap_lock((MY_BITMAP*)map);
763 res= bitmap_get_first_set(map);
764 bitmap_unlock((MY_BITMAP*)map);
765 return res;
769 void bitmap_lock_set_bit(MY_BITMAP *map, uint bitmap_bit)
771 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
772 bitmap_lock(map);
773 bitmap_set_bit(map, bitmap_bit);
774 bitmap_unlock(map);
778 void bitmap_lock_flip_bit(MY_BITMAP *map, uint bitmap_bit)
780 DBUG_ASSERT(map->bitmap && bitmap_bit < map->n_bits);
781 bitmap_lock(map);
782 bitmap_flip_bit(map, bitmap_bit);
783 bitmap_unlock(map);
785 #endif