1 // -----------------------------------------------------------
3 // Copyright (c) 2001-2002 Chuck Allison and Jeremy Siek
4 // Copyright (c) 2003-2006, 2008 Gennaro Prota
6 // Distributed under the Boost Software License, Version 1.0.
7 // (See accompanying file LICENSE_1_0.txt or copy at
8 // http://www.boost.org/LICENSE_1_0.txt)
10 // -----------------------------------------------------------
12 #ifndef BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP
13 #define BOOST_DYNAMIC_BITSET_DYNAMIC_BITSET_HPP
20 #include <climits> // for CHAR_BIT
22 #include "boost/dynamic_bitset/config.hpp"
24 #ifndef BOOST_NO_STD_LOCALE
28 #if defined(BOOST_OLD_IOSTREAMS)
29 # include <iostream.h>
30 # include <ctype.h> // for isspace
36 #include "boost/dynamic_bitset_fwd.hpp"
37 #include "boost/detail/dynamic_bitset.hpp"
38 #include "boost/detail/iterator.hpp" // used to implement append(Iter, Iter)
39 #include "boost/static_assert.hpp"
40 #include "boost/limits.hpp"
41 #include "boost/pending/lowest_bit.hpp"
46 template <typename Block
, typename Allocator
>
49 // Portability note: member function templates are defined inside
50 // this class definition to avoid problems with VC++. Similarly,
51 // with the member functions of nested classes.
53 // [October 2008: the note above is mostly historical; new versions
54 // of VC++ are likely able to digest a more drinking form of the
55 // code; but changing it now is probably not worth the risks...]
57 BOOST_STATIC_ASSERT(detail::dynamic_bitset_impl::allowed_block_type
<Block
>::value
);
60 typedef Block block_type
;
61 typedef Allocator allocator_type
;
62 typedef std::size_t size_type
;
63 typedef block_type block_width_type
;
65 BOOST_STATIC_CONSTANT(block_width_type
, bits_per_block
= (std::numeric_limits
<Block
>::digits
));
66 BOOST_STATIC_CONSTANT(size_type
, npos
= static_cast<size_type
>(-1));
71 // A proxy class to simulate lvalues of bit type.
75 friend class dynamic_bitset
<Block
, Allocator
>;
78 // the one and only non-copy ctor
79 reference(block_type
& b
, block_type pos
)
81 m_mask( (assert(pos
< bits_per_block
),
82 block_type(1) << pos
)
86 void operator&(); // left undefined
90 // copy constructor: compiler generated
92 operator bool() const { return (m_block
& m_mask
) != 0; }
93 bool operator~() const { return (m_block
& m_mask
) == 0; }
95 reference
& flip() { do_flip(); return *this; }
97 reference
& operator=(bool x
) { do_assign(x
); return *this; } // for b[i] = x
98 reference
& operator=(const reference
& rhs
) { do_assign(rhs
); return *this; } // for b[i] = b[j]
100 reference
& operator|=(bool x
) { if (x
) do_set(); return *this; }
101 reference
& operator&=(bool x
) { if (!x
) do_reset(); return *this; }
102 reference
& operator^=(bool x
) { if (x
) do_flip(); return *this; }
103 reference
& operator-=(bool x
) { if (x
) do_reset(); return *this; }
106 block_type
& m_block
;
107 const block_type m_mask
;
109 void do_set() { m_block
|= m_mask
; }
110 void do_reset() { m_block
&= ~m_mask
; }
111 void do_flip() { m_block
^= m_mask
; }
112 void do_assign(bool x
) { x
? do_set() : do_reset(); }
115 typedef bool const_reference
;
117 // constructors, etc.
119 dynamic_bitset(const Allocator
& alloc
= Allocator());
122 dynamic_bitset(size_type num_bits
, unsigned long value
= 0,
123 const Allocator
& alloc
= Allocator());
126 // WARNING: you should avoid using this constructor.
128 // A conversion from string is, in most cases, formatting,
129 // and should be performed by using operator>>.
132 // Leave the parentheses around std::basic_string<CharT, Traits, Alloc>::npos.
133 // g++ 3.2 requires them and probably the standard will - see core issue 325
135 // split into two constructors because of bugs in MSVC 6.0sp5 with STLport
137 template <typename CharT
, typename Traits
, typename Alloc
>
138 dynamic_bitset(const std::basic_string
<CharT
, Traits
, Alloc
>& s
,
139 typename
std::basic_string
<CharT
, Traits
, Alloc
>::size_type pos
,
140 typename
std::basic_string
<CharT
, Traits
, Alloc
>::size_type n
,
141 size_type num_bits
= npos
,
142 const Allocator
& alloc
= Allocator())
147 init_from_string(s
, pos
, n
, num_bits
);
150 template <typename CharT
, typename Traits
, typename Alloc
>
152 dynamic_bitset(const std::basic_string
<CharT
, Traits
, Alloc
>& s
,
153 typename
std::basic_string
<CharT
, Traits
, Alloc
>::size_type pos
= 0)
155 :m_bits(Allocator()),
158 init_from_string(s
, pos
, (std::basic_string
<CharT
, Traits
, Alloc
>::npos
),
162 // The first bit in *first is the least significant bit, and the
163 // last bit in the block just before *last is the most significant bit.
164 template <typename BlockInputIterator
>
165 dynamic_bitset(BlockInputIterator first
, BlockInputIterator last
,
166 const Allocator
& alloc
= Allocator())
171 using boost::detail::dynamic_bitset_impl::value_to_type
;
172 using boost::detail::dynamic_bitset_impl::is_numeric
;
175 is_numeric
<BlockInputIterator
>::value
> selector
;
177 dispatch_init(first
, last
, selector
);
180 template <typename T
>
181 void dispatch_init(T num_bits
, unsigned long value
,
182 detail::dynamic_bitset_impl::value_to_type
<true>)
184 init_from_unsigned_long(static_cast<size_type
>(num_bits
), value
);
187 template <typename T
>
188 void dispatch_init(T first
, T last
,
189 detail::dynamic_bitset_impl::value_to_type
<false>)
191 init_from_block_range(first
, last
);
194 template <typename BlockIter
>
195 void init_from_block_range(BlockIter first
, BlockIter last
)
197 assert(m_bits
.size() == 0);
198 m_bits
.insert(m_bits
.end(), first
, last
);
199 m_num_bits
= m_bits
.size() * bits_per_block
;
203 dynamic_bitset(const dynamic_bitset
& b
);
207 void swap(dynamic_bitset
& b
);
208 dynamic_bitset
& operator=(const dynamic_bitset
& b
);
210 allocator_type
get_allocator() const;
212 // size changing operations
213 void resize(size_type num_bits
, bool value
= false);
215 void push_back(bool bit
);
216 void append(Block block
);
218 template <typename BlockInputIterator
>
219 void m_append(BlockInputIterator first
, BlockInputIterator last
, std::input_iterator_tag
)
221 std::vector
<Block
, Allocator
> v(first
, last
);
222 m_append(v
.begin(), v
.end(), std::random_access_iterator_tag());
224 template <typename BlockInputIterator
>
225 void m_append(BlockInputIterator first
, BlockInputIterator last
, std::forward_iterator_tag
)
227 assert(first
!= last
);
228 block_width_type r
= count_extra_bits();
229 std::size_t d
= boost::detail::distance(first
, last
);
230 m_bits
.reserve(num_blocks() + d
);
232 for( ; first
!= last
; ++first
)
233 m_bits
.push_back(*first
); // could use vector<>::insert()
236 m_highest_block() |= (*first
<< r
);
238 Block b
= *first
>> (bits_per_block
- r
);
240 m_bits
.push_back(b
| (first
==last
? 0 : *first
<< r
));
241 } while (first
!= last
);
243 m_num_bits
+= bits_per_block
* d
;
245 template <typename BlockInputIterator
>
246 void append(BlockInputIterator first
, BlockInputIterator last
) // strong guarantee
249 typename
detail::iterator_traits
<BlockInputIterator
>::iterator_category cat
;
250 m_append(first
, last
, cat
);
256 dynamic_bitset
& operator&=(const dynamic_bitset
& b
);
257 dynamic_bitset
& operator|=(const dynamic_bitset
& b
);
258 dynamic_bitset
& operator^=(const dynamic_bitset
& b
);
259 dynamic_bitset
& operator-=(const dynamic_bitset
& b
);
260 dynamic_bitset
& operator<<=(size_type n
);
261 dynamic_bitset
& operator>>=(size_type n
);
262 dynamic_bitset
operator<<(size_type n
) const;
263 dynamic_bitset
operator>>(size_type n
) const;
265 // basic bit operations
266 dynamic_bitset
& set(size_type n
, bool val
= true);
267 dynamic_bitset
& set();
268 dynamic_bitset
& reset(size_type n
);
269 dynamic_bitset
& reset();
270 dynamic_bitset
& flip(size_type n
);
271 dynamic_bitset
& flip();
272 bool test(size_type n
) const;
275 dynamic_bitset
operator~() const;
276 size_type
count() const;
279 reference
operator[](size_type pos
) {
280 return reference(m_bits
[block_index(pos
)], bit_index(pos
));
282 bool operator[](size_type pos
) const { return test(pos
); }
284 unsigned long to_ulong() const;
286 size_type
size() const;
287 size_type
num_blocks() const;
288 size_type
max_size() const;
291 bool is_subset_of(const dynamic_bitset
& a
) const;
292 bool is_proper_subset_of(const dynamic_bitset
& a
) const;
293 bool intersects(const dynamic_bitset
& a
) const;
296 size_type
find_first() const;
297 size_type
find_next(size_type pos
) const;
300 #if !defined BOOST_DYNAMIC_BITSET_DONT_USE_FRIENDS
301 // lexicographical comparison
302 template <typename B
, typename A
>
303 friend bool operator==(const dynamic_bitset
<B
, A
>& a
,
304 const dynamic_bitset
<B
, A
>& b
);
306 template <typename B
, typename A
>
307 friend bool operator<(const dynamic_bitset
<B
, A
>& a
,
308 const dynamic_bitset
<B
, A
>& b
);
311 template <typename B
, typename A
, typename BlockOutputIterator
>
312 friend void to_block_range(const dynamic_bitset
<B
, A
>& b
,
313 BlockOutputIterator result
);
315 template <typename BlockIterator
, typename B
, typename A
>
316 friend void from_block_range(BlockIterator first
, BlockIterator last
,
317 dynamic_bitset
<B
, A
>& result
);
320 template <typename CharT
, typename Traits
, typename B
, typename A
>
321 friend std::basic_istream
<CharT
, Traits
>& operator>>(std::basic_istream
<CharT
, Traits
>& is
,
322 dynamic_bitset
<B
, A
>& b
);
324 template <typename B
, typename A
, typename stringT
>
325 friend void to_string_helper(const dynamic_bitset
<B
, A
> & b
, stringT
& s
, bool dump_all
);
332 BOOST_STATIC_CONSTANT(block_width_type
, ulong_width
= std::numeric_limits
<unsigned long>::digits
);
333 typedef std::vector
<block_type
, allocator_type
> buffer_type
;
335 void m_zero_unused_bits();
336 bool m_check_invariants() const;
338 size_type
m_do_find_from(size_type first_block
) const;
340 block_width_type
count_extra_bits() const { return bit_index(size()); }
341 static size_type
block_index(size_type pos
) { return pos
/ bits_per_block
; }
342 static block_width_type
bit_index(size_type pos
) { return static_cast<block_width_type
>(pos
% bits_per_block
); }
343 static Block
bit_mask(size_type pos
) { return Block(1) << bit_index(pos
); }
345 template <typename CharT
, typename Traits
, typename Alloc
>
346 void init_from_string(const std::basic_string
<CharT
, Traits
, Alloc
>& s
,
347 typename
std::basic_string
<CharT
, Traits
, Alloc
>::size_type pos
,
348 typename
std::basic_string
<CharT
, Traits
, Alloc
>::size_type n
,
351 assert(pos
<= s
.size());
353 typedef typename
std::basic_string
<CharT
, Traits
, Alloc
> StrT
;
354 typedef typename
StrT::traits_type Tr
;
356 const typename
StrT::size_type rlen
= (std::min
)(n
, s
.size() - pos
);
357 const size_type sz
= ( num_bits
!= npos
? num_bits
: rlen
);
358 m_bits
.resize(calc_num_blocks(sz
));
362 BOOST_DYNAMIC_BITSET_CTYPE_FACET(CharT
, fac
, std::locale());
363 const CharT one
= BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac
, '1');
365 const size_type m
= num_bits
< rlen
? num_bits
: rlen
;
366 typename
StrT::size_type i
= 0;
369 const CharT c
= s
[(pos
+ m
- 1) - i
];
371 assert( Tr::eq(c
, one
)
372 || Tr::eq(c
, BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac
, '0')) );
381 void init_from_unsigned_long(size_type num_bits
,
382 unsigned long value
/*,
383 const Allocator& alloc*/)
386 assert(m_bits
.size() == 0);
388 m_bits
.resize(calc_num_blocks(num_bits
));
389 m_num_bits
= num_bits
;
391 typedef unsigned long num_type
;
392 typedef boost::detail::dynamic_bitset_impl
393 ::shifter
<num_type
, bits_per_block
, ulong_width
> shifter
;
398 // zero out all bits at pos >= num_bits, if any;
399 // note that: num_bits == 0 implies value == 0
400 if (num_bits
< static_cast<size_type
>(ulong_width
)) {
401 const num_type mask
= (num_type(1) << num_bits
) - 1;
405 typename
buffer_type::iterator it
= m_bits
.begin();
406 for( ; value
; shifter::left_shift(value
), ++it
) {
407 *it
= static_cast<block_type
>(value
);
414 BOOST_DYNAMIC_BITSET_PRIVATE
:
416 bool m_unchecked_test(size_type pos
) const;
417 static size_type
calc_num_blocks(size_type num_bits
);
419 Block
& m_highest_block();
420 const Block
& m_highest_block() const;
423 size_type m_num_bits
;
427 friend class bit_appender
;
429 // helper for stream >>
430 // Supplies to the lack of an efficient append at the less
431 // significant end: bits are actually appended "at left" but
432 // rearranged in the destructor. From the perspective of
433 // client code everything works *as if* dynamic_bitset<> had
434 // an append_at_right() function (eventually throwing the same
435 // exceptions as push_back) except that the function is in fact
436 // called bit_appender::do_append().
444 bit_appender(const bit_appender
&);
445 bit_appender
& operator=(const bit_appender
&);
448 bit_appender(dynamic_bitset
& r
) : bs(r
), n(0), mask(0), current(0) {}
450 // reverse the order of blocks, shift
451 // if needed, and then resize
453 std::reverse(bs
.m_bits
.begin(), bs
.m_bits
.end());
454 const block_width_type offs
= bit_index(n
);
456 bs
>>= (bits_per_block
- offs
);
457 bs
.resize(n
); // doesn't enlarge, so can't throw
458 assert(bs
.m_check_invariants());
460 inline void do_append(bool value
) {
464 current
= &bs
.m_highest_block();
465 mask
= Block(1) << (bits_per_block
- 1);
474 size_type
get_count() const { return n
; }
479 #if !defined BOOST_NO_INCLASS_MEMBER_INITIALIZATION
481 template <typename Block
, typename Allocator
>
482 const typename dynamic_bitset
<Block
, Allocator
>::block_width_type
483 dynamic_bitset
<Block
, Allocator
>::bits_per_block
;
485 template <typename Block
, typename Allocator
>
486 const typename dynamic_bitset
<Block
, Allocator
>::size_type
487 dynamic_bitset
<Block
, Allocator
>::npos
;
489 template <typename Block
, typename Allocator
>
490 const typename dynamic_bitset
<Block
, Allocator
>::block_width_type
491 dynamic_bitset
<Block
, Allocator
>::ulong_width
;
498 template <typename Block
, typename Allocator
>
499 bool operator!=(const dynamic_bitset
<Block
, Allocator
>& a
,
500 const dynamic_bitset
<Block
, Allocator
>& b
);
502 template <typename Block
, typename Allocator
>
503 bool operator<=(const dynamic_bitset
<Block
, Allocator
>& a
,
504 const dynamic_bitset
<Block
, Allocator
>& b
);
506 template <typename Block
, typename Allocator
>
507 bool operator>(const dynamic_bitset
<Block
, Allocator
>& a
,
508 const dynamic_bitset
<Block
, Allocator
>& b
);
510 template <typename Block
, typename Allocator
>
511 bool operator>=(const dynamic_bitset
<Block
, Allocator
>& a
,
512 const dynamic_bitset
<Block
, Allocator
>& b
);
515 #ifdef BOOST_OLD_IOSTREAMS
516 template <typename Block
, typename Allocator
>
517 std::ostream
& operator<<(std::ostream
& os
,
518 const dynamic_bitset
<Block
, Allocator
>& b
);
520 template <typename Block
, typename Allocator
>
521 std::istream
& operator>>(std::istream
& is
, dynamic_bitset
<Block
,Allocator
>& b
);
523 template <typename CharT
, typename Traits
, typename Block
, typename Allocator
>
524 std::basic_ostream
<CharT
, Traits
>&
525 operator<<(std::basic_ostream
<CharT
, Traits
>& os
,
526 const dynamic_bitset
<Block
, Allocator
>& b
);
528 template <typename CharT
, typename Traits
, typename Block
, typename Allocator
>
529 std::basic_istream
<CharT
, Traits
>&
530 operator>>(std::basic_istream
<CharT
, Traits
>& is
,
531 dynamic_bitset
<Block
, Allocator
>& b
);
535 template <typename Block
, typename Allocator
>
536 dynamic_bitset
<Block
, Allocator
>
537 operator&(const dynamic_bitset
<Block
, Allocator
>& b1
,
538 const dynamic_bitset
<Block
, Allocator
>& b2
);
540 template <typename Block
, typename Allocator
>
541 dynamic_bitset
<Block
, Allocator
>
542 operator|(const dynamic_bitset
<Block
, Allocator
>& b1
,
543 const dynamic_bitset
<Block
, Allocator
>& b2
);
545 template <typename Block
, typename Allocator
>
546 dynamic_bitset
<Block
, Allocator
>
547 operator^(const dynamic_bitset
<Block
, Allocator
>& b1
,
548 const dynamic_bitset
<Block
, Allocator
>& b2
);
550 template <typename Block
, typename Allocator
>
551 dynamic_bitset
<Block
, Allocator
>
552 operator-(const dynamic_bitset
<Block
, Allocator
>& b1
,
553 const dynamic_bitset
<Block
, Allocator
>& b2
);
555 // namespace scope swap
556 template<typename Block
, typename Allocator
>
557 void swap(dynamic_bitset
<Block
, Allocator
>& b1
,
558 dynamic_bitset
<Block
, Allocator
>& b2
);
561 template <typename Block
, typename Allocator
, typename stringT
>
563 to_string(const dynamic_bitset
<Block
, Allocator
>& b
, stringT
& s
);
565 template <typename Block
, typename Allocator
, typename BlockOutputIterator
>
567 to_block_range(const dynamic_bitset
<Block
, Allocator
>& b
,
568 BlockOutputIterator result
);
571 template <typename BlockIterator
, typename B
, typename A
>
573 from_block_range(BlockIterator first
, BlockIterator last
,
574 dynamic_bitset
<B
, A
>& result
)
576 // PRE: distance(first, last) <= numblocks()
577 std::copy (first
, last
, result
.m_bits
.begin());
580 //=============================================================================
581 // dynamic_bitset implementation
584 //-----------------------------------------------------------------------------
585 // constructors, etc.
587 template <typename Block
, typename Allocator
>
588 dynamic_bitset
<Block
, Allocator
>::dynamic_bitset(const Allocator
& alloc
)
589 : m_bits(alloc
), m_num_bits(0)
594 template <typename Block
, typename Allocator
>
595 dynamic_bitset
<Block
, Allocator
>::
596 dynamic_bitset(size_type num_bits
, unsigned long value
, const Allocator
& alloc
)
600 init_from_unsigned_long(num_bits
, value
);
604 template <typename Block
, typename Allocator
>
605 inline dynamic_bitset
<Block
, Allocator
>::
606 dynamic_bitset(const dynamic_bitset
& b
)
607 : m_bits(b
.m_bits
), m_num_bits(b
.m_num_bits
)
612 template <typename Block
, typename Allocator
>
613 inline dynamic_bitset
<Block
, Allocator
>::
616 assert(m_check_invariants());
619 template <typename Block
, typename Allocator
>
620 inline void dynamic_bitset
<Block
, Allocator
>::
621 swap(dynamic_bitset
<Block
, Allocator
>& b
) // no throw
623 std::swap(m_bits
, b
.m_bits
);
624 std::swap(m_num_bits
, b
.m_num_bits
);
627 template <typename Block
, typename Allocator
>
628 dynamic_bitset
<Block
, Allocator
>& dynamic_bitset
<Block
, Allocator
>::
629 operator=(const dynamic_bitset
<Block
, Allocator
>& b
)
632 m_num_bits
= b
.m_num_bits
;
636 template <typename Block
, typename Allocator
>
637 inline typename dynamic_bitset
<Block
, Allocator
>::allocator_type
638 dynamic_bitset
<Block
, Allocator
>::get_allocator() const
640 return m_bits
.get_allocator();
643 //-----------------------------------------------------------------------------
644 // size changing operations
646 template <typename Block
, typename Allocator
>
647 void dynamic_bitset
<Block
, Allocator
>::
648 resize(size_type num_bits
, bool value
) // strong guarantee
651 const size_type old_num_blocks
= num_blocks();
652 const size_type required_blocks
= calc_num_blocks(num_bits
);
654 const block_type v
= value
? ~Block(0) : Block(0);
656 if (required_blocks
!= old_num_blocks
) {
657 m_bits
.resize(required_blocks
, v
); // s.g. (copy)
663 // - if the buffer was shrunk, we have nothing more to do,
664 // except a call to m_zero_unused_bits()
666 // - if it was enlarged, all the (used) bits in the new blocks have
667 // the correct value, but we have not yet touched those bits, if
668 // any, that were 'unused bits' before enlarging: if value == true,
671 if (value
&& (num_bits
> m_num_bits
)) {
673 const size_type extra_bits
= count_extra_bits();
675 assert(old_num_blocks
>= 1 && old_num_blocks
<= m_bits
.size());
678 m_bits
[old_num_blocks
- 1] |= (v
<< extra_bits
);
683 m_num_bits
= num_bits
;
684 m_zero_unused_bits();
688 template <typename Block
, typename Allocator
>
689 void dynamic_bitset
<Block
, Allocator
>::
697 template <typename Block
, typename Allocator
>
698 void dynamic_bitset
<Block
, Allocator
>::
701 const size_type sz
= size();
706 template <typename Block
, typename Allocator
>
707 void dynamic_bitset
<Block
, Allocator
>::
708 append(Block value
) // strong guarantee
710 const block_width_type r
= count_extra_bits();
713 // the buffer is empty, or all blocks are filled
714 m_bits
.push_back(value
);
717 m_bits
.push_back(value
>> (bits_per_block
- r
));
718 m_bits
[m_bits
.size() - 2] |= (value
<< r
); // m_bits.size() >= 2
721 m_num_bits
+= bits_per_block
;
722 assert(m_check_invariants());
727 //-----------------------------------------------------------------------------
729 template <typename Block
, typename Allocator
>
730 dynamic_bitset
<Block
, Allocator
>&
731 dynamic_bitset
<Block
, Allocator
>::operator&=(const dynamic_bitset
& rhs
)
733 assert(size() == rhs
.size());
734 for (size_type i
= 0; i
< num_blocks(); ++i
)
735 m_bits
[i
] &= rhs
.m_bits
[i
];
739 template <typename Block
, typename Allocator
>
740 dynamic_bitset
<Block
, Allocator
>&
741 dynamic_bitset
<Block
, Allocator
>::operator|=(const dynamic_bitset
& rhs
)
743 assert(size() == rhs
.size());
744 for (size_type i
= 0; i
< num_blocks(); ++i
)
745 m_bits
[i
] |= rhs
.m_bits
[i
];
746 //m_zero_unused_bits();
750 template <typename Block
, typename Allocator
>
751 dynamic_bitset
<Block
, Allocator
>&
752 dynamic_bitset
<Block
, Allocator
>::operator^=(const dynamic_bitset
& rhs
)
754 assert(size() == rhs
.size());
755 for (size_type i
= 0; i
< this->num_blocks(); ++i
)
756 m_bits
[i
] ^= rhs
.m_bits
[i
];
757 //m_zero_unused_bits();
761 template <typename Block
, typename Allocator
>
762 dynamic_bitset
<Block
, Allocator
>&
763 dynamic_bitset
<Block
, Allocator
>::operator-=(const dynamic_bitset
& rhs
)
765 assert(size() == rhs
.size());
766 for (size_type i
= 0; i
< num_blocks(); ++i
)
767 m_bits
[i
] &= ~rhs
.m_bits
[i
];
768 //m_zero_unused_bits();
774 // Note that the 'if (r != 0)' is crucial to avoid undefined
775 // behavior when the left hand operand of >> isn't promoted to a
776 // wider type (because rs would be too large).
778 template <typename Block
, typename Allocator
>
779 dynamic_bitset
<Block
, Allocator
>&
780 dynamic_bitset
<Block
, Allocator
>::operator<<=(size_type n
)
787 size_type
const last
= num_blocks() - 1; // num_blocks() is >= 1
788 size_type
const div
= n
/ bits_per_block
; // div is <= last
789 block_width_type
const r
= bit_index(n
);
790 block_type
* const b
= &m_bits
[0];
794 block_width_type
const rs
= bits_per_block
- r
;
796 for (size_type i
= last
-div
; i
>0; --i
) {
797 b
[i
+div
] = (b
[i
] << r
) | (b
[i
-1] >> rs
);
803 for (size_type i
= last
-div
; i
>0; --i
) {
809 // zero out div blocks at the less significant end
810 std::fill_n(b
, div
, static_cast<block_type
>(0));
812 // zero out any 1 bit that flowed into the unused part
813 m_zero_unused_bits(); // thanks to Lester Gong
825 // see the comments to operator <<=
827 template <typename B
, typename A
>
828 dynamic_bitset
<B
, A
> & dynamic_bitset
<B
, A
>::operator>>=(size_type n
) {
829 if (n
>= m_num_bits
) {
835 size_type
const last
= num_blocks() - 1; // num_blocks() is >= 1
836 size_type
const div
= n
/ bits_per_block
; // div is <= last
837 block_width_type
const r
= bit_index(n
);
838 block_type
* const b
= &m_bits
[0];
843 block_width_type
const ls
= bits_per_block
- r
;
845 for (size_type i
= div
; i
< last
; ++i
) {
846 b
[i
-div
] = (b
[i
] >> r
) | (b
[i
+1] << ls
);
849 b
[last
-div
] = b
[last
] >> r
;
853 for (size_type i
= div
; i
<= last
; ++i
) {
856 // note the '<=': the last iteration 'absorbs'
857 // b[last-div] = b[last] >> 0;
862 // div blocks are zero filled at the most significant end
863 std::fill_n(b
+ (num_blocks()-div
), div
, static_cast<block_type
>(0));
870 template <typename Block
, typename Allocator
>
871 dynamic_bitset
<Block
, Allocator
>
872 dynamic_bitset
<Block
, Allocator
>::operator<<(size_type n
) const
874 dynamic_bitset
r(*this);
878 template <typename Block
, typename Allocator
>
879 dynamic_bitset
<Block
, Allocator
>
880 dynamic_bitset
<Block
, Allocator
>::operator>>(size_type n
) const
882 dynamic_bitset
r(*this);
887 //-----------------------------------------------------------------------------
888 // basic bit operations
890 template <typename Block
, typename Allocator
>
891 dynamic_bitset
<Block
, Allocator
>&
892 dynamic_bitset
<Block
, Allocator
>::set(size_type pos
, bool val
)
894 assert(pos
< m_num_bits
);
897 m_bits
[block_index(pos
)] |= bit_mask(pos
);
904 template <typename Block
, typename Allocator
>
905 dynamic_bitset
<Block
, Allocator
>&
906 dynamic_bitset
<Block
, Allocator
>::set()
908 std::fill(m_bits
.begin(), m_bits
.end(), ~Block(0));
909 m_zero_unused_bits();
913 template <typename Block
, typename Allocator
>
914 dynamic_bitset
<Block
, Allocator
>&
915 dynamic_bitset
<Block
, Allocator
>::reset(size_type pos
)
917 assert(pos
< m_num_bits
);
918 #if defined __MWERKS__ && BOOST_WORKAROUND(__MWERKS__, <= 0x3003) // 8.x
919 // CodeWarrior 8 generates incorrect code when the &=~ is compiled,
920 // use the |^ variation instead.. <grafik>
921 m_bits
[block_index(pos
)] |= bit_mask(pos
);
922 m_bits
[block_index(pos
)] ^= bit_mask(pos
);
924 m_bits
[block_index(pos
)] &= ~bit_mask(pos
);
929 template <typename Block
, typename Allocator
>
930 dynamic_bitset
<Block
, Allocator
>&
931 dynamic_bitset
<Block
, Allocator
>::reset()
933 std::fill(m_bits
.begin(), m_bits
.end(), Block(0));
937 template <typename Block
, typename Allocator
>
938 dynamic_bitset
<Block
, Allocator
>&
939 dynamic_bitset
<Block
, Allocator
>::flip(size_type pos
)
941 assert(pos
< m_num_bits
);
942 m_bits
[block_index(pos
)] ^= bit_mask(pos
);
946 template <typename Block
, typename Allocator
>
947 dynamic_bitset
<Block
, Allocator
>&
948 dynamic_bitset
<Block
, Allocator
>::flip()
950 for (size_type i
= 0; i
< num_blocks(); ++i
)
951 m_bits
[i
] = ~m_bits
[i
];
952 m_zero_unused_bits();
956 template <typename Block
, typename Allocator
>
957 bool dynamic_bitset
<Block
, Allocator
>::m_unchecked_test(size_type pos
) const
959 return (m_bits
[block_index(pos
)] & bit_mask(pos
)) != 0;
962 template <typename Block
, typename Allocator
>
963 bool dynamic_bitset
<Block
, Allocator
>::test(size_type pos
) const
965 assert(pos
< m_num_bits
);
966 return m_unchecked_test(pos
);
969 template <typename Block
, typename Allocator
>
970 bool dynamic_bitset
<Block
, Allocator
>::any() const
972 for (size_type i
= 0; i
< num_blocks(); ++i
)
978 template <typename Block
, typename Allocator
>
979 inline bool dynamic_bitset
<Block
, Allocator
>::none() const
984 template <typename Block
, typename Allocator
>
985 dynamic_bitset
<Block
, Allocator
>
986 dynamic_bitset
<Block
, Allocator
>::operator~() const
988 dynamic_bitset
b(*this);
993 template <typename Block
, typename Allocator
>
994 typename dynamic_bitset
<Block
, Allocator
>::size_type
995 dynamic_bitset
<Block
, Allocator
>::count() const
997 using detail::dynamic_bitset_impl::table_width
;
998 using detail::dynamic_bitset_impl::access_by_bytes
;
999 using detail::dynamic_bitset_impl::access_by_blocks
;
1000 using detail::dynamic_bitset_impl::value_to_type
;
1002 #if BOOST_WORKAROUND(__GNUC__, == 4) && (__GNUC_MINOR__ == 3) && (__GNUC_PATCHLEVEL__ == 3)
1003 // NOTE: Explicit qualification of "bits_per_block"
1004 // breaks compilation on gcc 4.3.3
1005 enum { no_padding
= bits_per_block
== CHAR_BIT
* sizeof(Block
) };
1007 // NOTE: Explicitly qualifying "bits_per_block" to workaround
1008 // regressions of gcc 3.4.x
1010 dynamic_bitset
<Block
, Allocator
>::bits_per_block
1011 == CHAR_BIT
* sizeof(Block
) };
1014 enum { enough_table_width
= table_width
>= CHAR_BIT
};
1016 enum { mode
= (no_padding
&& enough_table_width
)
1018 : access_by_blocks
};
1020 return do_count(m_bits
.begin(), num_blocks(), Block(0),
1021 static_cast<value_to_type
<(bool)mode
> *>(0));
1025 //-----------------------------------------------------------------------------
1029 template <typename B
, typename A
, typename stringT
>
1030 void to_string_helper(const dynamic_bitset
<B
, A
> & b
, stringT
& s
,
1033 typedef typename
stringT::traits_type Tr
;
1034 typedef typename
stringT::value_type Ch
;
1036 BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch
, fac
, std::locale());
1037 const Ch zero
= BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac
, '0');
1038 const Ch one
= BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac
, '1');
1040 // Note that this function may access (when
1041 // dump_all == true) bits beyond position size() - 1
1043 typedef typename dynamic_bitset
<B
, A
>::size_type size_type
;
1045 const size_type len
= dump_all
?
1046 dynamic_bitset
<B
, A
>::bits_per_block
* b
.num_blocks():
1048 s
.assign (len
, zero
);
1050 for (size_type i
= 0; i
< len
; ++i
) {
1051 if (b
.m_unchecked_test(i
))
1052 Tr::assign(s
[len
- 1 - i
], one
);
1059 // A comment similar to the one about the constructor from
1060 // basic_string can be done here. Thanks to James Kanze for
1061 // making me (Gennaro) realize this important separation of
1062 // concerns issue, as well as many things about i18n.
1064 template <typename Block
, typename Allocator
, typename stringT
>
1066 to_string(const dynamic_bitset
<Block
, Allocator
>& b
, stringT
& s
)
1068 to_string_helper(b
, s
, false);
1072 // Differently from to_string this function dumps out
1073 // every bit of the internal representation (may be
1074 // useful for debugging purposes)
1076 template <typename B
, typename A
, typename stringT
>
1078 dump_to_string(const dynamic_bitset
<B
, A
>& b
, stringT
& s
)
1080 to_string_helper(b
, s
, true /* =dump_all*/);
1083 template <typename Block
, typename Allocator
, typename BlockOutputIterator
>
1085 to_block_range(const dynamic_bitset
<Block
, Allocator
>& b
,
1086 BlockOutputIterator result
)
1088 // note how this copies *all* bits, including the
1089 // unused ones in the last block (which are zero)
1090 std::copy(b
.m_bits
.begin(), b
.m_bits
.end(), result
);
1093 template <typename Block
, typename Allocator
>
1094 unsigned long dynamic_bitset
<Block
, Allocator
>::
1098 if (m_num_bits
== 0)
1099 return 0; // convention
1101 // Check for overflows. This may be a performance burden on very
1102 // large bitsets but is required by the specification, sorry
1103 if (find_next(ulong_width
- 1) != npos
)
1104 throw std::overflow_error("boost::dynamic_bitset::to_ulong overflow");
1107 // Ok, from now on we can be sure there's no "on" bit
1108 // beyond the "allowed" positions
1109 typedef unsigned long result_type
;
1111 const size_type max_size
=
1112 (std::min
)(m_num_bits
, static_cast<size_type
>(ulong_width
));
1114 const size_type last_block
= block_index( max_size
- 1 );
1116 assert((last_block
* bits_per_block
) < static_cast<size_type
>(ulong_width
));
1118 result_type result
= 0;
1119 for (size_type i
= 0; i
<= last_block
; ++i
) {
1120 const size_type offset
= i
* bits_per_block
;
1121 result
|= (static_cast<result_type
>(m_bits
[i
]) << offset
);
1127 template <typename Block
, typename Allocator
>
1128 inline typename dynamic_bitset
<Block
, Allocator
>::size_type
1129 dynamic_bitset
<Block
, Allocator
>::size() const
1134 template <typename Block
, typename Allocator
>
1135 inline typename dynamic_bitset
<Block
, Allocator
>::size_type
1136 dynamic_bitset
<Block
, Allocator
>::num_blocks() const
1138 return m_bits
.size();
1141 template <typename Block
, typename Allocator
>
1142 inline typename dynamic_bitset
<Block
, Allocator
>::size_type
1143 dynamic_bitset
<Block
, Allocator
>::max_size() const
1145 // Semantics of vector<>::max_size() aren't very clear
1146 // (see lib issue 197) and many library implementations
1147 // simply return dummy values, _unrelated_ to the underlying
1150 // Given these problems, I was tempted to not provide this
1151 // function at all but the user could need it if he provides
1152 // his own allocator.
1155 const size_type m
= detail::dynamic_bitset_impl::
1156 vector_max_size_workaround(m_bits
);
1158 return m
<= (size_type(-1)/bits_per_block
) ?
1159 m
* bits_per_block
:
1163 template <typename Block
, typename Allocator
>
1164 inline bool dynamic_bitset
<Block
, Allocator
>::empty() const
1169 template <typename Block
, typename Allocator
>
1170 bool dynamic_bitset
<Block
, Allocator
>::
1171 is_subset_of(const dynamic_bitset
<Block
, Allocator
>& a
) const
1173 assert(size() == a
.size());
1174 for (size_type i
= 0; i
< num_blocks(); ++i
)
1175 if (m_bits
[i
] & ~a
.m_bits
[i
])
1180 template <typename Block
, typename Allocator
>
1181 bool dynamic_bitset
<Block
, Allocator
>::
1182 is_proper_subset_of(const dynamic_bitset
<Block
, Allocator
>& a
) const
1184 assert(size() == a
.size());
1185 assert(num_blocks() == a
.num_blocks());
1187 bool proper
= false;
1188 for (size_type i
= 0; i
< num_blocks(); ++i
) {
1189 const Block
& bt
= m_bits
[i
];
1190 const Block
& ba
= a
.m_bits
[i
];
1193 return false; // not a subset at all
1200 template <typename Block
, typename Allocator
>
1201 bool dynamic_bitset
<Block
, Allocator
>::intersects(const dynamic_bitset
& b
) const
1203 size_type common_blocks
= num_blocks() < b
.num_blocks()
1204 ? num_blocks() : b
.num_blocks();
1206 for(size_type i
= 0; i
< common_blocks
; ++i
) {
1207 if(m_bits
[i
] & b
.m_bits
[i
])
1213 // --------------------------------
1217 // look for the first bit "on", starting
1218 // from the block with index first_block
1220 template <typename Block
, typename Allocator
>
1221 typename dynamic_bitset
<Block
, Allocator
>::size_type
1222 dynamic_bitset
<Block
, Allocator
>::m_do_find_from(size_type first_block
) const
1224 size_type i
= first_block
;
1227 while (i
< num_blocks() && m_bits
[i
] == 0)
1230 if (i
>= num_blocks())
1231 return npos
; // not found
1233 return i
* bits_per_block
+ boost::lowest_bit(m_bits
[i
]);
1238 template <typename Block
, typename Allocator
>
1239 typename dynamic_bitset
<Block
, Allocator
>::size_type
1240 dynamic_bitset
<Block
, Allocator
>::find_first() const
1242 return m_do_find_from(0);
1246 template <typename Block
, typename Allocator
>
1247 typename dynamic_bitset
<Block
, Allocator
>::size_type
1248 dynamic_bitset
<Block
, Allocator
>::find_next(size_type pos
) const
1251 const size_type sz
= size();
1252 if (pos
>= (sz
-1) || sz
== 0)
1257 const size_type blk
= block_index(pos
);
1258 const block_width_type ind
= bit_index(pos
);
1260 // mask out bits before pos
1261 const Block fore
= m_bits
[blk
] & ( ~Block(0) << ind
);
1264 blk
* bits_per_block
+ lowest_bit(fore
)
1266 m_do_find_from(blk
+ 1);
1272 //-----------------------------------------------------------------------------
1275 template <typename Block
, typename Allocator
>
1276 bool operator==(const dynamic_bitset
<Block
, Allocator
>& a
,
1277 const dynamic_bitset
<Block
, Allocator
>& b
)
1279 return (a
.m_num_bits
== b
.m_num_bits
)
1280 && (a
.m_bits
== b
.m_bits
);
1283 template <typename Block
, typename Allocator
>
1284 inline bool operator!=(const dynamic_bitset
<Block
, Allocator
>& a
,
1285 const dynamic_bitset
<Block
, Allocator
>& b
)
1290 template <typename Block
, typename Allocator
>
1291 bool operator<(const dynamic_bitset
<Block
, Allocator
>& a
,
1292 const dynamic_bitset
<Block
, Allocator
>& b
)
1294 assert(a
.size() == b
.size());
1295 typedef typename dynamic_bitset
<Block
, Allocator
>::size_type size_type
;
1297 //if (a.size() == 0)
1300 // Since we are storing the most significant bit
1301 // at pos == size() - 1, we need to do the comparisons in reverse.
1303 for (size_type ii
= a
.num_blocks(); ii
> 0; --ii
) {
1305 if (a
.m_bits
[i
] < b
.m_bits
[i
])
1307 else if (a
.m_bits
[i
] > b
.m_bits
[i
])
1313 template <typename Block
, typename Allocator
>
1314 inline bool operator<=(const dynamic_bitset
<Block
, Allocator
>& a
,
1315 const dynamic_bitset
<Block
, Allocator
>& b
)
1320 template <typename Block
, typename Allocator
>
1321 inline bool operator>(const dynamic_bitset
<Block
, Allocator
>& a
,
1322 const dynamic_bitset
<Block
, Allocator
>& b
)
1327 template <typename Block
, typename Allocator
>
1328 inline bool operator>=(const dynamic_bitset
<Block
, Allocator
>& a
,
1329 const dynamic_bitset
<Block
, Allocator
>& b
)
1334 //-----------------------------------------------------------------------------
1335 // stream operations
1337 #ifdef BOOST_OLD_IOSTREAMS
1338 template < typename Block
, typename Alloc
>
1340 operator<<(std::ostream
& os
, const dynamic_bitset
<Block
, Alloc
>& b
)
1342 // NOTE: since this is aimed at "classic" iostreams, exception
1343 // masks on the stream are not supported. The library that
1344 // ships with gcc 2.95 has an exceptions() member function but
1345 // nothing is actually implemented; not even the class ios::failure.
1347 using namespace std
;
1349 const ios::iostate ok
= ios::goodbit
;
1350 ios::iostate err
= ok
;
1355 typedef typename dynamic_bitset
<Block
, Alloc
>::size_type bitsetsize_type
;
1357 const bitsetsize_type sz
= b
.size();
1358 std::streambuf
* buf
= os
.rdbuf();
1359 size_t npad
= os
.width() <= 0 // careful: os.width() is signed (and can be < 0)
1360 || (bitsetsize_type
) os
.width() <= sz
? 0 : os
.width() - sz
;
1362 const char fill_char
= os
.fill();
1363 const ios::fmtflags adjustfield
= os
.flags() & ios::adjustfield
;
1365 // if needed fill at left; pad is decresed along the way
1366 if (adjustfield
!= ios::left
) {
1367 for (; 0 < npad
; --npad
)
1368 if (fill_char
!= buf
->sputc(fill_char
)) {
1369 err
|= ios::failbit
;
1375 // output the bitset
1376 for (bitsetsize_type i
= b
.size(); 0 < i
; --i
) {
1377 const char dig
= b
.test(i
-1)? '1' : '0';
1378 if (EOF
== buf
->sputc(dig
)) {
1379 err
|= ios::failbit
;
1386 // if needed fill at right
1387 for (; 0 < npad
; --npad
) {
1388 if (fill_char
!= buf
->sputc(fill_char
)) {
1389 err
|= ios::failbit
;
1401 os
.setstate(err
); // assume this does NOT throw
1407 template <typename Ch
, typename Tr
, typename Block
, typename Alloc
>
1408 std::basic_ostream
<Ch
, Tr
>&
1409 operator<<(std::basic_ostream
<Ch
, Tr
>& os
,
1410 const dynamic_bitset
<Block
, Alloc
>& b
)
1413 using namespace std
;
1415 const ios_base::iostate ok
= ios_base::goodbit
;
1416 ios_base::iostate err
= ok
;
1418 typename basic_ostream
<Ch
, Tr
>::sentry
cerberos(os
);
1421 BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch
, fac
, os
.getloc());
1422 const Ch zero
= BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac
, '0');
1423 const Ch one
= BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac
, '1');
1427 typedef typename dynamic_bitset
<Block
, Alloc
>::size_type bitsetsize_type
;
1428 typedef basic_streambuf
<Ch
, Tr
> buffer_type
;
1430 buffer_type
* buf
= os
.rdbuf();
1431 size_t npad
= os
.width() <= 0 // careful: os.width() is signed (and can be < 0)
1432 || (bitsetsize_type
) os
.width() <= b
.size()? 0 : os
.width() - b
.size();
1434 const Ch fill_char
= os
.fill();
1435 const ios_base::fmtflags adjustfield
= os
.flags() & ios_base::adjustfield
;
1437 // if needed fill at left; pad is decresed along the way
1438 if (adjustfield
!= ios_base::left
) {
1439 for (; 0 < npad
; --npad
)
1440 if (Tr::eq_int_type(Tr::eof(), buf
->sputc(fill_char
))) {
1441 err
|= ios_base::failbit
;
1447 // output the bitset
1448 for (bitsetsize_type i
= b
.size(); 0 < i
; --i
) {
1449 typename
buffer_type::int_type
1450 ret
= buf
->sputc(b
.test(i
-1)? one
: zero
);
1451 if (Tr::eq_int_type(Tr::eof(), ret
)) {
1452 err
|= ios_base::failbit
;
1459 // if needed fill at right
1460 for (; 0 < npad
; --npad
) {
1461 if (Tr::eq_int_type(Tr::eof(), buf
->sputc(fill_char
))) {
1462 err
|= ios_base::failbit
;
1471 } catch (...) { // see std 27.6.1.1/4
1472 bool rethrow
= false;
1473 try { os
.setstate(ios_base::failbit
); } catch (...) { rethrow
= true; }
1481 os
.setstate(err
); // may throw exception
1488 #ifdef BOOST_OLD_IOSTREAMS
1490 // A sentry-like class that calls isfx in its destructor.
1491 // "Necessary" because bit_appender::do_append may throw.
1492 class pseudo_sentry
{
1496 explicit pseudo_sentry(std::istream
& r
) : m_r(r
), m_ok(r
.ipfx(0)) { }
1497 ~pseudo_sentry() { m_r
.isfx(); }
1498 operator bool() const { return m_ok
; }
1501 template <typename Block
, typename Alloc
>
1503 operator>>(std::istream
& is
, dynamic_bitset
<Block
, Alloc
>& b
)
1506 // Extractor for classic IO streams (libstdc++ < 3.0)
1507 // ----------------------------------------------------//
1508 // It's assumed that the stream buffer functions, and
1509 // the stream's setstate() _cannot_ throw.
1512 typedef dynamic_bitset
<Block
, Alloc
> bitset_type
;
1513 typedef typename
bitset_type::size_type size_type
;
1515 std::ios::iostate err
= std::ios::goodbit
;
1516 pseudo_sentry
cerberos(is
); // skips whitespaces
1521 const std::streamsize w
= is
.width();
1522 const size_type limit
= w
> 0 && static_cast<size_type
>(w
) < b
.max_size()
1524 typename
bitset_type::bit_appender
appender(b
);
1525 std::streambuf
* buf
= is
.rdbuf();
1526 for(int c
= buf
->sgetc(); appender
.get_count() < limit
; c
= buf
->snextc() ) {
1529 err
|= std::ios::eofbit
;
1532 else if (char(c
) != '0' && char(c
) != '1')
1533 break; // non digit character
1537 appender
.do_append(char(c
) == '1');
1540 is
.setstate(std::ios::failbit
); // assume this can't throw
1550 err
|= std::ios::failbit
;
1551 if (err
!= std::ios::goodbit
)
1552 is
.setstate (err
); // may throw
1557 #else // BOOST_OLD_IOSTREAMS
1559 template <typename Ch
, typename Tr
, typename Block
, typename Alloc
>
1560 std::basic_istream
<Ch
, Tr
>&
1561 operator>>(std::basic_istream
<Ch
, Tr
>& is
, dynamic_bitset
<Block
, Alloc
>& b
)
1564 using namespace std
;
1566 typedef dynamic_bitset
<Block
, Alloc
> bitset_type
;
1567 typedef typename
bitset_type::size_type size_type
;
1569 const streamsize w
= is
.width();
1570 const size_type limit
= 0 < w
&& static_cast<size_type
>(w
) < b
.max_size()?
1573 ios_base::iostate err
= ios_base::goodbit
;
1574 typename basic_istream
<Ch
, Tr
>::sentry
cerberos(is
); // skips whitespaces
1577 // in accordance with prop. resol. of lib DR 303 [last checked 4 Feb 2004]
1578 BOOST_DYNAMIC_BITSET_CTYPE_FACET(Ch
, fac
, is
.getloc());
1579 const Ch zero
= BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac
, '0');
1580 const Ch one
= BOOST_DYNAMIC_BITSET_WIDEN_CHAR(fac
, '1');
1584 typename
bitset_type::bit_appender
appender(b
);
1585 basic_streambuf
<Ch
, Tr
> * buf
= is
.rdbuf();
1586 typename
Tr::int_type c
= buf
->sgetc();
1587 for( ; appender
.get_count() < limit
; c
= buf
->snextc() ) {
1589 if (Tr::eq_int_type(Tr::eof(), c
)) {
1590 err
|= ios_base::eofbit
;
1594 const Ch to_c
= Tr::to_char_type(c
);
1595 const bool is_one
= Tr::eq(to_c
, one
);
1597 if (!is_one
&& !Tr::eq(to_c
, zero
))
1598 break; // non digit character
1600 appender
.do_append(is_one
);
1607 // catches from stream buf, or from vector:
1609 // bits_stored bits have been extracted and stored, and
1610 // either no further character is extractable or we can't
1611 // append to the underlying vector (out of memory)
1613 bool rethrow
= false; // see std 27.6.1.1/4
1614 try { is
.setstate(ios_base::badbit
); }
1615 catch(...) { rethrow
= true; }
1624 if (b
.size() == 0 /*|| !cerberos*/)
1625 err
|= ios_base::failbit
;
1626 if (err
!= ios_base::goodbit
)
1627 is
.setstate (err
); // may throw
1637 //-----------------------------------------------------------------------------
1638 // bitset operations
1640 template <typename Block
, typename Allocator
>
1641 dynamic_bitset
<Block
, Allocator
>
1642 operator&(const dynamic_bitset
<Block
, Allocator
>& x
,
1643 const dynamic_bitset
<Block
, Allocator
>& y
)
1645 dynamic_bitset
<Block
, Allocator
> b(x
);
1649 template <typename Block
, typename Allocator
>
1650 dynamic_bitset
<Block
, Allocator
>
1651 operator|(const dynamic_bitset
<Block
, Allocator
>& x
,
1652 const dynamic_bitset
<Block
, Allocator
>& y
)
1654 dynamic_bitset
<Block
, Allocator
> b(x
);
1658 template <typename Block
, typename Allocator
>
1659 dynamic_bitset
<Block
, Allocator
>
1660 operator^(const dynamic_bitset
<Block
, Allocator
>& x
,
1661 const dynamic_bitset
<Block
, Allocator
>& y
)
1663 dynamic_bitset
<Block
, Allocator
> b(x
);
1667 template <typename Block
, typename Allocator
>
1668 dynamic_bitset
<Block
, Allocator
>
1669 operator-(const dynamic_bitset
<Block
, Allocator
>& x
,
1670 const dynamic_bitset
<Block
, Allocator
>& y
)
1672 dynamic_bitset
<Block
, Allocator
> b(x
);
1676 //-----------------------------------------------------------------------------
1677 // namespace scope swap
1679 template<typename Block
, typename Allocator
>
1681 swap(dynamic_bitset
<Block
, Allocator
>& left
,
1682 dynamic_bitset
<Block
, Allocator
>& right
) // no throw
1688 //-----------------------------------------------------------------------------
1689 // private (on conforming compilers) member functions
1692 template <typename Block
, typename Allocator
>
1693 inline typename dynamic_bitset
<Block
, Allocator
>::size_type
1694 dynamic_bitset
<Block
, Allocator
>::calc_num_blocks(size_type num_bits
)
1696 return num_bits
/ bits_per_block
1697 + static_cast<int>( num_bits
% bits_per_block
!= 0 );
1700 // gives a reference to the highest block
1702 template <typename Block
, typename Allocator
>
1703 inline Block
& dynamic_bitset
<Block
, Allocator
>::m_highest_block()
1705 return const_cast<Block
&>
1706 (static_cast<const dynamic_bitset
*>(this)->m_highest_block());
1709 // gives a const-reference to the highest block
1711 template <typename Block
, typename Allocator
>
1712 inline const Block
& dynamic_bitset
<Block
, Allocator
>::m_highest_block() const
1714 assert(size() > 0 && num_blocks() > 0);
1715 return m_bits
.back();
1719 // If size() is not a multiple of bits_per_block
1720 // then not all the bits in the last block are used.
1721 // This function resets the unused bits (convenient
1722 // for the implementation of many member functions)
1724 template <typename Block
, typename Allocator
>
1725 inline void dynamic_bitset
<Block
, Allocator
>::m_zero_unused_bits()
1727 assert (num_blocks() == calc_num_blocks(m_num_bits
));
1729 // if != 0 this is the number of bits used in the last block
1730 const block_width_type extra_bits
= count_extra_bits();
1732 if (extra_bits
!= 0)
1733 m_highest_block() &= ~(~static_cast<Block
>(0) << extra_bits
);
1737 // check class invariants
1738 template <typename Block
, typename Allocator
>
1739 bool dynamic_bitset
<Block
, Allocator
>::m_check_invariants() const
1741 const block_width_type extra_bits
= count_extra_bits();
1742 if (extra_bits
> 0) {
1743 block_type
const mask
= (~static_cast<Block
>(0) << extra_bits
);
1744 if ((m_highest_block() & mask
) != 0)
1747 if (m_bits
.size() > m_bits
.capacity() || num_blocks() != calc_num_blocks(size()))
1755 } // namespace boost
1758 #undef BOOST_BITSET_CHAR
1760 #endif // include guard