mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-17 04:52:59 +01:00
Merge pull request #18833 from benpicco/bitfield-ops
sys/bitfield: add bf_find_first_{set, unset}()
This commit is contained in:
commit
7e0af3cd22
@ -13,26 +13,34 @@
|
||||
* @brief Bitfield auxiliary functions
|
||||
*
|
||||
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
||||
* @author Benjamin Valentin <benjamin.valentin@ml-pa.com>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "bitfield.h"
|
||||
#include "irq.h"
|
||||
|
||||
static inline unsigned _skip_bytes(const uint8_t field[], unsigned nbytes, uint8_t byte)
|
||||
{
|
||||
unsigned i = 0;
|
||||
for (unsigned j = 0; (j < nbytes) && (field[j] == byte); j++) {
|
||||
i += 8;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
int bf_get_unset(uint8_t field[], size_t size)
|
||||
{
|
||||
int result = -1;
|
||||
int nbytes = (size + 7) / 8;
|
||||
size_t i = 0;
|
||||
unsigned nbytes = (size + 7) / 8;
|
||||
|
||||
unsigned state = irq_disable();
|
||||
|
||||
/* skip full bytes */
|
||||
for (int j = 0; (j < nbytes) && (field[j] == 255); j++) {
|
||||
i += 8;
|
||||
}
|
||||
unsigned i = _skip_bytes(field, nbytes, 0xff);
|
||||
|
||||
for (; i < size; i++) {
|
||||
if (!bf_isset(field, i)) {
|
||||
@ -45,3 +53,42 @@ int bf_get_unset(uint8_t field[], size_t size)
|
||||
irq_restore(state);
|
||||
return result;
|
||||
}
|
||||
|
||||
int bf_find_first_set(const uint8_t field[], size_t size)
|
||||
{
|
||||
unsigned nbytes = (size + 7) / 8;
|
||||
unsigned i = _skip_bytes(field, nbytes, 0);
|
||||
|
||||
for (; i < size; i++) {
|
||||
if (bf_isset(field, i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int bf_find_first_unset(const uint8_t field[], size_t size)
|
||||
{
|
||||
unsigned nbytes = (size + 7) / 8;
|
||||
unsigned i = _skip_bytes(field, nbytes, 0xff);
|
||||
|
||||
for (; i < size; i++) {
|
||||
if (!bf_isset(field, i)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void bf_set_all(uint8_t field[], size_t size)
|
||||
{
|
||||
unsigned bytes = size >> 3;
|
||||
unsigned bits = size & 0x7;
|
||||
|
||||
memset(field, 0xff, bytes);
|
||||
if (bits) {
|
||||
field[bytes] = ~((1U << (8 - bits)) - 1);
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ static inline void bf_toggle(uint8_t field[], size_t idx)
|
||||
* @param[in,out] field The bitfield
|
||||
* @param[in] idx The number of the bit to check
|
||||
*/
|
||||
static inline bool bf_isset(uint8_t field[], size_t idx)
|
||||
static inline bool bf_isset(const uint8_t field[], size_t idx)
|
||||
{
|
||||
return (field[idx / 8] & (1u << (7 - (idx % 8))));
|
||||
}
|
||||
@ -189,6 +189,36 @@ static inline void bf_inv(uint8_t out[], const uint8_t a[], size_t len)
|
||||
*/
|
||||
int bf_get_unset(uint8_t field[], size_t len);
|
||||
|
||||
/**
|
||||
* @brief Get the index of the first set bit in the field
|
||||
*
|
||||
* @param[in] field The bitfield
|
||||
* @param[in] size The size of the bitfield
|
||||
*
|
||||
* @return number of the first set bit
|
||||
* @return -1 if no bit is set
|
||||
*/
|
||||
int bf_find_first_set(const uint8_t field[], size_t size);
|
||||
|
||||
/**
|
||||
* @brief Get the index of the zero bit in the field
|
||||
*
|
||||
* @param[in] field The bitfield
|
||||
* @param[in] size The size of the bitfield
|
||||
*
|
||||
* @return number of the first unset bit
|
||||
* @return -1 if all bits are set
|
||||
*/
|
||||
int bf_find_first_unset(const uint8_t field[], size_t size);
|
||||
|
||||
/**
|
||||
* @brief Set all bits in the bitfield to 1
|
||||
*
|
||||
* @param[in] field The bitfield
|
||||
* @param[in] size The size of the bitfield
|
||||
*/
|
||||
void bf_set_all(uint8_t field[], size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -222,8 +222,84 @@ static void test_bf_ops(void)
|
||||
TEST_ASSERT_EQUAL_INT(0, memcmp(c, b, sizeof(c)));
|
||||
}
|
||||
|
||||
Test *tests_bitfield_tests(void)
|
||||
static void test_bf_find_first_set(void)
|
||||
{
|
||||
int res;
|
||||
uint8_t field[5];
|
||||
memset(field, 0, sizeof(field));
|
||||
|
||||
res = bf_find_first_set(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(-1, res);
|
||||
|
||||
bf_set(field, 23);
|
||||
res = bf_find_first_set(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(23, res);
|
||||
|
||||
bf_set(field, 24);
|
||||
res = bf_find_first_set(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(23, res);
|
||||
|
||||
bf_set(field, 13);
|
||||
res = bf_find_first_set(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(13, res);
|
||||
|
||||
bf_set(field, 3);
|
||||
res = bf_find_first_set(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(3, res);
|
||||
}
|
||||
|
||||
static void test_bf_find_first_unset(void)
|
||||
{
|
||||
int res;
|
||||
uint8_t field[5];
|
||||
memset(field, 0xff, sizeof(field));
|
||||
|
||||
res = bf_find_first_unset(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(-1, res);
|
||||
|
||||
bf_unset(field, 23);
|
||||
res = bf_find_first_unset(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(23, res);
|
||||
|
||||
bf_unset(field, 24);
|
||||
res = bf_find_first_unset(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(23, res);
|
||||
|
||||
bf_unset(field, 13);
|
||||
res = bf_find_first_unset(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(13, res);
|
||||
|
||||
bf_unset(field, 3);
|
||||
res = bf_find_first_unset(field, 40);
|
||||
TEST_ASSERT_EQUAL_INT(3, res);
|
||||
}
|
||||
|
||||
static void test_bf_set_all(void)
|
||||
{
|
||||
uint8_t field[5];
|
||||
|
||||
memset(field, 0, sizeof(field));
|
||||
bf_set_all(field, 5);
|
||||
TEST_ASSERT_EQUAL_INT(0xf8, field[0]);
|
||||
TEST_ASSERT_EQUAL_INT(0, field[1]);
|
||||
|
||||
memset(field, 0, sizeof(field));
|
||||
bf_set_all(field, 24);
|
||||
TEST_ASSERT_EQUAL_INT(0xff, field[0]);
|
||||
TEST_ASSERT_EQUAL_INT(0xff, field[1]);
|
||||
TEST_ASSERT_EQUAL_INT(0xff, field[2]);
|
||||
TEST_ASSERT_EQUAL_INT(0, field[3]);
|
||||
|
||||
memset(field, 0, sizeof(field));
|
||||
bf_set_all(field, 30);
|
||||
TEST_ASSERT_EQUAL_INT(0xff, field[0]);
|
||||
TEST_ASSERT_EQUAL_INT(0xff, field[1]);
|
||||
TEST_ASSERT_EQUAL_INT(0xff, field[2]);
|
||||
TEST_ASSERT_EQUAL_INT(0xfc, field[3]);
|
||||
TEST_ASSERT_EQUAL_INT(0, field[4]);
|
||||
}
|
||||
|
||||
Test *tests_bitfield_tests(void) {
|
||||
EMB_UNIT_TESTFIXTURES(fixtures) {
|
||||
new_TestFixture(test_bf_set),
|
||||
new_TestFixture(test_bf_unset),
|
||||
@ -234,6 +310,9 @@ Test *tests_bitfield_tests(void)
|
||||
new_TestFixture(test_bf_get_unset_middle),
|
||||
new_TestFixture(test_bf_get_unset_lastbyte),
|
||||
new_TestFixture(test_bf_ops),
|
||||
new_TestFixture(test_bf_find_first_set),
|
||||
new_TestFixture(test_bf_find_first_unset),
|
||||
new_TestFixture(test_bf_set_all),
|
||||
};
|
||||
|
||||
EMB_UNIT_TESTCALLER(bitfield_tests, NULL, NULL, fixtures);
|
||||
|
Loading…
Reference in New Issue
Block a user