1 //  flags.hpp
2 //
3 //  Copyright (c) 2004 Eugene Gladyshev
4 //
5 //  Permission to copy, use, modify, sell and distribute this software
6 //  is granted provided this copyright notice appears in all copies.
7 //  This software is provided "as is" without express or implied
8 //  warranty, and with no claim as to its suitability for any purpose.
9 //
10 
11 #ifndef __ttl_flg_flags__hpp
12 #define __ttl_flg_flags__hpp
13 
14 #include <algorithm>
15 
16 namespace ttl
17 {
18 namespace flg
19 {
20 	namespace impl
21 	{
22 		template<
23 				int Bits,
24 				int type = Bits <= sizeof(char)*8?1:(Bits <= sizeof(short)*8?2:(Bits <= sizeof(int)*8?3:4))
25 			> struct bestfit;
26 
27 		template< int Bits >
28 		struct bestfit<Bits, 1>
29 		{
30 			typedef unsigned char type;
31 		};
32 
33 		template< int Bits >
34 		struct bestfit<Bits, 2>
35 		{
36 			typedef unsigned short type;
37 		};
38 
39 		template< int Bits >
40 		struct bestfit<Bits, 3>
41 		{
42 			typedef unsigned int type;
43 		};
44 
45 		template< int Bits >
46 		struct bestfit<Bits, 4>
47 		{
48 			typedef unsigned int type;
49 		};
50 	};
51 
52 	template< typename T, int Bits = sizeof(int)*8, typename Holder = typename impl::bestfit<Bits>::type >
53 	struct flags
54 	{
55 		typedef flags this_t;
56 		typedef T value_type;
57 
58 		Holder f_;
59 
flagsttl::flg::flags60 		flags() : f_(0) {}
flagsttl::flg::flags61 		flags( T f1 ) : f_(f1) {}
flagsttl::flg::flags62 		flags( T f1, T f2 ) : f_(f1|f2) {}
flagsttl::flg::flags63 		flags( T f1, T f2, T f3 ) : f_(f1|f2|f3) {}
flagsttl::flg::flags64 		flags( T f1, T f2, T f3, T f4 ) : f_(f1|f2|f3|f4) {}
flagsttl::flg::flags65 		flags( T f1, T f2, T f3, T f4, T f5 ) : f_(f1|f2|f3|f4|f5) {}
flagsttl::flg::flags66 		flags( T f1, T f2, T f3, T f4, T f5, T f6 ) : f_(f1|f2|f3|f4|f5|f6) {}
flagsttl::flg::flags67 		flags( T f1, T f2, T f3, T f4, T f5, T f6, T f7 ) : f_(f1|f2|f3|f4|f5|f6|f7) {}
flagsttl::flg::flags68 		flags( T f1, T f2, T f3, T f4, T f5, T f6, T f7, T f8 ) : f_(f1|f2|f3|f4|f5|f6|f7|f8) {}
flagsttl::flg::flags69 		flags( T f1, T f2, T f3, T f4, T f5, T f6, T f7, T f8, T f9 ) : f_(f1|f2|f3|f4|f5|f6|f7|f8|f9) {}
flagsttl::flg::flags70 		flags( T f1, T f2, T f3, T f4, T f5, T f6, T f7, T f8, T f9, T f10 ) : f_(f1|f2|f3|f4|f5|f6|f7|f8|f9|f10) {}
71 
operator |=ttl::flg::flags72 		this_t& operator |=( const this_t& f ) { f_ |= f.f_; return *this; }
operator &=ttl::flg::flags73 		this_t& operator &=( const this_t& f ) { f_ &= f.f_; return *this; }
74 
operator ==ttl::flg::flags75 		bool operator ==( const this_t& l ) const { return f_ == l.f_; }
operator !=ttl::flg::flags76 		bool operator !=( const this_t& l ) const { return f_ != l.f_; }
77 
operator !ttl::flg::flags78 		bool operator !() { return f_ == 0; }
79 
get_holderttl::flg::flags80 		Holder get_holder() const { return f_; }
81 
testttl::flg::flags82 		bool test( const this_t l ) const { return (f_ & l.f_)?true:false; }
testttl::flg::flags83 		bool test() const { return f_!=0; }
84 	};
85 
86 	template< typename T, int Bits, typename Holder >
operator ~(const flags<T,Bits,Holder> & l)87 	flags<T, Bits, Holder> operator ~(const flags<T, Bits, Holder>& l)
88 	{
89 		flags<T, Bits, Holder> tmp;
90 		tmp.f_ = ~l.f_;
91 		return tmp;
92 	}
93 
94 	template< typename T, int Bits, typename Holder >
operator |(const flags<T,Bits,Holder> & l,const T & r)95 	flags<T, Bits, Holder> operator |(const flags<T, Bits, Holder>& l, const T& r)
96 	{
97 		flags<T, Bits, Holder> tmp( r );
98 		return l|tmp;
99 	}
100 
101 	template< typename T, int Bits, typename Holder >
operator |(const flags<T,Bits,Holder> & l,const flags<T,Bits,Holder> & r)102 	flags<T, Bits, Holder> operator |(const flags<T, Bits, Holder>& l, const flags<T, Bits, Holder>& r)
103 	{
104 		flags<T, Bits, Holder> tmp( l );
105 		tmp|=r;
106 		return tmp;
107 	}
108 
109 	template< typename T, int Bits, typename Holder >
operator &(const flags<T,Bits,Holder> & l,const T & r)110 	flags<T, Bits, Holder> operator &(const flags<T, Bits, Holder>& l, const T& r)
111 	{
112 		flags<T, Bits, Holder> tmp( r );
113 		return l&tmp;
114 	}
115 
116 	template< typename T, int Bits, typename Holder >
operator &(const flags<T,Bits,Holder> & l,const flags<T,Bits,Holder> & r)117 	flags<T, Bits, Holder> operator &(const flags<T, Bits, Holder>& l, const flags<T, Bits, Holder>& r)
118 	{
119 		flags<T, Bits, Holder> tmp( l );
120 		tmp&=r;
121 		return tmp;
122 	}
123 
124 	struct map_first2second {};
125 	struct map_second2first {};
126 
127 	template < typename Pair, typename MapDirection = map_first2second >
128 	struct flag_mapper;
129 
130 	template< typename Pair >
131 	struct flag_mapper<Pair, map_first2second>
132 	{
133 		typedef typename Pair::first_type type;
134 		typedef typename Pair::second_type result_type;
135 
136 		const type& d_;
137 		result_type& r_;
138 
flag_mapperttl::flg::flag_mapper139 		flag_mapper( const type& d, result_type& r ) : d_(d), r_(r) {}
140 
operator ()ttl::flg::flag_mapper141 		void operator()( const Pair& p ) const
142 		{
143 			if( (p.first&d_) == true ) r_ |= p.second;
144 		}
145 	};
146 
147 	template< typename Pair >
148 	struct flag_mapper<Pair, map_second2first>
149 	{
150 		typedef typename Pair::second_type type;
151 		typedef typename Pair::first_type result_type;
152 
153 		const type& d_;
154 		result_type r_;
155 
flag_mapperttl::flg::flag_mapper156 		flag_mapper( const type& d ) : d_(d), r_() {}
157 
operator ()ttl::flg::flag_mapper158 		void operator()( const Pair& p ) const
159 		{
160 			if( (p.second&d_) == true ) r_ |= p.first;
161 		}
162 	};
163 
164 	//It is a an iterator of elements like std::pair
165 	template< typename It >
map(const typename It::value_type::first_type f,It first,It end)166 	typename It::value_type::second_type map(
167 		const typename It::value_type::first_type f,
168 		It first, It end )
169 	{
170 		typename It::value_type::second_type r;
171 		flag_mapper<typename It::value_type> m(f, r);
172 		std::for_each( first, end, m );
173 		return r;
174 	}
175 
176 };	//flg
177 };
178 
179 #endif //__flags__hpp
180 
181