bitmap.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-08-04 JasonHu First Version
  9. */
  10. #include <bitmap.h>
  11. #include <rtdebug.h>
  12. #include <string.h>
  13. void rt_bitmap_init(rt_bitmap_t *bitmap, uint8_t *bits, rt_size_t byte_len)
  14. {
  15. bitmap->bits = bits;
  16. bitmap->byte_length = byte_len;
  17. memset(bitmap->bits, 0, bitmap->byte_length);
  18. }
  19. static rt_bool_t rt_bitmap_test(rt_bitmap_t *bitmap, rt_ubase_t index)
  20. {
  21. rt_ubase_t byte_idx = index / 8;
  22. rt_ubase_t bit_odd = index % 8;
  23. return (bitmap->bits[byte_idx] & (RT_BITMAP_MASK << bit_odd));
  24. }
  25. rt_base_t rt_bitmap_scan(rt_bitmap_t *bitmap, rt_size_t count)
  26. {
  27. if (!bitmap || !count)
  28. {
  29. return -1;
  30. }
  31. rt_ubase_t idx_byte = 0;
  32. while ((0xff == bitmap->bits[idx_byte]) && (idx_byte < bitmap->byte_length))
  33. {
  34. idx_byte++;
  35. }
  36. if (idx_byte == bitmap->byte_length) /* out of array range */
  37. {
  38. return -1;
  39. }
  40. rt_base_t idx_bit = 0;
  41. while ((rt_uint8_t)(RT_BITMAP_MASK << idx_bit) & bitmap->bits[idx_byte])
  42. {
  43. idx_bit++;
  44. }
  45. rt_base_t idx_start = idx_byte * 8 + idx_bit;
  46. if (count == 1)
  47. {
  48. return idx_start;
  49. }
  50. rt_ubase_t bit_left = (bitmap->byte_length * 8 - idx_start);
  51. rt_ubase_t next_bit = idx_start + 1;
  52. rt_ubase_t ret_count = 1;
  53. idx_start = -1;
  54. while (bit_left-- > 0)
  55. {
  56. if (!(rt_bitmap_test(bitmap, next_bit)))
  57. {
  58. ret_count++;
  59. }
  60. else
  61. {
  62. ret_count = 0; /* no consecutive bits, reset count */
  63. }
  64. if (ret_count == count)
  65. {
  66. idx_start = next_bit - ret_count + 1;
  67. break;
  68. }
  69. next_bit++;
  70. }
  71. return idx_start;
  72. }
  73. void rt_bitmap_set(rt_bitmap_t *bitmap, rt_ubase_t index, rt_bool_t value)
  74. {
  75. rt_ubase_t byte_idx = index / 8;
  76. rt_ubase_t bit_odd = index % 8;
  77. if (value) {
  78. bitmap->bits[byte_idx] |= (RT_BITMAP_MASK << bit_odd);
  79. } else {
  80. bitmap->bits[byte_idx] &= ~(RT_BITMAP_MASK << bit_odd);
  81. }
  82. }
  83. rt_bool_t rt_bitmap_change(rt_bitmap_t *bitmap, rt_ubase_t index)
  84. {
  85. rt_ubase_t byte_idx = index / 8;
  86. rt_ubase_t bit_odd = index % 8;
  87. bitmap->bits[byte_idx] ^= (RT_BITMAP_MASK << bit_odd); /* xor */
  88. return (bitmap->bits[byte_idx] & (RT_BITMAP_MASK << bit_odd));
  89. }
  90. rt_bool_t rt_bitmap_test_and_change(rt_bitmap_t *bitmap, rt_ubase_t index)
  91. {
  92. rt_ubase_t byte_idx = index / 8;
  93. rt_ubase_t bit_odd = index % 8;
  94. rt_bool_t ret = (rt_bool_t) bitmap->bits[byte_idx] & (RT_BITMAP_MASK << bit_odd);
  95. bitmap->bits[byte_idx] ^= (RT_BITMAP_MASK << bit_odd); /* xor */
  96. return ret;
  97. }