libuav original

Dependents:   UAVCAN UAVCAN_Subscriber

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers bitset.hpp Source File

bitset.hpp

00001 /*
00002  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
00003  */
00004 
00005 #ifndef UAVCAN_UTIL_BITSET_HPP_INCLUDED
00006 #define UAVCAN_UTIL_BITSET_HPP_INCLUDED
00007 
00008 #include <cassert>
00009 #include <cstddef>
00010 #include <cstring>
00011 #include <uavcan/build_config.hpp>
00012 
00013 namespace uavcan
00014 {
00015 /**
00016  * STL-like bitset
00017  */
00018 template <std::size_t NumBits>
00019 class UAVCAN_EXPORT BitSet
00020 {
00021     enum { NumBytes = (NumBits + 7) / 8 };
00022 
00023     static std::size_t getByteNum(std::size_t bit_num) { return bit_num / 8; }
00024 
00025     static std::size_t getBitNum(const std::size_t bit_num) { return bit_num % 8; }
00026 
00027     static void validatePos(std::size_t& inout_pos)
00028     {
00029         if (inout_pos >= NumBits)
00030         {
00031             UAVCAN_ASSERT(0);
00032             inout_pos = NumBits - 1;
00033         }
00034     }
00035 
00036     char data_[NumBytes];
00037 
00038 public:
00039     class Reference
00040     {
00041         friend class BitSet;
00042 
00043         BitSet* const parent_;
00044         const std::size_t bitpos_;
00045 
00046         Reference(BitSet* arg_parent, std::size_t arg_bitpos)
00047             : parent_(arg_parent)
00048             , bitpos_(arg_bitpos)
00049         { }
00050 
00051     public:
00052         Reference& operator=(bool x)
00053         {
00054             parent_->set(bitpos_, x);
00055             return *this;
00056         }
00057 
00058         Reference& operator=(const Reference& x)
00059         {
00060             parent_->set(bitpos_, x);
00061             return *this;
00062         }
00063 
00064         bool operator~() const
00065         {
00066             return !parent_->test(bitpos_);
00067         }
00068 
00069         operator bool() const
00070         {
00071             return parent_->test(bitpos_);
00072         }
00073     };
00074 
00075     BitSet()
00076         : data_()
00077     {
00078         reset();
00079     }
00080 
00081     BitSet<NumBits>& reset()
00082     {
00083         std::memset(data_, 0, NumBytes);
00084         return *this;
00085     }
00086 
00087     BitSet<NumBits>& set()
00088     {
00089         std::memset(data_, 0xFF, NumBytes);
00090         return *this;
00091     }
00092 
00093     BitSet<NumBits>& set(std::size_t pos, bool val = true)
00094     {
00095         validatePos(pos);
00096         if (val)
00097         {
00098             data_[getByteNum(pos)] = char(data_[getByteNum(pos)] | (1 << getBitNum(pos)));
00099         }
00100         else
00101         {
00102             data_[getByteNum(pos)] = char(data_[getByteNum(pos)] & ~(1 << getBitNum(pos)));
00103         }
00104         return *this;
00105     }
00106 
00107     bool test(std::size_t pos) const
00108     {
00109         return (data_[getByteNum(pos)] & (1 << getBitNum(pos))) != 0;
00110     }
00111 
00112     bool any() const
00113     {
00114         for (std::size_t i = 0; i < NumBits; ++i)
00115         {
00116             if (test(i))
00117             {
00118                 return true;
00119             }
00120         }
00121         return false;
00122     }
00123 
00124     std::size_t count() const
00125     {
00126         std::size_t retval = 0;
00127         for (std::size_t i = 0; i < NumBits; ++i)
00128         {
00129             retval += test(i) ? 1U : 0U;
00130         }
00131         return retval;
00132     }
00133 
00134     std::size_t size() const { return NumBits; }
00135 
00136     bool operator[](std::size_t pos) const
00137     {
00138         return test(pos);
00139     }
00140 
00141     Reference operator[](std::size_t pos)
00142     {
00143         validatePos(pos);
00144         return Reference(this, pos);
00145     }
00146 
00147     BitSet<NumBits>& operator=(const BitSet<NumBits> & rhs)
00148     {
00149         if (&rhs == this)
00150         {
00151             return *this;
00152         }
00153         for (std::size_t i = 0; i < NumBytes; ++i)
00154         {
00155             data_[i] = rhs.data_[i];
00156         }
00157         return *this;
00158     }
00159 
00160     bool operator!=(const BitSet<NumBits>& rhs) const { return !operator==(rhs); }
00161     bool operator==(const BitSet<NumBits>& rhs) const
00162     {
00163         for (std::size_t i = 0; i < NumBits; ++i)
00164         {
00165             if (test(i) != rhs.test(i))
00166             {
00167                 return false;
00168             }
00169         }
00170         return true;
00171     }
00172 };
00173 
00174 template <> class BitSet<0>;  ///< Invalid instantiation
00175 
00176 
00177 template <typename Stream, std::size_t NumBits>
00178 Stream& operator<<(Stream& s, const BitSet<NumBits>& x)
00179 {
00180     for (std::size_t i = NumBits; i > 0; --i)
00181     {
00182         s << (x.test(i-1) ? "1" : "0");
00183     }
00184     return s;
00185 }
00186 
00187 }
00188 
00189 #endif // UAVCAN_UTIL_BITSET_HPP_INCLUDED