1// Debugging bitset implementation -*- C++ -*-
2
3// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
4// Free Software Foundation, Inc.
5//
6// This file is part of the GNU ISO C++ Library.  This library is free
7// software; you can redistribute it and/or modify it under the
8// terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 3, or (at your option)
10// any later version.
11
12// This library is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15// GNU General Public License for more details.
16
17// Under Section 7 of GPL version 3, you are granted additional
18// permissions described in the GCC Runtime Library Exception, version
19// 3.1, as published by the Free Software Foundation.
20
21// You should have received a copy of the GNU General Public License and
22// a copy of the GCC Runtime Library Exception along with this program;
23// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24// <http://www.gnu.org/licenses/>.
25
26/** @file debug/bitset
27 *  This file is a GNU debug extension to the Standard C++ Library.
28 */
29
30#ifndef _GLIBCXX_DEBUG_BITSET
31#define _GLIBCXX_DEBUG_BITSET
32
33#include <bitset>
34#include <debug/safe_sequence.h>
35#include <debug/safe_iterator.h>
36
37namespace std
38{
39namespace __debug
40{
41  /// Class std::bitset with additional safety/checking/debug instrumentation.
42  template<size_t _Nb>
43    class bitset
44    : public _GLIBCXX_STD_D::bitset<_Nb>, 
45      public __gnu_debug::_Safe_sequence_base
46    {
47      typedef _GLIBCXX_STD_D::bitset<_Nb> _Base;
48      typedef __gnu_debug::_Safe_sequence_base  _Safe_base;
49
50    public:
51      // bit reference:
52      class reference
53      : private _Base::reference, public __gnu_debug::_Safe_iterator_base
54      {
55	typedef typename _Base::reference _Base_ref;
56
57	friend class bitset;
58	reference();
59
60	reference(const _Base_ref& __base, bitset* __seq)
61	: _Base_ref(__base), _Safe_iterator_base(__seq, false)
62	{ }
63
64      public:
65	reference(const reference& __x)
66	: _Base_ref(__x), _Safe_iterator_base(__x, false)
67	{ }
68
69	reference&
70	operator=(bool __x)
71	{
72	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
73			      _M_message(__gnu_debug::__msg_bad_bitset_write)
74				._M_iterator(*this));
75	  *static_cast<_Base_ref*>(this) = __x;
76	  return *this;
77	}
78
79	reference&
80	operator=(const reference& __x)
81	{
82	  _GLIBCXX_DEBUG_VERIFY(! __x._M_singular(),
83			       _M_message(__gnu_debug::__msg_bad_bitset_read)
84				._M_iterator(__x));
85	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
86			      _M_message(__gnu_debug::__msg_bad_bitset_write)
87				._M_iterator(*this));
88	  *static_cast<_Base_ref*>(this) = __x;
89	  return *this;
90	}
91
92	bool
93	operator~() const
94	{
95	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
96			       _M_message(__gnu_debug::__msg_bad_bitset_read)
97				._M_iterator(*this));
98	  return ~(*static_cast<const _Base_ref*>(this));
99	}
100
101	operator bool() const
102	{
103	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
104			      _M_message(__gnu_debug::__msg_bad_bitset_read)
105				._M_iterator(*this));
106	  return *static_cast<const _Base_ref*>(this);
107	}
108
109	reference&
110	flip()
111	{
112	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
113			      _M_message(__gnu_debug::__msg_bad_bitset_flip)
114				._M_iterator(*this));
115	  _Base_ref::flip();
116	  return *this;
117	}
118      };
119
120      // 23.3.5.1 constructors:
121      bitset() : _Base() { }
122
123#ifdef __GXX_EXPERIMENTAL_CXX0X__
124      bitset(unsigned long long __val)
125#else
126      bitset(unsigned long __val)
127#endif
128      : _Base(__val) { }
129
130      template<typename _CharT, typename _Traits, typename _Alloc>
131        explicit
132        bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
133	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
134	       __pos = 0,
135	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
136	       __n = (std::basic_string<_CharT, _Traits, _Alloc>::npos))
137	: _Base(__str, __pos, __n) { }
138
139      // _GLIBCXX_RESOLVE_LIB_DEFECTS
140      // 396. what are characters zero and one.
141      template<class _CharT, class _Traits, class _Alloc>
142	bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
143	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
144	       __pos,
145	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
146	       __n,
147	       _CharT __zero, _CharT __one = _CharT('1'))
148	: _Base(__str, __pos, __n, __zero, __one) { }
149
150      bitset(const _Base& __x) : _Base(__x), _Safe_base() { }
151
152#ifdef __GXX_EXPERIMENTAL_CXX0X__
153      explicit
154      bitset(const char* __str) : _Base(__str) { }
155#endif
156
157      // 23.3.5.2 bitset operations:
158      bitset<_Nb>&
159      operator&=(const bitset<_Nb>& __rhs)
160      {
161	_M_base() &= __rhs;
162	return *this;
163      }
164
165      bitset<_Nb>&
166      operator|=(const bitset<_Nb>& __rhs)
167      {
168	_M_base() |= __rhs;
169	return *this;
170      }
171
172      bitset<_Nb>&
173      operator^=(const bitset<_Nb>& __rhs)
174      {
175	_M_base() ^= __rhs;
176	return *this;
177      }
178
179      bitset<_Nb>&
180      operator<<=(size_t __pos)
181      {
182	_M_base() <<= __pos;
183	return *this;
184      }
185
186      bitset<_Nb>&
187      operator>>=(size_t __pos)
188      {
189	_M_base() >>= __pos;
190	return *this;
191      }
192
193      bitset<_Nb>&
194      set()
195      {
196	_Base::set();
197	return *this;
198      }
199
200      // _GLIBCXX_RESOLVE_LIB_DEFECTS
201      // 186. bitset::set() second parameter should be bool
202      bitset<_Nb>&
203      set(size_t __pos, bool __val = true)
204      {
205	_Base::set(__pos, __val);
206	return *this;
207      }
208
209      bitset<_Nb>&
210      reset()
211      {
212	_Base::reset();
213	return *this;
214      }
215
216      bitset<_Nb>&
217      reset(size_t __pos)
218      {
219	_Base::reset(__pos);
220	return *this;
221      }
222
223      bitset<_Nb> operator~() const { return bitset(~_M_base()); }
224
225      bitset<_Nb>&
226      flip()
227      {
228	_Base::flip();
229	return *this;
230      }
231
232      bitset<_Nb>&
233      flip(size_t __pos)
234      {
235	_Base::flip(__pos);
236	return *this;
237      }
238
239      // element access:
240      // _GLIBCXX_RESOLVE_LIB_DEFECTS
241      // 11. Bitset minor problems
242      reference
243      operator[](size_t __pos)
244      {
245	__glibcxx_check_subscript(__pos);
246	return reference(_M_base()[__pos], this);
247      }
248
249      // _GLIBCXX_RESOLVE_LIB_DEFECTS
250      // 11. Bitset minor problems
251      bool
252      operator[](size_t __pos) const
253      {
254	__glibcxx_check_subscript(__pos);
255	return _M_base()[__pos];
256      }
257
258      using _Base::to_ulong;
259#ifdef __GXX_EXPERIMENTAL_CXX0X__
260      using _Base::to_ullong;
261#endif
262
263      template <typename _CharT, typename _Traits, typename _Alloc>
264        std::basic_string<_CharT, _Traits, _Alloc>
265        to_string() const
266        { return _M_base().template to_string<_CharT, _Traits, _Alloc>(); }
267
268      // _GLIBCXX_RESOLVE_LIB_DEFECTS
269      // 396. what are characters zero and one.
270      template<class _CharT, class _Traits, class _Alloc>
271	std::basic_string<_CharT, _Traits, _Alloc>
272	to_string(_CharT __zero, _CharT __one = _CharT('1')) const
273	{
274	  return _M_base().template
275	    to_string<_CharT, _Traits, _Alloc>(__zero, __one);
276	}
277
278      // _GLIBCXX_RESOLVE_LIB_DEFECTS
279      // 434. bitset::to_string() hard to use.
280      template<typename _CharT, typename _Traits>
281        std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
282        to_string() const
283        { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); }
284
285      // _GLIBCXX_RESOLVE_LIB_DEFECTS
286      // 853. to_string needs updating with zero and one.
287      template<class _CharT, class _Traits>
288	std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
289	to_string(_CharT __zero, _CharT __one = _CharT('1')) const
290	{ return to_string<_CharT, _Traits,
291	                   std::allocator<_CharT> >(__zero, __one); }
292
293      template<typename _CharT>
294        std::basic_string<_CharT, std::char_traits<_CharT>,
295                          std::allocator<_CharT> >
296        to_string() const
297        {
298          return to_string<_CharT, std::char_traits<_CharT>,
299                           std::allocator<_CharT> >();
300        }
301
302      template<class _CharT>
303	std::basic_string<_CharT, std::char_traits<_CharT>,
304	                  std::allocator<_CharT> >
305	to_string(_CharT __zero, _CharT __one = _CharT('1')) const
306	{
307	  return to_string<_CharT, std::char_traits<_CharT>,
308	                   std::allocator<_CharT> >(__zero, __one);
309	}
310
311      std::basic_string<char, std::char_traits<char>, std::allocator<char> >
312      to_string() const
313      {
314	return to_string<char,std::char_traits<char>,std::allocator<char> >();
315      }
316
317      std::basic_string<char, std::char_traits<char>, std::allocator<char> >
318      to_string(char __zero, char __one = '1') const
319      {
320	return to_string<char, std::char_traits<char>,
321	                 std::allocator<char> >(__zero, __one);
322      }
323
324      using _Base::count;
325      using _Base::size;
326
327      bool
328      operator==(const bitset<_Nb>& __rhs) const
329      { return _M_base() == __rhs; }
330
331      bool
332      operator!=(const bitset<_Nb>& __rhs) const
333      { return _M_base() != __rhs; }
334
335      using _Base::test;
336      using _Base::all;
337      using _Base::any;
338      using _Base::none;
339
340      bitset<_Nb>
341      operator<<(size_t __pos) const
342      { return bitset<_Nb>(_M_base() << __pos); }
343
344      bitset<_Nb>
345      operator>>(size_t __pos) const
346      { return bitset<_Nb>(_M_base() >> __pos); }
347
348      _Base&
349      _M_base() { return *this; }
350
351      const _Base&
352      _M_base() const { return *this; }
353    };
354
355  template<size_t _Nb>
356    bitset<_Nb>
357    operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y)
358    { return bitset<_Nb>(__x) &= __y; }
359
360  template<size_t _Nb>
361    bitset<_Nb>
362    operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y)
363    { return bitset<_Nb>(__x) |= __y; }
364
365  template<size_t _Nb>
366    bitset<_Nb>
367    operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y)
368    { return bitset<_Nb>(__x) ^= __y; }
369
370  template<typename _CharT, typename _Traits, size_t _Nb>
371    std::basic_istream<_CharT, _Traits>&
372    operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x)
373    { return __is >> __x._M_base(); }
374
375  template<typename _CharT, typename _Traits, size_t _Nb>
376    std::basic_ostream<_CharT, _Traits>&
377    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
378	       const bitset<_Nb>& __x)
379    { return __os << __x._M_base(); }
380
381} // namespace __debug
382
383#ifdef __GXX_EXPERIMENTAL_CXX0X__
384  // DR 1182.
385  /// std::hash specialization for bitset.
386  template<size_t _Nb>
387    struct hash<__debug::bitset<_Nb>>
388    : public std::unary_function<__debug::bitset<_Nb>, size_t>
389    {
390      size_t
391      operator()(const __debug::bitset<_Nb>& __b) const
392      { return std::hash<_GLIBCXX_STD_D::bitset<_Nb>>()(__b._M_base()); }
393    };
394#endif
395
396} // namespace std
397
398#endif
399