From 7ea7f186e66f2b0a51ccb278c7e527204e92e3f6 Mon Sep 17 00:00:00 2001 From: ilor <kailoran@gmail.com> Date: Thu, 4 Nov 2010 12:30:16 +0100 Subject: [PATCH] Pwrutiuls: add set_bits_iterator with a test, bump version to 0.0.3 --- libpwrutils/CMakeLists.txt | 2 +- libpwrutils/bitset.h | 65 +++++++++++++++++++++++++++++++++++++- tests/tag_split.cpp | 12 +++++++ 3 files changed, 77 insertions(+), 2 deletions(-) diff --git a/libpwrutils/CMakeLists.txt b/libpwrutils/CMakeLists.txt index b7e1370..84cbcc8 100644 --- a/libpwrutils/CMakeLists.txt +++ b/libpwrutils/CMakeLists.txt @@ -4,7 +4,7 @@ PROJECT(pwrutils) set(pwrutils_ver_major "0") set(pwrutils_ver_minor "0") -set(pwrutils_ver_patch "2") +set(pwrutils_ver_patch "3") set(LIBPWRUTILS_VERSION "${pwrutils_ver_major}.${pwrutils_ver_minor}.${pwrutils_ver_patch}") diff --git a/libpwrutils/bitset.h b/libpwrutils/bitset.h index a0a2be6..2b5342b 100644 --- a/libpwrutils/bitset.h +++ b/libpwrutils/bitset.h @@ -58,6 +58,69 @@ inline size_t lowest_bit(const unsigned long& t) return boost::lowest_bit(t); } +/// Helper iterator class for iterating through set bits +template<typename T> +struct set_bits_iterator +{ + typedef T value_type; + typedef std::forward_iterator_tag iterator_category; + typedef int difference_type; + typedef const T *pointer; + typedef const T &reference; + set_bits_iterator(const set_bits_iterator &i): i_(i.i_), c_(i.c_) {} + set_bits_iterator(const T& i) : i_(i), c_(0) { + adv(); + } + + set_bits_iterator &operator++() { + adv(); return *this; + } + set_bits_iterator operator++(int) { + set_bits_iterator c(*this); + c.adv(); + return c; + } + bool operator==(const set_bits_iterator &i) const { + return i_ == i.i_ && c_ == i.c_; + } + bool operator!=(const set_bits_iterator &i) const { + return i_ != i.i_ || c_ != i.c_; + } + const T &operator*() const { return c_; } + +private: + void adv() { + c_.reset(); + if (i_.any()) { + c_.set(lowest_bit(i_)); + i_ ^= c_; + } + } + + T i_; + T c_; +}; + +/** + * Function that returns a foreach-compatible iterator range that allows + * iterating through the set bits of a bitset. It only makes sense to read + * from the returned range. + * + * Example usage: \code + * foreach (const bitset<32>& b, my_bitset) { + * foo_with(b); + * } + * \endcode + */ +template<size_t S> +boost::iterator_range< set_bits_iterator< std::bitset<S> > > set_bits( + const bitset<S>& bs) +{ + return boost::iterator_range< set_bits_iterator< std::bitset<S> > >( + bs, bitset<S>() + ); +} + } /* end ns PwrNlp */ namespace std { @@ -106,6 +169,6 @@ bool operator<(bitset<PwrNlp::ulong_bits> left, bitset<PwrNlp::ulong_bits> right return left.to_ulong() < right.to_ulong(); } -} +} /* end ns std */ #endif // PWRNLP_BITSET_H diff --git a/tests/tag_split.cpp b/tests/tag_split.cpp index 1f4ca44..7197653 100644 --- a/tests/tag_split.cpp +++ b/tests/tag_split.cpp @@ -1,6 +1,7 @@ #include <boost/test/unit_test.hpp> #include <set> #include <libpwrutils/foreach.h> +#include <libpwrutils/bitset.h> #include <libcorpus2/tagset.h> #include <libcorpus2/token.h> @@ -196,3 +197,14 @@ BOOST_FIXTURE_TEST_CASE( tag_size, F ) } BOOST_AUTO_TEST_SUITE_END() + +BOOST_AUTO_TEST_CASE(bs_split) +{ + std::bitset<32> x(0xf6543); + std::bitset<32> y(0); + foreach (std::bitset<32> b, PwrNlp::set_bits(x)) { + BOOST_CHECK_EQUAL(b.count(), 1); + y |= b; + } + BOOST_CHECK_EQUAL(x, y); +} -- GitLab