From 787af8de1808e286bc0ea2d8dcc5d7208d237209 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Thu, 7 Sep 2017 11:49:07 -0500 Subject: [PATCH] BitSet building convenience Allow set()/clear()/flip() to be chained. Support c++11 initializer lists. --- src/misc/bitSet.cpp | 31 +++++++++++++++++++++++-------- src/misc/pv/bitSet.h | 20 +++++++++++++++++--- testApp/misc/testBitSet.cpp | 20 +++++++++++++++++++- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/src/misc/bitSet.cpp b/src/misc/bitSet.cpp index 930b470..e58e778 100644 --- a/src/misc/bitSet.cpp +++ b/src/misc/bitSet.cpp @@ -55,6 +55,19 @@ namespace epics { namespace pvData { words.reserve((nbits == 0) ? 1 : WORD_INDEX(nbits-1) + 1); } +#if __cplusplus>=201103L + BitSet::BitSet(std::initializer_list I) + { + // optimistically guess that highest bit is last (not required) + words.reserve((I.size() == 0) ? 1 : WORD_INDEX(*(I.end()-1)) + 1); + + for(uint32 idx : I) + { + set(idx); + } + } +#endif + BitSet::~BitSet() {} void BitSet::recalculateWordsInUse() { @@ -76,7 +89,7 @@ namespace epics { namespace pvData { ensureCapacity(wordIndex+1); } - void BitSet::flip(uint32 bitIndex) { + BitSet& BitSet::flip(uint32 bitIndex) { uint32 wordIdx = WORD_INDEX(bitIndex); expandTo(wordIdx); @@ -84,25 +97,27 @@ namespace epics { namespace pvData { words[wordIdx] ^= (((uint64)1) << WORD_OFFSET(bitIndex)); recalculateWordsInUse(); + return *this; } - void BitSet::set(uint32 bitIndex) { + BitSet& BitSet::set(uint32 bitIndex) { uint32 wordIdx = WORD_INDEX(bitIndex); expandTo(wordIdx); words[wordIdx] |= (((uint64)1) << WORD_OFFSET(bitIndex)); + return *this; } - void BitSet::clear(uint32 bitIndex) { + BitSet& BitSet::clear(uint32 bitIndex) { uint32 wordIdx = WORD_INDEX(bitIndex); - if (wordIdx >= words.size()) - return; + if (wordIdx < words.size()) { + words[wordIdx] &= ~(((uint64)1) << WORD_OFFSET(bitIndex)); - words[wordIdx] &= ~(((uint64)1) << WORD_OFFSET(bitIndex)); - - recalculateWordsInUse(); + recalculateWordsInUse(); + } + return *this; } void BitSet::set(uint32 bitIndex, bool value) { diff --git a/src/misc/pv/bitSet.h b/src/misc/pv/bitSet.h index ac78c16..aac6ea9 100644 --- a/src/misc/pv/bitSet.h +++ b/src/misc/pv/bitSet.h @@ -9,6 +9,10 @@ #ifndef BITSET_H #define BITSET_H +#if __cplusplus>=201103L +# include +#endif + #include #include @@ -65,6 +69,16 @@ namespace epics { namespace pvData { */ BitSet(uint32 nbits); +#if __cplusplus>=201103L + /** Initialize from a list of indicies + @code + BitSet X({1, 5}); + assert(X.get(1) && X.get(5)); + @endcode + */ + BitSet(std::initializer_list I); +#endif + /** * Destructor. */ @@ -76,21 +90,21 @@ namespace epics { namespace pvData { * * @param bitIndex the index of the bit to flip */ - void flip(uint32 bitIndex); + BitSet& flip(uint32 bitIndex); /** * Sets the bit at the specified index to @c true. * * @param bitIndex a bit index */ - void set(uint32 bitIndex); + BitSet& set(uint32 bitIndex); /** * Sets the bit specified by the index to @c false. * * @param bitIndex the index of the bit to be cleared */ - void clear(uint32 bitIndex); + BitSet& clear(uint32 bitIndex); /** * Sets the bit at the specified index to the specified value. diff --git a/testApp/misc/testBitSet.cpp b/testApp/misc/testBitSet.cpp index 5370699..1fd55d0 100644 --- a/testApp/misc/testBitSet.cpp +++ b/testApp/misc/testBitSet.cpp @@ -23,10 +23,13 @@ #include #include +#include #include #include +namespace { + using namespace epics::pvData; using std::string; @@ -37,6 +40,18 @@ static string toString(BitSet& bitSet) return oss.str(); } +void testInitialize() +{ + testDiag("testInitialize()"); +#if __cplusplus>=201103L + testOk1(BitSet().size()==0); + testOk1(BitSet({}).size()==0); + testEqual(BitSet().set(1).set(5).set(500), BitSet({1, 5, 500})); +#else + testSkip(3, "Not c++11"); +#endif +} + static void testGetSetClearFlip() { testDiag("testGetSetClearFlip... "); @@ -292,9 +307,12 @@ static void testSerialize() #undef TOFRO } +} // namespace + MAIN(testBitSet) { - testPlan(87); + testPlan(90); + testInitialize(); testGetSetClearFlip(); testOperators(); testLogical();