diff --git a/libuavcan/include/uavcan/bitset.hpp b/libuavcan/include/uavcan/bitset.hpp new file mode 100644 index 0000000000..74ea6cb765 --- /dev/null +++ b/libuavcan/include/uavcan/bitset.hpp @@ -0,0 +1,186 @@ +/* + * Copyright (C) 2014 Pavel Kirienko + */ + +#pragma once + +#include +#include +#include +#include + +namespace uavcan +{ +/** + * STL-like bitset + */ +template +class BitSet +{ + enum { NumBytes = (NumBits + 7) / 8 }; + + static std::size_t getByteNum(std::size_t bit_num) { return bit_num / 8; } + + static std::size_t getBitNum(const std::size_t bit_num) { return bit_num % 8; } + + static void validatePos(std::size_t& inout_pos) + { + if (inout_pos >= NumBits) + { + assert(0); + inout_pos = NumBits - 1; + } + } + + char data_[NumBytes]; + +public: + class Reference + { + friend class BitSet; + + BitSet* const parent_; + const std::size_t bitpos_; + + Reference(BitSet* arg_parent, std::size_t arg_bitpos) + : parent_(arg_parent) + , bitpos_(arg_bitpos) + { } + + public: + Reference& operator=(bool x) + { + parent_->set(bitpos_, x); + return *this; + } + + Reference& operator=(const Reference& x) + { + parent_->set(bitpos_, x); + return *this; + } + + bool operator~() const + { + return !parent_->test(bitpos_); + } + + operator bool() const + { + return parent_->test(bitpos_); + } + }; + + BitSet() + : data_() + { + reset(); + } + + BitSet& reset() + { + std::memset(data_, 0, NumBytes); + return *this; + } + + BitSet& set() + { + std::memset(data_, 0xFF, NumBytes); + return *this; + } + + BitSet& set(std::size_t pos, bool val = true) + { + validatePos(pos); + if (val) + { + data_[getByteNum(pos)] |= (1 << getBitNum(pos)); + } + else + { + data_[getByteNum(pos)] &= ~(1 << getBitNum(pos)); + } + return *this; + } + + bool test(std::size_t pos) const + { + return (data_[getByteNum(pos)] & (1 << getBitNum(pos))) != 0; + } + + bool any() const + { + for (std::size_t i = 0; i < NumBits; ++i) + { + if (test(i)) + { + return true; + } + } + return false; + } + + std::size_t count() const + { + std::size_t retval = 0; + for (std::size_t i = 0; i < NumBits; ++i) + { + retval += test(i) ? 1U : 0U; + } + return retval; + } + + std::size_t size() const { return NumBits; } + + bool operator[](std::size_t pos) const + { + return test(pos); + } + + Reference operator[](std::size_t pos) + { + validatePos(pos); + return Reference(this, pos); + } + + BitSet& operator=(const BitSet & rhs) + { + if (&rhs == this) + { + return *this; + } + for (std::size_t i = 0; i < NumBytes; ++i) + { + data_[i] = rhs.data_[i]; + } + return *this; + } + + bool operator!=(const BitSet& rhs) const { return !operator==(rhs); } + bool operator==(const BitSet& rhs) const + { + for (std::size_t i = 0; i < NumBits; ++i) + { + if (test(i) != rhs.test(i)) + { + return false; + } + } + return true; + } +}; + +template <> class BitSet<0>; ///< Invalid instantiation + + +template +Stream& operator<<(Stream& s, const BitSet& x) +{ + for (std::size_t i = NumBits; i > 0; --i) + { + s << (x.test(i-1) ? "1" : "0"); + } + return s; +} + +} diff --git a/libuavcan/include/uavcan/marshal/array.hpp b/libuavcan/include/uavcan/marshal/array.hpp index 0b90c001ae..399759de36 100644 --- a/libuavcan/include/uavcan/marshal/array.hpp +++ b/libuavcan/include/uavcan/marshal/array.hpp @@ -5,13 +5,12 @@ #pragma once #include -#include #include #include -#include #include #include #include +#include #include #include #include @@ -21,6 +20,10 @@ # error UAVCAN_EXCEPTIONS #endif +#if UAVCAN_EXCEPTIONS +# include +#endif + namespace uavcan { @@ -202,7 +205,7 @@ public: */ template class UAVCAN_EXPORT ArrayImpl, ArrayMode, MaxSize> - : public std::bitset + : public BitSet , public Select, StaticArrayBase >::Result { typedef typename Select, Arra public: enum { IsStringLike = 0 }; - typedef typename std::bitset::reference Reference; + typedef typename BitSet::Reference Reference; typedef typename ArrayBase::SizeType SizeType; using ArrayBase::size; using ArrayBase::capacity; - Reference at(SizeType pos) { return std::bitset::operator[](ArrayBase::validateRange(pos)); } - bool at(SizeType pos) const { return std::bitset::operator[](ArrayBase::validateRange(pos)); } + Reference at(SizeType pos) { return BitSet::operator[](ArrayBase::validateRange(pos)); } + bool at(SizeType pos) const { return BitSet::operator[](ArrayBase::validateRange(pos)); } Reference operator[](SizeType pos) { return at(pos); } bool operator[](SizeType pos) const { return at(pos); } diff --git a/libuavcan/include/uavcan/node/global_data_type_registry.hpp b/libuavcan/include/uavcan/node/global_data_type_registry.hpp index 5fed147554..d18785690b 100644 --- a/libuavcan/include/uavcan/node/global_data_type_registry.hpp +++ b/libuavcan/include/uavcan/node/global_data_type_registry.hpp @@ -5,11 +5,11 @@ #pragma once #include -#include #include #include #include #include +#include #include #include #if UAVCAN_DEBUG @@ -19,7 +19,7 @@ namespace uavcan { -typedef std::bitset DataTypeIDMask; +typedef BitSet DataTypeIDMask; class UAVCAN_EXPORT GlobalDataTypeRegistry : Noncopyable { diff --git a/libuavcan/include/uavcan/protocol/network_compat_checker.hpp b/libuavcan/include/uavcan/protocol/network_compat_checker.hpp index da8444d397..61ed7f1fe4 100644 --- a/libuavcan/include/uavcan/protocol/network_compat_checker.hpp +++ b/libuavcan/include/uavcan/protocol/network_compat_checker.hpp @@ -4,7 +4,7 @@ #pragma once -#include +#include #include #include #include @@ -26,7 +26,7 @@ struct UAVCAN_EXPORT NetworkCompatibilityCheckResult */ class UAVCAN_EXPORT NetworkCompatibilityChecker : Noncopyable { - typedef std::bitset NodeIDMask; + typedef BitSet NodeIDMask; typedef MethodBinder&)> NodeStatusCallback; diff --git a/libuavcan/src/uc_error.cpp b/libuavcan/src/uc_error.cpp index 938fbe4a87..bfa15bc9f0 100644 --- a/libuavcan/src/uc_error.cpp +++ b/libuavcan/src/uc_error.cpp @@ -5,12 +5,15 @@ #include #include #include -#include #ifndef UAVCAN_EXCEPTIONS # error UAVCAN_EXCEPTIONS #endif +#if UAVCAN_EXCEPTIONS +# include +#endif + namespace uavcan {