diff --git a/Sming/Core/Data/BitSet.h b/Sming/Core/Data/BitSet.h index 46576015d6..3df5063653 100644 --- a/Sming/Core/Data/BitSet.h +++ b/Sming/Core/Data/BitSet.h @@ -430,6 +430,34 @@ template inline constexpr BitSet operator+(E a, E b) return a | b; } +inline String toString(uint8_t value) +{ + return String(value); +} + +/** + * @brief Class template to print the contents of a BitSet to a String + * @note Requires an implementation of `toString(E)` + */ +template +String toString(const BitSet& bitset, const String& separator = ", ") +{ + String s; + + for(unsigned i = 0; i < bitset.size(); ++i) { + if(!bitset[E(i)]) { + continue; + } + + if(s) { + s += separator; + } + s += toString(E(i)); + } + + return s; +} + /** * @brief A set of 32 bits */ diff --git a/docs/source/framework/core/data/bitset.rst b/docs/source/framework/core/data/bitset.rst index 03e2a99127..ca8f4c3e91 100644 --- a/docs/source/framework/core/data/bitset.rst +++ b/docs/source/framework/core/data/bitset.rst @@ -68,6 +68,14 @@ Bit manipulation operators are provided so you can do logical stuff like this:: And so on. +To display the contents of a BitSet, do this:: + + Serial.print(_F("My basket contains: ")); + Serial.println(basket1); + +You will also need to provide an implementation of ``toString(Fruit)`` +or whatever type you are using for the set elements. + API --- diff --git a/tests/HostTests/app/test-bitset.cpp b/tests/HostTests/app/test-bitset.cpp index 280b70d7bf..f7c16466bc 100644 --- a/tests/HostTests/app/test-bitset.cpp +++ b/tests/HostTests/app/test-bitset.cpp @@ -3,18 +3,32 @@ namespace { +#define FRUIT_ELEMENT_MAP(XX) \ + XX(apple) \ + XX(banana) \ + XX(kiwi) \ + XX(orange) \ + XX(passion) \ + XX(pear) \ + XX(tomato) + enum class Fruit { - apple, - banana, - kiwi, - orange, - passion, - pear, - tomato, +#define XX(n) n, + FRUIT_ELEMENT_MAP(XX) +#undef XX + MAX }; -using FruitBasket = BitSet; -using NumberSet = BitSet; +#define XX(n) #n "\0" +DEFINE_FSTR_LOCAL(fruitStrings, FRUIT_ELEMENT_MAP(XX)) +#undef XX + +String toString(Fruit f) +{ + return CStringArray(fruitStrings)[unsigned(f)]; +} + +using FruitBasket = BitSet; static constexpr FruitBasket fixedBasket = Fruit::orange | Fruit::banana | Fruit::tomato; @@ -61,6 +75,9 @@ class BitSetTest : public TestGroup TEST_CASE("Operations") { + Serial.print(_F("fixedBasket contains: ")); + Serial.println(toString(fixedBasket)); + FruitBasket basket; REQUIRE(basket.value() == 0); REQUIRE(!basket); @@ -103,8 +120,11 @@ class BitSetTest : public TestGroup TEST_CASE("Number set") { - NumberSet numbers = 12U; - REQUIRE(numbers.value() == 12); + using NumberSet = BitSet; + NumberSet numbers = 0x12345678U; + Serial.print(_F("numbers = ")); + Serial.println(toString(numbers)); + REQUIRE(numbers.value() == 0x12345678U); numbers = NumberSet{}; REQUIRE(numbers.value() == 0);