Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #ifndef BOOST_ENUM_BITFIELD_HPP
00011 #define BOOST_ENUM_BITFIELD_HPP
00012
00013
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
00025
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
00037
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
00069 bitfield_access();
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
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
00209 size_t count() const
00210 {
00211 return 0;
00212 }
00213
00214
00215 bool any() const
00216 {
00217 return false;
00218 }
00219
00220
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
00254
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
00299
00300
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 }
00315 }
00316
00317 #endif