📄 dynamic_bitset.hpp
字号:
{
return !(a > b);
}
template <typename Block, typename Allocator>
inline bool operator>(const dynamic_bitset<Block, Allocator>& a,
const dynamic_bitset<Block, Allocator>& b)
{
return b < a;
}
template <typename Block, typename Allocator>
inline bool operator>=(const dynamic_bitset<Block, Allocator>& a,
const dynamic_bitset<Block, Allocator>& b)
{
return !(a < b);
}
//-----------------------------------------------------------------------------
// stream operations
#ifdef BOOST_OLD_IOSTREAMS
template < typename Block, typename Alloc>
std::ostream&
operator<<(std::ostream& os, const dynamic_bitset<Block, Alloc>& b)
{
// NOTE: since this is aimed at "classic" iostreams, exception
// masks on the stream are not supported. The library that
// ships with gcc 2.95 has an exceptions() member function but
// nothing is actually implemented; not even the class ios::failure.
using namespace std;
const ios::iostate ok = ios::goodbit;
ios::iostate err = ok;
if (os.opfx()) { // gps
//try
typedef typename dynamic_bitset<Block, Alloc>::size_type bitsetsize_type;
const bitsetsize_type sz = b.size();
std::streambuf * buf = os.rdbuf();
size_t npad = os.width() <= 0 // careful: os.width() is signed (and can be < 0)
|| (bitsetsize_type) os.width() <= sz? 0 : os.width() - sz; //- gps
const char fill_char = os.fill();
const ios::fmtflags adjustfield = os.flags() & ios::adjustfield;
// if needed fill at left; pad is decresed along the way
if (adjustfield != ios::left) {
for (; 0 < npad; --npad)
if (fill_char != buf->sputc(fill_char)) {
err |= ios::failbit; // gps
break;
}
}
if (err == ok) {
// output the bitset
for (bitsetsize_type i = b.size(); 0 < i; --i) {// G.P.S.
const char dig = b.test(i-1)? '1' : '0';
if (EOF == buf->sputc(dig)) { // ok?? gps
err |= ios::failbit;
break;
}
}
}
if (err == ok) {
// if needed fill at right
for (; 0 < npad; --npad) {
if (fill_char != buf->sputc(fill_char)) {
err |= ios::failbit;
break;
}
}
}
os.osfx();
os.width(0);
} // if opfx
if(err != ok)
os.setstate(err); // assume this does NOT throw - gps
return os;
}
#else
template <typename Ch, typename Tr, typename Block, typename Alloc>
std::basic_ostream<Ch, Tr>&
operator<<(std::basic_ostream<Ch, Tr>& os,
const dynamic_bitset<Block, Alloc>& b)
{
using namespace std;
const ios_base::iostate ok = ios_base::goodbit;
ios_base::iostate err = ok;
typename basic_ostream<Ch, Tr>::sentry cerberos(os);
if (cerberos) {
BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, os.getloc());
const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
const Ch one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
try {
typedef typename dynamic_bitset<Block, Alloc>::size_type bitsetsize_type;
typedef basic_streambuf<Ch, Tr> buffer_type; // G.P.S.
buffer_type * buf = os.rdbuf();
size_t npad = os.width() <= 0 // careful: os.width() is signed (and can be < 0)
|| (bitsetsize_type) os.width() <= b.size()? 0 : os.width() - b.size(); //- G.P.S.
const Ch fill_char = os.fill();
const ios_base::fmtflags adjustfield = os.flags() & ios_base::adjustfield;
// if needed fill at left; pad is decresed along the way
if (adjustfield != ios_base::left) {
for (; 0 < npad; --npad)
if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) {
err |= ios_base::failbit; // G.P.S.
break;
}
}
if (err == ok) {
// output the bitset
for (bitsetsize_type i = b.size(); 0 < i; --i) {// G.P.S.
typename buffer_type::int_type
ret = buf->sputc(b.test(i-1)? one : zero);
if (Tr::eq_int_type(Tr::eof(), ret)) {
err |= ios_base::failbit;
break;
}
}
}
if (err == ok) {
// if needed fill at right
for (; 0 < npad; --npad) {
if (Tr::eq_int_type(Tr::eof(), buf->sputc(fill_char))) {
err |= ios_base::failbit;
break;
}
}
}
os.width(0);
} catch (...) { // see std 27.6.1.1/4
bool rethrow = false;
try { os.setstate(ios_base::failbit); } catch (...) { rethrow = true; }
if (rethrow)
throw;
}
}
if(err != ok)
os.setstate(err); // may throw exception
return os;
}
#endif
#ifdef BOOST_OLD_IOSTREAMS
// gps - A sentry-like class that calls isfx in its
// destructor. Necessary because bit_appender::do_append may throw.
class pseudo_sentry {
std::istream & m_r;
const bool m_ok;
public:
explicit pseudo_sentry(std::istream & r) : m_r(r), m_ok(r.ipfx(0)) { }
~pseudo_sentry() { m_r.isfx(); }
operator bool() const { return m_ok; }
};
template <typename Block, typename Alloc>
std::istream&
operator>>(std::istream& is, dynamic_bitset<Block, Alloc>& b)
{
// Extractor for classic IO streams (libstdc++ < 3.0)
// ----------------------------------------------------//
// It's assumed that the stream buffer functions, and
// the stream's setstate() _cannot_ throw.
typedef dynamic_bitset<Block, Alloc> bitset_type;
typedef typename bitset_type::size_type size_type;
std::ios::iostate err = std::ios::goodbit; // gps
pseudo_sentry cerberos(is); // skips whitespaces
if(cerberos) {
b.clear();
const std::streamsize w = is.width();
const size_type limit = w > 0 && static_cast<size_type>(w) < b.max_size()// gps
? w : b.max_size();
typename bitset_type::bit_appender appender(b);
std::streambuf * buf = is.rdbuf();
for(int c = buf->sgetc(); appender.get_count() < limit; c = buf->snextc() ) {
if (c == EOF) {
err |= std::ios::eofbit; // G.P.S.
break;
}
else if (char(c) != '0' && char(c) != '1')
break; // non digit character
else {
try {
//throw std::bad_alloc(); // gps
appender.do_append(char(c) == '1');
}
catch(...) {
is.setstate(std::ios::failbit); // assume this can't throw
throw;
}
}
} // for
}
is.width(0); // gps
if (b.size() == 0)
err |= std::ios::failbit;
if (err != std::ios::goodbit) // gps
is.setstate (err); // may throw
return is;
}
#else // BOOST_OLD_IOSTREAMS
template <typename Ch, typename Tr, typename Block, typename Alloc>
std::basic_istream<Ch, Tr>&
operator>>(std::basic_istream<Ch, Tr>& is, dynamic_bitset<Block, Alloc>& b)
{
using namespace std;
typedef dynamic_bitset<Block, Alloc> bitset_type;
typedef typename bitset_type::size_type size_type;
const streamsize w = is.width();
const size_type limit = 0 < w && static_cast<size_type>(w) < b.max_size()? // gps
w : b.max_size();
ios_base::iostate err = ios_base::goodbit; // gps
typename basic_istream<Ch, Tr>::sentry cerberos(is); // skips whitespaces
if(cerberos) {
// in accordance with prop. resol. of lib DR 303 [last checked 4 Feb 2004]
BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch, fac, is.getloc());
const Ch zero = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '0');
const Ch one = BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac, '1');
b.clear();
try {
typename bitset_type::bit_appender appender(b);
basic_streambuf <Ch, Tr> * buf = is.rdbuf();
typename Tr::int_type c = buf->sgetc(); // G.P.S.
for( ; appender.get_count() < limit; c = buf->snextc() ) {
if (Tr::eq_int_type(Tr::eof(), c)) {
err |= ios_base::eofbit; // G.P.S.
break;
}
else {
const Ch to_c = Tr::to_char_type(c);
const bool is_one = Tr::eq(to_c, one);
if (!is_one && !Tr::eq(to_c, zero))
break; // non digit character
appender.do_append(is_one);
}
} // for
}
catch (...) {
// catches from stream buf, or from vector:
//
// bits_stored bits have been extracted and stored, and
// either no further character is extractable or we can't
// append to the underlying vector (out of memory) gps
bool rethrow = false; // see std 27.6.1.1/4
try { is.setstate(ios_base::badbit); }
catch(...) { rethrow = true; }
if (rethrow)
throw;
}
}
is.width(0); // gps
if (b.size() == 0 /*|| !cerberos*/)
err |= ios_base::failbit;
if (err != ios_base::goodbit) // gps
is.setstate (err); // may throw
return is;
}
#endif
//-----------------------------------------------------------------------------
// bitset operations
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator&(const dynamic_bitset<Block, Allocator>& x,
const dynamic_bitset<Block, Allocator>& y)
{
dynamic_bitset<Block, Allocator> b(x);
return b &= y;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator|(const dynamic_bitset<Block, Allocator>& x,
const dynamic_bitset<Block, Allocator>& y)
{
dynamic_bitset<Block, Allocator> b(x);
return b |= y;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator^(const dynamic_bitset<Block, Allocator>& x,
const dynamic_bitset<Block, Allocator>& y)
{
dynamic_bitset<Block, Allocator> b(x);
return b ^= y;
}
template <typename Block, typename Allocator>
dynamic_bitset<Block, Allocator>
operator-(const dynamic_bitset<Block, Allocator>& x,
const dynamic_bitset<Block, Allocator>& y)
{
dynamic_bitset<Block, Allocator> b(x);
return b -= y;
}
//-----------------------------------------------------------------------------
// namespace scope swap
template<typename Block, typename Allocator>
inline void
swap(dynamic_bitset<Block, Allocator>& left,
dynamic_bitset<Block, Allocator>& right) // no throw
{
left.swap(right); // gps
}
//-----------------------------------------------------------------------------
// private (on conforming compilers) member functions
template <typename Block, typename Allocator>
inline typename dynamic_bitset<Block, Allocator>::size_type
dynamic_bitset<Block, Allocator>::calc_num_blocks(size_type num_bits)
{
return num_bits / bits_per_block
+ static_cast<int>( num_bits % bits_per_block != 0 );
}
// gives a reference to the highest block
//
template <typename Block, typename Allocator>
inline Block& dynamic_bitset<Block, Allocator>::m_highest_block()
{
return const_cast<Block &>
(static_cast<const dynamic_bitset *>(this)->m_highest_block());
}
// gives a const-reference to the highest block
//
template <typename Block, typename Allocator>
inline const Block& dynamic_bitset<Block, Allocator>::m_highest_block() const
{
assert(size() > 0 && num_blocks() > 0);
return m_bits.back();
}
// If size() is not a multiple of bits_per_block
// then not all the bits in the last block are used.
// This function resets the unused bits (convenient
// for the implementation of many member functions)
//
template <typename Block, typename Allocator>
inline void dynamic_bitset<Block, Allocator>::m_zero_unused_bits()
{
assert (num_blocks() == calc_num_blocks(m_num_bits));
// if != 0 this is the number of bits used in the last block
const block_width_type extra_bits = count_extra_bits();
if (extra_bits != 0)
m_highest_block() &= ~(~static_cast<Block>(0) << extra_bits);
}
// check class invariants
template <typename Block, typename Allocator>
bool dynamic_bitset<Block, Allocator>::m_check_invariants() const
{
const block_width_type extra_bits = count_extra_bits();
if (extra_bits > 0) {
block_type const mask = (~static_cast<Block>(0) << extra_bits);
if ((m_highest_block() & mask) != 0)
return false;
}
if (m_bits.size() > m_bits.capacity() || num_blocks() != calc_num_blocks(size()))
return false;
return true;
}
} // namespace boost
#undef BOOST_BITSET_CHAR
#endif // include guard
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -