Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions sys/include/bitfield.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
* @defgroup sys_bitfield Bitfields
* @ingroup sys
* @brief Bitfields of arbitrary length
*
* The bitfields in this module have their most significant bytes first and
* their most significant bits within each byte of the bitfield also first.
*
* @file
* @{
*
Expand Down Expand Up @@ -49,7 +53,7 @@ extern "C" {
*/
static inline void bf_set(uint8_t field[], size_t idx)
{
field[idx / 8] |= (1u << (idx % 8));
field[idx / 8] |= (1u << (7 - (idx % 8)));
}

/**
Expand All @@ -60,7 +64,7 @@ static inline void bf_set(uint8_t field[], size_t idx)
*/
static inline void bf_unset(uint8_t field[], size_t idx)
{
field[idx / 8] &= ~(1u << (idx % 8));
field[idx / 8] &= ~(1u << (7 - (idx % 8)));
Comment thread
benpicco marked this conversation as resolved.
}

/**
Expand All @@ -71,7 +75,7 @@ static inline void bf_unset(uint8_t field[], size_t idx)
*/
static inline void bf_toggle(uint8_t field[], size_t idx)
{
field[idx / 8] ^= (1u << (idx % 8));
field[idx / 8] ^= (1u << (7 - (idx % 8)));
}

/**
Expand All @@ -82,7 +86,7 @@ static inline void bf_toggle(uint8_t field[], size_t idx)
*/
static inline bool bf_isset(uint8_t field[], size_t idx)
{
return (field[idx / 8] & (1u << (idx % 8)));
return (field[idx / 8] & (1u << (7 - (idx % 8))));
}

/**
Expand Down
103 changes: 94 additions & 9 deletions tests/unittests/tests-bitfield/tests-bitfield.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2015 Kaspar Schleiser <kaspar@schleiser.de>
* 2019 Freie Universität Berlin
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
Expand All @@ -13,6 +14,86 @@

#include "bitfield.h"

static void test_bf_set(void)
{
BITFIELD(field, 32U);

memset(field, 0x00, sizeof(field));
bf_set(field, 3);
/* bit idx: 3/8 + 01234567
* 0x10 == 0b00010000 */
TEST_ASSERT_EQUAL_INT(0x10, field[3 / 8]);
bf_set(field, 1);
/* bit idx: 1/8 + 01234567
* 0x50 == 0b01010000 */
TEST_ASSERT_EQUAL_INT(0x50, field[1 / 8]);
bf_set(field, 25);
/* bit idx: 25/8 + 01234567
* 0x40 == 0b01000000 */
TEST_ASSERT_EQUAL_INT(0x40, field[25 / 8]);
}

static void test_bf_unset(void)
{
BITFIELD(field, 32U);

memset(field, 0xff, sizeof(field));
bf_unset(field, 5);
/* bit idx: 5/8 + 01234567
* 0xfb == 0b11111011 */
TEST_ASSERT_EQUAL_INT(0xfb, field[5 / 8]);
bf_unset(field, 8);
/* cppcheck-suppress duplicateExpression
* reason: intentionally dividing 8 by itself to make test more readable
* bit idx: 8/8 + 01234567
* 0x7f == 0b01111111 */
TEST_ASSERT_EQUAL_INT(0x7f, field[8 / 8]);
bf_unset(field, 10);
/* bit idx: 10/8 + 01234567
* 0x5f == 0b01011111 */
TEST_ASSERT_EQUAL_INT(0x5f, field[10 / 8]);
}

static void test_bf_toggle(void)
{
BITFIELD(field, 32U);

memset(field, 0xff, sizeof(field));
bf_toggle(field, 7);
/* bit idx: 7/8 + 01234567
* 0xfe == 0b11111110 */
TEST_ASSERT_EQUAL_INT(0xfe, field[7 / 8]);
bf_toggle(field, 0);
/* bit idx: 0/8 + 01234567
* 0x7e == 0b01111110 */
TEST_ASSERT_EQUAL_INT(0x7e, field[0 / 8]);
bf_toggle(field, 7);
/* bit idx: 7/8 + 01234567
* 0x7f == 0b01111111 */
TEST_ASSERT_EQUAL_INT(0x7f, field[7 / 8]);
bf_toggle(field, 0);
/* bit idx: 0/8 + 01234567
* 0xff == 0b11111111 */
TEST_ASSERT_EQUAL_INT(0xff, field[0 / 8]);
bf_toggle(field, 28);
/* bit idx: 28/8 + 01234567
* 0xf7 == 0b11110111 */
TEST_ASSERT_EQUAL_INT(0xf7, field[28 / 8]);
}

static void test_bf_isset(void)
{
BITFIELD(field, 32U);

/* bf_set / bf_unset tested above */
memset(field, 0x00, sizeof(field));
TEST_ASSERT(!bf_isset(field, 25));
bf_set(field, 25);
TEST_ASSERT(bf_isset(field, 25));
bf_unset(field, 25);
TEST_ASSERT(!bf_isset(field, 25));
}

static void test_bf_get_unset_empty(void)
{
int res = 0;
Expand Down Expand Up @@ -53,15 +134,15 @@ static void test_bf_get_unset_firstbyte(void)
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(0, res);

field[0] = 0x01;
field[0] = 0x80;
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(1, res);

field[0] = 0x0f;
field[0] = 0xf0;
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(4, res);

field[0] = 0x7f;
field[0] = 0xfe;
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(7, res);

Expand All @@ -80,15 +161,15 @@ static void test_bf_get_unset_middle(void)
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(16, res);

field[2] = 0x01;
field[2] = 0x80;
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(17, res);

field[2] = 0x0f;
field[2] = 0xf0;
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(20, res);

field[2] = 0x7f;
field[2] = 0xfe;
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(23, res);
}
Expand All @@ -103,22 +184,26 @@ static void test_bf_get_unset_lastbyte(void)
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(32, res);

field[4] = 0x01;
field[4] = 0x80;
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(33, res);

field[4] = 0x0f;
field[4] = 0xf0;
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(36, res);

field[4] = 0x7f;
field[4] = 0xfe;
res = bf_get_unset(field, 40);
TEST_ASSERT_EQUAL_INT(39, res);
}

Test *tests_bitfield_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(test_bf_set),
new_TestFixture(test_bf_unset),
new_TestFixture(test_bf_toggle),
new_TestFixture(test_bf_isset),
new_TestFixture(test_bf_get_unset_empty),
new_TestFixture(test_bf_get_unset_firstbyte),
new_TestFixture(test_bf_get_unset_middle),
Expand Down