1// Debugging bitset implementation -*- C++ -*-
2
3// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
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 _GLIBCXX_VISIBILITY(default)
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_C::bitset<_Nb>
45#ifndef __GXX_EXPERIMENTAL_CXX0X__
46    , public __gnu_debug::_Safe_sequence_base
47#endif
48    {
49      typedef _GLIBCXX_STD_C::bitset<_Nb> _Base;
50
51    public:
52      // In C++0x we rely on normal reference type to preserve the property
53      // of bitset to be use as a literal.
54      // TODO: Find another solution.
55#ifdef __GXX_EXPERIMENTAL_CXX0X__
56      typedef typename _Base::reference reference;
57#else
58      // bit reference:
59      class reference
60      : private _Base::reference
61        , public __gnu_debug::_Safe_iterator_base
62      {
63	typedef typename _Base::reference _Base_ref;
64
65	friend class bitset;
66	reference();
67
68	reference(const _Base_ref& __base,
69		  bitset* __seq __attribute__((__unused__))) _GLIBCXX_NOEXCEPT
70	: _Base_ref(__base)
71	, _Safe_iterator_base(__seq, false)
72	{ }
73
74      public:
75	reference(const reference& __x) _GLIBCXX_NOEXCEPT
76	: _Base_ref(__x)
77	, _Safe_iterator_base(__x, false)
78	{ }
79
80	reference&
81	operator=(bool __x) _GLIBCXX_NOEXCEPT
82	{
83	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
84			      _M_message(__gnu_debug::__msg_bad_bitset_write)
85				._M_iterator(*this));
86	  *static_cast<_Base_ref*>(this) = __x;
87	  return *this;
88	}
89
90	reference&
91	operator=(const reference& __x) _GLIBCXX_NOEXCEPT
92	{
93	  _GLIBCXX_DEBUG_VERIFY(! __x._M_singular(),
94			       _M_message(__gnu_debug::__msg_bad_bitset_read)
95				._M_iterator(__x));
96	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
97			      _M_message(__gnu_debug::__msg_bad_bitset_write)
98				._M_iterator(*this));
99	  *static_cast<_Base_ref*>(this) = __x;
100	  return *this;
101	}
102
103	bool
104	operator~() const _GLIBCXX_NOEXCEPT
105	{
106	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
107			       _M_message(__gnu_debug::__msg_bad_bitset_read)
108				._M_iterator(*this));
109	  return ~(*static_cast<const _Base_ref*>(this));
110	}
111
112	operator bool() const _GLIBCXX_NOEXCEPT
113	{
114	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
115			      _M_message(__gnu_debug::__msg_bad_bitset_read)
116				._M_iterator(*this));
117	  return *static_cast<const _Base_ref*>(this);
118	}
119
120	reference&
121	flip() _GLIBCXX_NOEXCEPT
122	{
123	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
124			      _M_message(__gnu_debug::__msg_bad_bitset_flip)
125				._M_iterator(*this));
126	  _Base_ref::flip();
127	  return *this;
128	}
129      };
130#endif
131
132      // 23.3.5.1 constructors:
133      _GLIBCXX_CONSTEXPR bitset() _GLIBCXX_NOEXCEPT
134      : _Base() { }
135
136#ifdef __GXX_EXPERIMENTAL_CXX0X__
137      constexpr bitset(unsigned long long __val) noexcept
138#else
139      bitset(unsigned long __val)
140#endif
141      : _Base(__val) { }
142
143      template<typename _CharT, typename _Traits, typename _Alloc>
144        explicit
145        bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
146	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
147	       __pos = 0,
148	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
149	       __n = (std::basic_string<_CharT, _Traits, _Alloc>::npos))
150	: _Base(__str, __pos, __n) { }
151
152      // _GLIBCXX_RESOLVE_LIB_DEFECTS
153      // 396. what are characters zero and one.
154      template<class _CharT, class _Traits, class _Alloc>
155	bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
156	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
157	       __pos,
158	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
159	       __n,
160	       _CharT __zero, _CharT __one = _CharT('1'))
161	: _Base(__str, __pos, __n, __zero, __one) { }
162
163      bitset(const _Base& __x) : _Base(__x) { }
164
165#ifdef __GXX_EXPERIMENTAL_CXX0X__
166      template<typename _CharT>
167        explicit
168        bitset(const _CharT* __str,
169	       typename std::basic_string<_CharT>::size_type __n
170	       = std::basic_string<_CharT>::npos,
171	       _CharT __zero = _CharT('0'), _CharT __one = _CharT('1'))
172	: _Base(__str, __n, __zero, __one) { }
173#endif
174
175      // 23.3.5.2 bitset operations:
176      bitset<_Nb>&
177      operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
178      {
179	_M_base() &= __rhs;
180	return *this;
181      }
182
183      bitset<_Nb>&
184      operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
185      {
186	_M_base() |= __rhs;
187	return *this;
188      }
189
190      bitset<_Nb>&
191      operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT
192      {
193	_M_base() ^= __rhs;
194	return *this;
195      }
196
197      bitset<_Nb>&
198      operator<<=(size_t __pos) _GLIBCXX_NOEXCEPT
199      {
200	_M_base() <<= __pos;
201	return *this;
202      }
203
204      bitset<_Nb>&
205      operator>>=(size_t __pos) _GLIBCXX_NOEXCEPT
206      {
207	_M_base() >>= __pos;
208	return *this;
209      }
210
211      bitset<_Nb>&
212      set() _GLIBCXX_NOEXCEPT
213      {
214	_Base::set();
215	return *this;
216      }
217
218      // _GLIBCXX_RESOLVE_LIB_DEFECTS
219      // 186. bitset::set() second parameter should be bool
220      bitset<_Nb>&
221      set(size_t __pos, bool __val = true)
222      {
223	_Base::set(__pos, __val);
224	return *this;
225      }
226
227      bitset<_Nb>&
228      reset() _GLIBCXX_NOEXCEPT
229      {
230	_Base::reset();
231	return *this;
232      }
233
234      bitset<_Nb>&
235      reset(size_t __pos)
236      {
237	_Base::reset(__pos);
238	return *this;
239      }
240
241      bitset<_Nb>
242      operator~() const _GLIBCXX_NOEXCEPT
243      { return bitset(~_M_base()); }
244
245      bitset<_Nb>&
246      flip() _GLIBCXX_NOEXCEPT
247      {
248	_Base::flip();
249	return *this;
250      }
251
252      bitset<_Nb>&
253      flip(size_t __pos)
254      {
255	_Base::flip(__pos);
256	return *this;
257      }
258
259      // element access:
260      // _GLIBCXX_RESOLVE_LIB_DEFECTS
261      // 11. Bitset minor problems
262      reference
263      operator[](size_t __pos)
264      {
265	__glibcxx_check_subscript(__pos);
266#ifdef __GXX_EXPERIMENTAL_CXX0X__
267	return _M_base()[__pos];
268#else
269	return reference(_M_base()[__pos], this);
270#endif
271      }
272
273      // _GLIBCXX_RESOLVE_LIB_DEFECTS
274      // 11. Bitset minor problems
275      _GLIBCXX_CONSTEXPR bool
276      operator[](size_t __pos) const
277      {
278#ifndef __GXX_EXPERIMENTAL_CXX0X__
279	// TODO: Check in debug-mode too.
280	__glibcxx_check_subscript(__pos);
281#endif
282	return _Base::operator[](__pos);
283      }
284
285      using _Base::to_ulong;
286#ifdef __GXX_EXPERIMENTAL_CXX0X__
287      using _Base::to_ullong;
288#endif
289
290      template <typename _CharT, typename _Traits, typename _Alloc>
291        std::basic_string<_CharT, _Traits, _Alloc>
292        to_string() const
293        { return _M_base().template to_string<_CharT, _Traits, _Alloc>(); }
294
295      // _GLIBCXX_RESOLVE_LIB_DEFECTS
296      // 396. what are characters zero and one.
297      template<class _CharT, class _Traits, class _Alloc>
298	std::basic_string<_CharT, _Traits, _Alloc>
299	to_string(_CharT __zero, _CharT __one = _CharT('1')) const
300	{
301	  return _M_base().template
302	    to_string<_CharT, _Traits, _Alloc>(__zero, __one);
303	}
304
305      // _GLIBCXX_RESOLVE_LIB_DEFECTS
306      // 434. bitset::to_string() hard to use.
307      template<typename _CharT, typename _Traits>
308        std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
309        to_string() const
310        { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); }
311
312      // _GLIBCXX_RESOLVE_LIB_DEFECTS
313      // 853. to_string needs updating with zero and one.
314      template<class _CharT, class _Traits>
315	std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
316	to_string(_CharT __zero, _CharT __one = _CharT('1')) const
317	{ return to_string<_CharT, _Traits,
318	                   std::allocator<_CharT> >(__zero, __one); }
319
320      template<typename _CharT>
321        std::basic_string<_CharT, std::char_traits<_CharT>,
322                          std::allocator<_CharT> >
323        to_string() const
324        {
325          return to_string<_CharT, std::char_traits<_CharT>,
326                           std::allocator<_CharT> >();
327        }
328
329      template<class _CharT>
330	std::basic_string<_CharT, std::char_traits<_CharT>,
331	                  std::allocator<_CharT> >
332	to_string(_CharT __zero, _CharT __one = _CharT('1')) const
333	{
334	  return to_string<_CharT, std::char_traits<_CharT>,
335	                   std::allocator<_CharT> >(__zero, __one);
336	}
337
338      std::basic_string<char, std::char_traits<char>, std::allocator<char> >
339      to_string() const
340      {
341	return to_string<char,std::char_traits<char>,std::allocator<char> >();
342      }
343
344      std::basic_string<char, std::char_traits<char>, std::allocator<char> >
345      to_string(char __zero, char __one = '1') const
346      {
347	return to_string<char, std::char_traits<char>,
348	                 std::allocator<char> >(__zero, __one);
349      }
350
351      using _Base::count;
352      using _Base::size;
353
354      bool
355      operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
356      { return _M_base() == __rhs; }
357
358      bool
359      operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT
360      { return _M_base() != __rhs; }
361
362      using _Base::test;
363      using _Base::all;
364      using _Base::any;
365      using _Base::none;
366
367      bitset<_Nb>
368      operator<<(size_t __pos) const _GLIBCXX_NOEXCEPT
369      { return bitset<_Nb>(_M_base() << __pos); }
370
371      bitset<_Nb>
372      operator>>(size_t __pos) const _GLIBCXX_NOEXCEPT
373      { return bitset<_Nb>(_M_base() >> __pos); }
374
375      _Base&
376      _M_base() _GLIBCXX_NOEXCEPT
377      { return *this; }
378
379      const _Base&
380      _M_base() const _GLIBCXX_NOEXCEPT
381      { return *this; }
382    };
383
384  template<size_t _Nb>
385    bitset<_Nb>
386    operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
387    { return bitset<_Nb>(__x) &= __y; }
388
389  template<size_t _Nb>
390    bitset<_Nb>
391    operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
392    { return bitset<_Nb>(__x) |= __y; }
393
394  template<size_t _Nb>
395    bitset<_Nb>
396    operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT
397    { return bitset<_Nb>(__x) ^= __y; }
398
399  template<typename _CharT, typename _Traits, size_t _Nb>
400    std::basic_istream<_CharT, _Traits>&
401    operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x)
402    { return __is >> __x._M_base(); }
403
404  template<typename _CharT, typename _Traits, size_t _Nb>
405    std::basic_ostream<_CharT, _Traits>&
406    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
407	       const bitset<_Nb>& __x)
408    { return __os << __x._M_base(); }
409
410} // namespace __debug
411
412#ifdef __GXX_EXPERIMENTAL_CXX0X__
413  // DR 1182.
414  /// std::hash specialization for bitset.
415  template<size_t _Nb>
416    struct hash<__debug::bitset<_Nb>>
417    : public __hash_base<size_t, __debug::bitset<_Nb>>
418    {
419      size_t
420      operator()(const __debug::bitset<_Nb>& __b) const noexcept
421      { return std::hash<_GLIBCXX_STD_C::bitset<_Nb>>()(__b._M_base()); }
422    };
423#endif
424
425} // namespace std
426
427#endif
428