bitfield.hpp
Go to the documentation of this file.
00001 
00002 // bitfield.hpp: defines the bitfield_base type
00003 //
00004 // Copyright 2005 Frank Laub
00005 // Distributed under the Boost Software License, Version 1.0. (See
00006 // accompanying file LICENSE_1_0.txt or copy at
00007 // http://www.boost.org/LICENSE_1_0.txt)
00008 //
00009 
00010 #ifndef BOOST_ENUM_BITFIELD_HPP
00011 #define BOOST_ENUM_BITFIELD_HPP
00012 
00013 // MS compatible compilers support #pragma once
00014 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
00015 # pragma once
00016 #endif
00017 
00018 #include <sstream>
00019 #include <boost/operators.hpp>
00020 
00021 namespace boost {
00022 namespace detail {
00023 
00024         // Befriending Templates requires the need for all this mess.
00025         // So that we can allow the templated ostream insertion operator to access private members.
00026         template <typename T>
00027         class bitfield_base;
00028 
00029         template <typename T>
00030         std::ostream& operator << (std::ostream& os, const bitfield_base<T>& value);
00031 
00032         class bitfield_access
00033         {
00034 # if defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) \
00035         || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551))
00036         // Tasteless as this may seem, making all members public allows member templates
00037         // to work in the absence of member template friends.
00038         public:
00039 # else
00040                 template <typename T>
00041                 friend class bitfield_base;
00042 
00043                 template <typename T>
00044                 friend std::ostream& operator << (std::ostream& os, const bitfield_base<T>& value);
00045 #endif
00046 
00047                 template <typename T>
00048                 static const char* names(BOOST_DEDUCED_TYPENAME T::domain index)
00049                 {
00050                         return T::names(index);
00051                 }
00052 
00053                 template <typename T>
00054                 static BOOST_DEDUCED_TYPENAME T::optional_value values(
00055                         BOOST_DEDUCED_TYPENAME T::domain index)
00056                 {
00057                         return T::values(index);
00058                 }
00059 
00060                 template <typename T>
00061                 static T get_by_value(BOOST_DEDUCED_TYPENAME T::value_type value)
00062                 {
00063                         T ret(value, 0);
00064                         return ret;
00065                 }
00066 
00067         private:
00068                 // objects of this class are useless
00069                 bitfield_access(); //undefined
00070         };
00071 
00072         template <typename T>
00073         class bitfield_base 
00074                 : private boost::bitwise<T>
00075                 , private boost::totally_ordered<T>
00076         {
00077         public:
00078                 typedef bitfield_base<T> this_type;
00079                 typedef size_t index_type;
00080                 typedef size_t value_type;
00081                 typedef enum_iterator<T> const_iterator;
00082                 typedef boost::optional<T> optional;
00083 
00084         protected:
00085                 bitfield_base(value_type value, int) : m_value(value) {}
00086 
00087         public:
00088                 bitfield_base() : m_value(0) {}
00089                 bitfield_base(index_type index)
00090                 {
00091                         optional_value value = bitfield_access::values<T>(enum_cast<T>(index));
00092                         if(value)
00093                                 m_value = *value;
00094                 }
00095 
00096                 static const_iterator begin()
00097                 {
00098                         return const_iterator(0);
00099                 }
00100 
00101                 static const_iterator end()
00102                 {
00103                         return const_iterator(T::size);
00104                 }
00105 
00106                 static optional get_by_value(value_type value)
00107                 {
00108                         // make sure that 'value' is valid
00109                         optional_value not_mask = bitfield_access::values<T>(T::not_mask);
00110                         BOOST_ASSERT(not_mask);
00111                         if(value & *not_mask)
00112                                 return optional();
00113                         return bitfield_access::get_by_value<T>(value);
00114                 }
00115 
00116                 static optional get_by_index(index_type index)
00117                 {
00118                         if(index >= T::size) return optional();
00119                         return optional(enum_cast<T>(index));
00120                 }
00121 
00122                 std::string str() const
00123                 {
00124                         std::stringstream ss;
00125                         ss << *this;
00126                         return ss.str();
00127                 }
00128 
00129                 value_type value() const
00130                 {
00131                         return m_value;
00132                 }
00133 
00134                 bool operator == (const this_type& rhs) const
00135                 {
00136                         return m_value == rhs.m_value;
00137                 }
00138 
00139                 bool operator < (const this_type& rhs) const
00140                 {
00141                         return m_value < rhs.m_value;
00142                 }
00143 
00144                 T& operator |= (const this_type& rhs) 
00145                 {
00146                         m_value |= rhs.m_value;
00147                         return static_cast<T&>(*this);
00148                 }
00149 
00150                 T& operator &= (const this_type& rhs)
00151                 {
00152                         m_value &= rhs.m_value;
00153                         return static_cast<T&>(*this);
00154                 }
00155 
00156                 T& operator ^= (const this_type& rhs)
00157                 {
00158                         m_value ^= rhs.m_value;
00159                         return static_cast<T&>(*this);
00160                 }
00161 
00162                 bool operator[] (index_type pos) const
00163                 {
00164                         optional element = get_by_index(pos);
00165                         if(!element) return false;
00166                         return operator[](*element);
00167                 }
00168 
00169                 bool operator[] (const this_type& rhs) const
00170                 {
00171                         return (m_value & rhs.m_value) != 0;
00172                 }
00173 
00174                 bool set(index_type pos, bool bit = true)
00175                 {
00176                         if(!bit) return reset(pos);
00177                         optional element = get_by_index(pos);
00178                         if(!element) return false;
00179                         return set(*element, bit);
00180                 }
00181 
00182                 bool set(const this_type& rhs, bool bit = true)
00183                 {
00184                         if(!bit) return reset(rhs);
00185                         value_type new_value = m_value | rhs.m_value;
00186                         if(!get_by_value(new_value))
00187                                 return false;
00188 
00189                         m_value = new_value;
00190                         return true;
00191                 }
00192 
00193                 bool reset(index_type pos)
00194                 {
00195                         optional element = get_by_index(pos);
00196                         if(!element) return false;
00197                         return reset(*element);
00198                 }
00199 
00200                 bool reset(const this_type& rhs)
00201                 {
00202                         value_type new_value = m_value & ~(rhs.m_value);
00203                         if(!get_by_value(new_value)) return false;
00204                         m_value = new_value;
00205                         return true;
00206                 }
00207 
00208                 // TODO: implement me
00209                 size_t count() const
00210                 {
00211                         return 0;
00212                 }
00213 
00214                 // TODO: implement me
00215                 bool any() const
00216                 {
00217                         return false;
00218                 }
00219 
00220                 // TODO: implement me
00221                 bool none() const
00222                 {
00223                         return false;
00224                 }
00225 
00226         private:
00227                 typedef boost::optional<value_type> optional_value;
00228                 friend class bitfield_access;
00229                 value_type m_value;
00230         };
00231 
00232         template <typename T>
00233         std::ostream& operator << (std::ostream& os, const bitfield_base<T>& rhs)
00234         {
00235                 typedef BOOST_DEDUCED_TYPENAME T::value_type value_type;
00236                 typedef BOOST_DEDUCED_TYPENAME T::index_type index_type;
00237                 typedef boost::optional<value_type> optional_value;
00238 
00239                 value_type remain = rhs.value();
00240                 optional_value all_mask = bitfield_access::values<T>(T::all_mask);
00241                 if(remain == *all_mask)
00242                 {
00243                         os << "all_mask";
00244                         return os;
00245                 }
00246 
00247                 optional_value not_mask = bitfield_access::values<T>(T::not_mask);
00248                 if(remain == *not_mask)
00249                 {
00250                         os << "not_mask";
00251                         return os;
00252                 }
00253                 // FIXME: there might be a reason the user wants to define the value 0
00254                 //        or perhaps 0 is never legitimate for their usage
00255                 bool isZero = (remain == 0);
00256 
00257                 bool isFirst = true;
00258                 for(index_type i = 0; i < T::size; ++i)
00259                 {
00260                         optional_value mask = bitfield_access::values<T>(enum_cast<T>(i));
00261                         if(*mask == 0 && isZero)
00262                         {
00263                                 const char* name = bitfield_access::names<T>(enum_cast<T>(i));
00264                                 BOOST_ASSERT(name);
00265                                 os << name;
00266                                 return os;
00267                         }
00268                         else if(remain & *mask)
00269                         {
00270                                 if(isFirst)
00271                                         isFirst = false;
00272                                 else
00273                                         os << '|';
00274 
00275                                 const char* name = bitfield_access::names<T>(enum_cast<T>(i));
00276                                 BOOST_ASSERT(name);
00277                                 os << name;
00278                                 remain &= ~(*mask);
00279                                 if(remain == 0)
00280                                         return os;
00281                         }
00282                 }
00283                 if(remain)
00284                 {
00285                         if(!isFirst)
00286                                 os << '|';
00287                         os.fill('0');
00288                         os.width(8);
00289                         os << std::hex << remain;
00290                 }
00291                 else if(isZero)
00292                 {
00293                         os << "<null>";
00294                 }
00295                 return os;
00296         }
00297 
00298         // TODO: this should be symmetrical to operator <<
00299         //       it needs to be able to take a string like A|B and
00300         //       return a value that represents A|B.
00301         template <typename T>
00302         std::istream& operator >> (std::istream& is, bitfield_base<T>& rhs)
00303         {
00304                 std::string str;
00305                 is >> str;
00306                 BOOST_DEDUCED_TYPENAME T::optional ret = T::get_by_name(str.c_str());
00307                 if(ret)
00308                         rhs = *ret;
00309                 else
00310                         is.setstate(std::ios::badbit);
00311                 return is;
00312         }
00313 
00314 } // detail
00315 } // boost
00316 
00317 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


telekyb_defines
Author(s): Dr. Antonio Franchi and Martin Riedel
autogenerated on Mon Nov 11 2013 11:12:30