// Debugging bitset implementation -*- C++ -*-

// Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
// Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library 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 3, or (at your option)
// any later version.

// This library 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.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file debug/bitset
 *  This file is a GNU debug extension to the Standard C++ Library.
 */

#ifndef _GLIBCXX_DEBUG_BITSET
#define _GLIBCXX_DEBUG_BITSET

#include <bitset>
#include <debug/safe_sequence.h>
#include <debug/safe_iterator.h>

namespace std
{
namespace __debug
{
  /// Class std::bitset with additional safety/checking/debug instrumentation.
  template<size_t _Nb>
    class bitset
    : public _GLIBCXX_STD_D::bitset<_Nb>, 
      public __gnu_debug::_Safe_sequence_base
    {
      typedef _GLIBCXX_STD_D::bitset<_Nb> _Base;
      typedef __gnu_debug::_Safe_sequence_base  _Safe_base;

    public:
      // bit reference:
      class reference
      : private _Base::reference, public __gnu_debug::_Safe_iterator_base
      {
	typedef typename _Base::reference _Base_ref;

	friend class bitset;
	reference();

	reference(const _Base_ref& __base, bitset* __seq)
	: _Base_ref(__base), _Safe_iterator_base(__seq, false)
	{ }

      public:
	reference(const reference& __x)
	: _Base_ref(__x), _Safe_iterator_base(__x, false)
	{ }

	reference&
	operator=(bool __x)
	{
	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
			      _M_message(__gnu_debug::__msg_bad_bitset_write)
				._M_iterator(*this));
	  *static_cast<_Base_ref*>(this) = __x;
	  return *this;
	}

	reference&
	operator=(const reference& __x)
	{
	  _GLIBCXX_DEBUG_VERIFY(! __x._M_singular(),
			       _M_message(__gnu_debug::__msg_bad_bitset_read)
				._M_iterator(__x));
	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
			      _M_message(__gnu_debug::__msg_bad_bitset_write)
				._M_iterator(*this));
	  *static_cast<_Base_ref*>(this) = __x;
	  return *this;
	}

	bool
	operator~() const
	{
	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
			       _M_message(__gnu_debug::__msg_bad_bitset_read)
				._M_iterator(*this));
	  return ~(*static_cast<const _Base_ref*>(this));
	}

	operator bool() const
	{
	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
			      _M_message(__gnu_debug::__msg_bad_bitset_read)
				._M_iterator(*this));
	  return *static_cast<const _Base_ref*>(this);
	}

	reference&
	flip()
	{
	  _GLIBCXX_DEBUG_VERIFY(! this->_M_singular(),
			      _M_message(__gnu_debug::__msg_bad_bitset_flip)
				._M_iterator(*this));
	  _Base_ref::flip();
	  return *this;
	}
      };

      // 23.3.5.1 constructors:
      bitset() : _Base() { }

#ifdef __GXX_EXPERIMENTAL_CXX0X__
      bitset(unsigned long long __val)
#else
      bitset(unsigned long __val)
#endif
      : _Base(__val) { }

      template<typename _CharT, typename _Traits, typename _Alloc>
        explicit
        bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
	       __pos = 0,
	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
	       __n = (std::basic_string<_CharT, _Traits, _Alloc>::npos))
	: _Base(__str, __pos, __n) { }

      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 396. what are characters zero and one.
      template<class _CharT, class _Traits, class _Alloc>
	bitset(const std::basic_string<_CharT, _Traits, _Alloc>& __str,
	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
	       __pos,
	       typename std::basic_string<_CharT, _Traits, _Alloc>::size_type
	       __n,
	       _CharT __zero, _CharT __one = _CharT('1'))
	: _Base(__str, __pos, __n, __zero, __one) { }

      bitset(const _Base& __x) : _Base(__x), _Safe_base() { }

#ifdef __GXX_EXPERIMENTAL_CXX0X__
      explicit
      bitset(const char* __str) : _Base(__str) { }
#endif

      // 23.3.5.2 bitset operations:
      bitset<_Nb>&
      operator&=(const bitset<_Nb>& __rhs)
      {
	_M_base() &= __rhs;
	return *this;
      }

      bitset<_Nb>&
      operator|=(const bitset<_Nb>& __rhs)
      {
	_M_base() |= __rhs;
	return *this;
      }

      bitset<_Nb>&
      operator^=(const bitset<_Nb>& __rhs)
      {
	_M_base() ^= __rhs;
	return *this;
      }

      bitset<_Nb>&
      operator<<=(size_t __pos)
      {
	_M_base() <<= __pos;
	return *this;
      }

      bitset<_Nb>&
      operator>>=(size_t __pos)
      {
	_M_base() >>= __pos;
	return *this;
      }

      bitset<_Nb>&
      set()
      {
	_Base::set();
	return *this;
      }

      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 186. bitset::set() second parameter should be bool
      bitset<_Nb>&
      set(size_t __pos, bool __val = true)
      {
	_Base::set(__pos, __val);
	return *this;
      }

      bitset<_Nb>&
      reset()
      {
	_Base::reset();
	return *this;
      }

      bitset<_Nb>&
      reset(size_t __pos)
      {
	_Base::reset(__pos);
	return *this;
      }

      bitset<_Nb> operator~() const { return bitset(~_M_base()); }

      bitset<_Nb>&
      flip()
      {
	_Base::flip();
	return *this;
      }

      bitset<_Nb>&
      flip(size_t __pos)
      {
	_Base::flip(__pos);
	return *this;
      }

      // element access:
      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 11. Bitset minor problems
      reference
      operator[](size_t __pos)
      {
	__glibcxx_check_subscript(__pos);
	return reference(_M_base()[__pos], this);
      }

      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 11. Bitset minor problems
      bool
      operator[](size_t __pos) const
      {
	__glibcxx_check_subscript(__pos);
	return _M_base()[__pos];
      }

      using _Base::to_ulong;
