//============================ // Project: Open Code Foundation Classes (OCFC) // Version: 1.0.0 // File: flags.hpp // Written by Nabla // Copyright @ 2007 Nabla. All rights reserved. //============================ // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #ifndef OCFCSENTRY_FLAGS_HPP # define OCFCSENTRY_FLAGS_HPP #include #include #include #include #include #include namespace ocfc { #define IS_FLAG(val, flag) (((val) & (flag)) == (flag)) #define SET_FLAG(val, flag) val |= (flag) #define UNSET_FLAG(val, flag) val &= ~(flag) #define IS_MASKED_FLAG(val, flag, mask) (((val) & (mask)) == (flag)) template class flags { public: typedef _E enum_type; typedef typename _E::enum_type c_enum_type; typedef typename _E::item_type item_type; typedef size_t size_type; class predicate { private: int __m_nFlags; public: explicit predicate(int __nFlags = 0) NO_THROW : __m_nFlags(__nFlags) {} inline ~predicate() NO_THROW {} bool operator()(item_type const& __e) { return IS_FLAG(__m_nFlags, __e.value()); } }; typedef boost::filter_iterator const_iterator; // the following is only needed for BOOST_FOREACH because you cannot normally modify any element of flags<> ! // but if I don't define it, I get an error message from boost::range typedef const_iterator iterator; private: int __m_nFlags; public: inline flags() NO_THROW : __m_nFlags(0) {} inline flags(const flags& __x) NO_THROW : __m_nFlags(__x.__m_nFlags) {} inline flags(const enum_type& __e) NO_THROW : __m_nFlags(__e.value()) {} inline flags(c_enum_type __e) NO_THROW : __m_nFlags(__e) {} inline flags(const string& __s) { value(__s); } inline flags(int __f) { value(__f); } inline ~flags() NO_THROW {} inline int value() const NO_THROW { return __m_nFlags; } inline void value(const enum_type& __e) NO_THROW { __m_nFlags = __e.value(); } inline void value(c_enum_type __e) NO_THROW { __m_nFlags = __e; } void value(int __nValue) { if (valid_int(__nValue)) __m_nFlags = __nValue; else { LOG_DEBUG(_T("fail to convert value ") << __nValue << _T(" to flags<") << typeid(enum_type).name() << _T('>')); THROW_RUNTIME_OUT_OF_RANGE_EXCEPTION(); } } void value(const string& __sValue) { if (!_cvt(__sValue, __m_nFlags)) { LOG_DEBUG(_T("fail to convert value ") << OS_SQUOTE(__sValue) << _T(" to flags<") << typeid(enum_type).name() << _T('>')); THROW_RUNTIME_OUT_OF_RANGE_EXCEPTION(); } } inline operator int () const NO_THROW { return value(); } inline int operator * () const NO_THROW { return value(); } inline bool operator ! () const NO_THROW { return __m_nFlags != 0; } inline flags& operator = (const flags& __x) NO_THROW { __m_nFlags = __x.__m_nFlags; return *this; } inline flags& operator = (const enum_type& __e) NO_THROW { value(__e); return *this; } inline flags& operator = (c_enum_type __e) NO_THROW { value(__e); return *this; } inline flags& operator = (const string& __s) { value(__s); return *this; } inline flags& operator = (int __f) { value(__f); return *this; } inline flags& operator |= (const flags& __x) NO_THROW { set(__x); return *this; } inline flags& operator |= (const enum_type& __e) NO_THROW { set(__e); return *this; } inline flags& operator |= (c_enum_type __e) NO_THROW { set(__e); return *this; } inline bool contains(const flags& __x) const NO_THROW { return IS_FLAG(__m_nFlags, __x.__m_nFlags); } inline bool contains(const enum_type& __e) const NO_THROW { return IS_FLAG(__m_nFlags, __e.value());; } inline bool contains(c_enum_type __e) const NO_THROW { return IS_FLAG(__m_nFlags, __e);; } inline void set(const flags& __x) NO_THROW { SET_FLAG(__m_nFlags, __x.__m_nFlags); } inline void set(const enum_type& __e) NO_THROW { SET_FLAG(__m_nFlags, __e.value()); } inline void set(c_enum_type __e) NO_THROW { SET_FLAG(__m_nFlags, __e); } inline void unset(const flags& __x) NO_THROW { UNSET_FLAG(__m_nFlags, __x.__m_nFlags); } inline void unset(const enum_type& __e) NO_THROW { UNSET_FLAG(__m_nFlags, __e.value()); } inline void unset(c_enum_type __e) NO_THROW { UNSET_FLAG(__m_nFlags, __e); } // OR inline flags operator | (const flags& __x) const NO_THROW { flags __tmp(*this); __tmp |= __x; return __tmp; } inline flags operator | (const enum_type& __e) const NO_THROW { flags __tmp(*this); __tmp |= __e; return __tmp; } inline flags operator | (c_enum_type __e) const NO_THROW { flags __tmp(*this); __tmp |= __e; return __tmp; } // AND inline int operator & (int __mask) const NO_THROW { return __m_nFlags & __mask; } inline int operator & (const flags& __x) const NO_THROW { return __m_nFlags & __x.__m_nFlags; } inline int operator & (const enum_type& __e) const NO_THROW { return __m_nFlags & __e.value(); } inline int operator & (c_enum_type __e) const NO_THROW { return __m_nFlags & __e; } // XOR inline int operator ^ (int __mask) const NO_THROW { return __m_nFlags ^ __mask; } inline int operator ^ (const flags& __x) const NO_THROW { return __m_nFlags ^ __x.__m_nFlags; } inline int operator ^ (const enum_type& __e) const NO_THROW { return __m_nFlags ^ __e.value(); } inline int operator ^ (c_enum_type __e) const NO_THROW { return __m_nFlags ^ __e; } // NEG inline int operator ~ () const NO_THROW { return ~__m_nFlags; } // list functions inline bool empty() const NO_THROW { return __m_nFlags == 0; } inline size_type size() const NO_THROW { return std::distance(begin(), end()); } inline const_iterator begin() const NO_THROW { return const_iterator(predicate(__m_nFlags), enum_type::begin()); } inline const_iterator end() const NO_THROW { return const_iterator(); } // checks static bool valid_int(int __nValue) NO_THROW { if (__nValue == 0) return true; for (typename enum_type::const_iterator __i = enum_type::begin(); __i != enum_type::end(); ++__i) { if (IS_FLAG(__nValue, __i->value())) UNSET_FLAG(__nValue, __i->value()); } return __nValue == 0; } static bool valid_string(const string& __sValue) NO_THROW { int __nFlags; return _cvt(__sValue, __nFlags); } // conversion string str() const { string __s; const_iterator __i = begin(); const_iterator __end = end(); if (__i != __end) { __s += __i->str(); for (++__i; __i != __end; ++__i) { __s += _T(" | "); __s += __i->str(); } } return __s; } // binary stream void load(ibstream& __in) { int __nFlags; __in >> __nFlags; // verify consistency of value if (!valid_int(__nFlags)) { LOG_DEBUG(_T("invalid flags<") << typeid(enum_type).name() << _T("> value read from stream")); THROW_CORRUPTED_STREAM_EXCEPTION(); } __m_nFlags = __nFlags; } inline void save(obstream& __out) const { __out << __m_nFlags; } protected: static bool _cvt(const string& __s, int& __nOut) { int __nFlags = 0; if (!boost::algorithm::trim_copy(__s).empty()) { tchar_separator __sep(_T("|")); tchar_tokenizer __tokens(__s, __sep); typename enum_type::const_iterator __end = enum_type::end(); for (tchar_tokenizer::const_iterator __t = __tokens.begin(); __t != __tokens.end(); ++__t) { string __sFlag = boost::algorithm::trim_copy(*__t); if (__sFlag.empty()) return false; typename enum_type::const_iterator __i = enum_type::begin(); while (__i != __end && t_strnocasecmp(__sFlag.c_str(), __i->str()) != 0) ++__i; if (__i == __end) return false; __nFlags |= __i->value(); } } __nOut = __nFlags; return true; } }; } // namespace ocfc #endif // OCFCSENTRY_FLAGS_HPP