_bitset.h

来自「stl的源码」· C头文件 代码 · 共 881 行 · 第 1/2 页

H
881
字号
/* * Copyright (c) 1998 * Silicon Graphics Computer Systems, Inc. * * Copyright (c) 1999 * Boris Fomitchev * * This material is provided "as is", with absolutely no warranty expressed * or implied. Any use is at your own risk. * * Permission to use or copy this software for any purpose is hereby granted * without fee, provided the above notices are retained on all copies. * Permission to modify the code and to distribute modified code is granted, * provided the above notices are retained, and a notice that the code was * modified is included with the above copyright notice. * */#ifndef _STLP_BITSET_H#define _STLP_BITSET_H// A bitset of size N has N % (sizeof(unsigned long) * CHAR_BIT) unused// bits.  (They are the high- order bits in the highest word.)  It is// a class invariant of class bitset<> that those unused bits are// always zero.// Most of the actual code isn't contained in bitset<> itself, but in the// base class _Base_bitset.  The base class works with whole words, not with// individual bits.  This allows us to specialize _Base_bitset for the// important special case where the bitset is only a single word.// The C++ standard does not define the precise semantics of operator[].// In this implementation the const version of operator[] is equivalent// to test(), except that it does no range checking.  The non-const version// returns a reference to a bit, again without doing any range checking.#ifndef _STLP_INTERNAL_ALGOBASE_H#  include <stl/_algobase.h>#endif#ifndef _STLP_INTERNAL_ALLOC_H#  include <stl/_alloc.h>#endif#ifndef _STLP_INTERNAL_ITERATOR_H#  include <stl/_iterator.h>#endif#ifndef _STLP_INTERNAL_UNINITIALIZED_H#  include <stl/_uninitialized.h>#endif#ifndef _STLP_RANGE_ERRORS_H#  include <stl/_range_errors.h>#endif#ifndef _STLP_INTERNAL_STRING_H#  include <stl/_string.h>#endif#define __BITS_PER_WORD (CHAR_BIT*sizeof(unsigned long))#define __BITSET_WORDS(__n) ((__n + __BITS_PER_WORD - 1)/__BITS_PER_WORD)_STLP_BEGIN_NAMESPACE_STLP_MOVE_TO_PRIV_NAMESPACE// structure to aid in counting bitsclass _STLP_CLASS_DECLSPEC _Bs_G{  public:    //returns the number of bit set within the buffer between __beg and __end.    static size_t _S_count(const unsigned char *__beg, const unsigned char *__end)#if defined (_STLP_USE_NO_IOSTREAMS)    {      size_t __result = 0;      for (; __beg != __end; ++__beg) {        for (size_t i = 0; i < (sizeof(unsigned char) * 8); ++i) {          if ((*__beg & (1 << i)) != 0) { ++__result; }        }      }      return __result;    }#else      ;#endif    // Mapping from 8 bit unsigned integers to the index of the first one bit set:    static unsigned char _S_first_one(unsigned char __x)#if defined (_STLP_USE_NO_IOSTREAMS)    {      for (unsigned char i = 0; i < (sizeof(unsigned char) * 8); ++i) {        if ((__x & (1 << i)) != 0) { return i; }      }      return 0;    }#else      ;#endif};//// Base class: general case.//template<size_t _Nw>struct _Base_bitset {  typedef unsigned long _WordT;  _WordT _M_w[_Nw];                // 0 is the least significant word.  _Base_bitset() { _M_do_reset(); }  _Base_bitset(unsigned long __val) {    _M_do_reset();    _M_w[0] = __val;  }  static size_t _STLP_CALL _S_whichword( size_t __pos ) {    return __pos / __BITS_PER_WORD;  }  static size_t _STLP_CALL _S_whichbyte( size_t __pos ) {    return (__pos % __BITS_PER_WORD) / CHAR_BIT;  }  static size_t _STLP_CALL _S_whichbit( size_t __pos ) {    return __pos % __BITS_PER_WORD;  }  static _WordT _STLP_CALL _S_maskbit( size_t __pos ) {    return __STATIC_CAST(_WordT,1) << _S_whichbit(__pos);  }  _WordT& _M_getword(size_t __pos)       { return _M_w[_S_whichword(__pos)]; }  _WordT  _M_getword(size_t __pos) const { return _M_w[_S_whichword(__pos)]; }  _WordT& _M_hiword()       { return _M_w[_Nw - 1]; }  _WordT  _M_hiword() const { return _M_w[_Nw - 1]; }  void _M_do_and(const _Base_bitset<_Nw>& __x) {    for ( size_t __i = 0; __i < _Nw; __i++ ) {      _M_w[__i] &= __x._M_w[__i];    }  }  void _M_do_or(const _Base_bitset<_Nw>& __x) {    for ( size_t __i = 0; __i < _Nw; __i++ ) {      _M_w[__i] |= __x._M_w[__i];    }  }  void _M_do_xor(const _Base_bitset<_Nw>& __x) {    for ( size_t __i = 0; __i < _Nw; __i++ ) {      _M_w[__i] ^= __x._M_w[__i];    }  }  void _M_do_left_shift(size_t __shift);  void _M_do_right_shift(size_t __shift);  void _M_do_flip() {    for ( size_t __i = 0; __i < _Nw; __i++ ) {      _M_w[__i] = ~_M_w[__i];    }  }  void _M_do_set() {    for ( size_t __i = 0; __i < _Nw; __i++ ) {      _M_w[__i] = ~__STATIC_CAST(_WordT,0);    }  }  void _M_do_reset() { memset(_M_w, 0, _Nw * sizeof(_WordT)); }  bool _M_is_equal(const _Base_bitset<_Nw>& __x) const {    for (size_t __i = 0; __i < _Nw; ++__i) {      if (_M_w[__i] != __x._M_w[__i])        return false;    }    return true;  }  bool _M_is_any() const {    for ( size_t __i = 0; __i < _Nw ; __i++ ) {      if ( _M_w[__i] != __STATIC_CAST(_WordT,0) )        return true;    }    return false;  }  size_t _M_do_count() const {    const unsigned char* __byte_ptr = (const unsigned char*)_M_w;    const unsigned char* __end_ptr = (const unsigned char*)(_M_w+_Nw);    return _Bs_G::_S_count(__byte_ptr, __end_ptr);  }  unsigned long _M_do_to_ulong() const;  // find first "on" bit  size_t _M_do_find_first(size_t __not_found) const;  // find the next "on" bit that follows "prev"  size_t _M_do_find_next(size_t __prev, size_t __not_found) const;};//// Base class: specialization for a single word.//_STLP_TEMPLATE_NULLstruct _Base_bitset<1UL> {  typedef unsigned long _WordT;  typedef _Base_bitset<1UL> _Self;  _WordT _M_w;  _Base_bitset( void ) : _M_w(0) {}  _Base_bitset(unsigned long __val) : _M_w(__val) {}  static size_t _STLP_CALL _S_whichword( size_t __pos ) {    return __pos / __BITS_PER_WORD ;  }  static size_t _STLP_CALL _S_whichbyte( size_t __pos ) {    return (__pos % __BITS_PER_WORD) / CHAR_BIT;  }  static size_t _STLP_CALL _S_whichbit( size_t __pos ) {    return __pos % __BITS_PER_WORD;  }  static _WordT _STLP_CALL _S_maskbit( size_t __pos ) {    return (__STATIC_CAST(_WordT,1)) << _S_whichbit(__pos);  }  _WordT& _M_getword(size_t)       { return _M_w; }  _WordT  _M_getword(size_t) const { return _M_w; }  _WordT& _M_hiword()       { return _M_w; }  _WordT  _M_hiword() const { return _M_w; }  void _M_do_and(const _Self& __x) { _M_w &= __x._M_w; }  void _M_do_or(const _Self& __x)  { _M_w |= __x._M_w; }  void _M_do_xor(const _Self& __x) { _M_w ^= __x._M_w; }  void _M_do_left_shift(size_t __shift)     { _M_w <<= __shift; }  void _M_do_right_shift(size_t __shift)    { _M_w >>= __shift; }  void _M_do_flip()                       { _M_w = ~_M_w; }  void _M_do_set()                        { _M_w = ~__STATIC_CAST(_WordT,0); }  void _M_do_reset()                      { _M_w = 0; }  bool _M_is_equal(const _Self& __x) const {    return _M_w == __x._M_w;  }  bool _M_is_any() const {    return _M_w != 0;  }  size_t _M_do_count() const {    const unsigned char* __byte_ptr = (const unsigned char*)&_M_w;    const unsigned char* __end_ptr = ((const unsigned char*)&_M_w)+sizeof(_M_w);    return _Bs_G::_S_count(__byte_ptr, __end_ptr);  }  unsigned long _M_do_to_ulong() const { return _M_w; }  inline size_t _M_do_find_first(size_t __not_found) const;  // find the next "on" bit that follows "prev"  inline size_t _M_do_find_next(size_t __prev, size_t __not_found) const;};// ------------------------------------------------------------//// Definitions of should-be-non-inline functions from the single-word version of//  _Base_bitset.//inline size_t_Base_bitset<1UL>::_M_do_find_first(size_t __not_found) const {  //  typedef unsigned long _WordT;  _WordT __thisword = _M_w;  if ( __thisword != __STATIC_CAST(_WordT,0) ) {    // find byte within word    for ( size_t __j = 0; __j < sizeof(_WordT); __j++ ) {      unsigned char __this_byte        = __STATIC_CAST(unsigned char,(__thisword & (~(unsigned char)0)));      if ( __this_byte )        return __j*CHAR_BIT + _Bs_G::_S_first_one(__this_byte);      __thisword >>= CHAR_BIT;    }  }  // not found, so return a value that indicates failure.  return __not_found;}inline size_t_Base_bitset<1UL>::_M_do_find_next(size_t __prev,                                   size_t __not_found ) const {  // make bound inclusive  ++__prev;  // check out of bounds  if ( __prev >= __BITS_PER_WORD )    return __not_found;    // search first (and only) word  _WordT __thisword = _M_w;  // mask off bits below bound  __thisword &= (~__STATIC_CAST(_WordT,0)) << _S_whichbit(__prev);  if ( __thisword != __STATIC_CAST(_WordT,0) ) {    // find byte within word    // get first byte into place    __thisword >>= _S_whichbyte(__prev) * CHAR_BIT;    for ( size_t __j = _S_whichbyte(__prev); __j < sizeof(_WordT); __j++ ) {      unsigned char __this_byte        = __STATIC_CAST(unsigned char,(__thisword & (~(unsigned char)0)));      if ( __this_byte )        return __j*CHAR_BIT + _Bs_G::_S_first_one(__this_byte);      __thisword >>= CHAR_BIT;    }  }  // not found, so return a value that indicates failure.  return __not_found;} // end _M_do_find_next// ------------------------------------------------------------// Helper class to zero out the unused high-order bits in the highest word.template <size_t _Extrabits> struct _Sanitize {  static void _STLP_CALL _M_do_sanitize(unsigned long& __val)  { __val &= ~((~__STATIC_CAST(unsigned long,0)) << _Extrabits); }};_STLP_TEMPLATE_NULL struct _Sanitize<0UL> {  static void _STLP_CALL _M_do_sanitize(unsigned long) {}};_STLP_MOVE_TO_STD_NAMESPACE// ------------------------------------------------------------// Class bitset.//   _Nb may be any nonzero number of type size_t.template<size_t _Nb>class bitset : public _STLP_PRIV _Base_bitset<__BITSET_WORDS(_Nb) > {public:  enum { _Words = __BITSET_WORDS(_Nb) } ;private:  typedef _STLP_PRIV _Base_bitset< _Words > _Base;  void _M_do_sanitize() {    _STLP_PRIV _Sanitize<_Nb%__BITS_PER_WORD >::_M_do_sanitize(this->_M_hiword());  }public:  typedef unsigned long _WordT;  struct reference;  friend struct reference;  // bit reference:  struct reference {  typedef _STLP_PRIV _Base_bitset<_Words > _Bitset_base;  typedef bitset<_Nb> _Bitset;    //    friend _Bitset;    _WordT *_M_wp;    size_t _M_bpos;    // should be left undefined    reference() {}    reference( _Bitset& __b, size_t __pos ) {      _M_wp = &__b._M_getword(__pos);      _M_bpos = _Bitset_base::_S_whichbit(__pos);    }  public:    ~reference() {}    // for b[i] = __x;    reference& operator=(bool __x) {      if ( __x )        *_M_wp |= _Bitset_base::_S_maskbit(_M_bpos);      else        *_M_wp &= ~_Bitset_base::_S_maskbit(_M_bpos);      return *this;    }    // for b[i] = b[__j];    reference& operator=(const reference& __j) {      if ( (*(__j._M_wp) & _Bitset_base::_S_maskbit(__j._M_bpos)) )        *_M_wp |= _Bitset_base::_S_maskbit(_M_bpos);      else        *_M_wp &= ~_Bitset_base::_S_maskbit(_M_bpos);      return *this;    }    // flips the bit    bool operator~() const { return (*(_M_wp) & _Bitset_base::_S_maskbit(_M_bpos)) == 0; }    // for __x = b[i];    operator bool() const { return (*(_M_wp) & _Bitset_base::_S_maskbit(_M_bpos)) != 0; }    // for b[i].flip();    reference& flip() {      *_M_wp ^= _Bitset_base::_S_maskbit(_M_bpos);      return *this;    }  };  // 23.3.5.1 constructors:  bitset() {}  bitset(unsigned long __val) : _STLP_PRIV _Base_bitset<_Words>(__val) { _M_do_sanitize(); }#if defined (_STLP_MEMBER_TEMPLATES)  template<class _CharT, class _Traits, class _Alloc>  explicit bitset(const basic_string<_CharT,_Traits,_Alloc>& __s,                  size_t __pos = 0)    : _STLP_PRIV _Base_bitset<_Words >() {    if (__pos > __s.size())      __stl_throw_out_of_range("bitset");    _M_copy_from_string(__s, __pos,                        basic_string<_CharT, _Traits, _Alloc>::npos);  }  template<class _CharT, class _Traits, class _Alloc>  bitset(const basic_string<_CharT, _Traits, _Alloc>& __s,          size_t __pos,          size_t __n)  : _STLP_PRIV _Base_bitset<_Words >() {    if (__pos > __s.size())      __stl_throw_out_of_range("bitset");    _M_copy_from_string(__s, __pos, __n);  }#else /* _STLP_MEMBER_TEMPLATES */  explicit bitset(const string& __s,                  size_t __pos = 0,                  size_t __n = (size_t)-1)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?