#ifdef __GXX_EXPERIMENTAL_CXX0X__
      using _Base::to_ullong;
#endif

      template <typename _CharT, typename _Traits, typename _Alloc>
        std::basic_string<_CharT, _Traits, _Alloc>
        to_string() const
        { return _M_base().template to_string<_CharT, _Traits, _Alloc>(); }

      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 396. what are characters zero and one.
      template<class _CharT, class _Traits, class _Alloc>
	std::basic_string<_CharT, _Traits, _Alloc>
	to_string(_CharT __zero, _CharT __one = _CharT('1')) const
	{
	  return _M_base().template
	    to_string<_CharT, _Traits, _Alloc>(__zero, __one);
	}

      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 434. bitset::to_string() hard to use.
      template<typename _CharT, typename _Traits>
        std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
        to_string() const
        { return to_string<_CharT, _Traits, std::allocator<_CharT> >(); }

      // _GLIBCXX_RESOLVE_LIB_DEFECTS
      // 853. to_string needs updating with zero and one.
      template<class _CharT, class _Traits>
	std::basic_string<_CharT, _Traits, std::allocator<_CharT> >
	to_string(_CharT __zero, _CharT __one = _CharT('1')) const
	{ return to_string<_CharT, _Traits,
	                   std::allocator<_CharT> >(__zero, __one); }

      template<typename _CharT>
        std::basic_string<_CharT, std::char_traits<_CharT>,
                          std::allocator<_CharT> >
        to_string() const
        {
          return to_string<_CharT, std::char_traits<_CharT>,
                           std::allocator<_CharT> >();
        }

      template<class _CharT>
	std::basic_string<_CharT, std::char_traits<_CharT>,
	                  std::allocator<_CharT> >
	to_string(_CharT __zero, _CharT __one = _CharT('1')) const
	{
	  return to_string<_CharT, std::char_traits<_CharT>,
	                   std::allocator<_CharT> >(__zero, __one);
	}

      std::basic_string<char, std::char_traits<char>, std::allocator<char> >
      to_string() const
      {
	return to_string<char,std::char_traits<char>,std::allocator<char> >();
      }

      std::basic_string<char, std::char_traits<char>, std::allocator<char> >
      to_string(char __zero, char __one = '1') const
      {
	return to_string<char, std::char_traits<char>,
	                 std::allocator<char> >(__zero, __one);
      }

      using _Base::count;
      using _Base::size;

      bool
      operator==(const bitset<_Nb>& __rhs) const
      { return _M_base() == __rhs; }

      bool
      operator!=(const bitset<_Nb>& __rhs) const
      { return _M_base() != __rhs; }

      using _Base::test;
      using _Base::all;
      using _Base::any;
      using _Base::none;

      bitset<_Nb>
      operator<<(size_t __pos) const
      { return bitset<_Nb>(_M_base() << __pos); }

      bitset<_Nb>
      operator>>(size_t __pos) const
      { return bitset<_Nb>(_M_base() >> __pos); }

      _Base&
      _M_base() { return *this; }

      const _Base&
      _M_base() const { return *this; }
    };

  template<size_t _Nb>
    bitset<_Nb>
    operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y)
    { return bitset<_Nb>(__x) &= __y; }

  template<size_t _Nb>
    bitset<_Nb>
    operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y)
    { return bitset<_Nb>(__x) |= __y; }

  template<size_t _Nb>
    bitset<_Nb>
    operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y)
    { return bitset<_Nb>(__x) ^= __y; }

  template<typename _CharT, typename _Traits, size_t _Nb>
    std::basic_istream<_CharT, _Traits>&
    operator>>(std::basic_istream<_CharT, _Traits>& __is, bitset<_Nb>& __x)
    { return __is >> __x._M_base(); }

  template<typename _CharT, typename _Traits, size_t _Nb>
    std::basic_ostream<_CharT, _Traits>&
    operator<<(std::basic_ostream<_CharT, _Traits>& __os,
	       const bitset<_Nb>& __x)
    { return __os << __x._M_base(); }

} // namespace __debug

#ifdef __GXX_EXPERIMENTAL_CXX0X__
  // DR 1182.
  /// std::hash specialization for bitset.
  template<size_t _Nb>
    struct hash<__debug::bitset<_Nb>>
    : public std::unary_function<__debug::bitset<_Nb>, size_t>
    {
      size_t
      operator()(const __debug::bitset<_Nb>& __b) const
      { return std::hash<_GLIBCXX_STD_D::bitset<_Nb>>()(__b._M_base()); }
    };
#endif

} // namespace std

#endif
