2 This file is a part of libcds - Concurrent Data Structures library
4 (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2017
6 Source code repo: http://github.com/khizmax/libcds/
7 Download: http://sourceforge.net/projects/libcds/files/
9 Redistribution and use in source and binary forms, with or without
10 modification, are permitted provided that the following conditions are met:
12 * Redistributions of source code must retain the above copyright notice, this
13 list of conditions and the following disclaimer.
15 * Redistributions in binary form must reproduce the above copyright notice,
16 this list of conditions and the following disclaimer in the documentation
17 and/or other materials provided with the distribution.
19 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef CDSLIB_ALGO_SPLIT_BITSTRING_H
32 #define CDSLIB_ALGO_SPLIT_BITSTRING_H
34 #include <cds/algo/base.h>
36 namespace cds { namespace algo {
38 /// Cuts a bit sequence from fixed-size bit-string
40 The splitter can be used as an iterator over bit-string.
41 Each call of \p cut() or \p safe_cut() cuts the bit count specified
42 and keeps the position inside bit-string for the next call.
44 The splitter stores a const reference to bit-string, not a copy.
45 The maximum count of bits that can be cut in a single call is <tt> sizeof(UInt) * 8 </tt>
48 - \p BitString - a fixed-sized type that interprets as bit string
49 - \p BitStringSize - the size of \p BitString in bytes, default is <tt>sizeof( BitString )</tt>.
50 You can specify 0 for default.
51 - \p UInt - an unsigned integer, return type for \p cut()
53 template <typename BitString, size_t BitStringSize = sizeof( BitString ), typename UInt = typename std::conditional< BitStringSize % sizeof(size_t) == 0, size_t, unsigned >::type >
57 typedef BitString bitstring; ///< Bit-string type
58 typedef UInt uint_type; ///< Bit-string portion type
59 static CDS_CONSTEXPR size_t const c_bitstring_size = BitStringSize ? BitStringSize : sizeof( BitString ); ///< size of \p BitString in bytes
61 /// Minimum count of bits to be cut
62 static CDS_CONSTEXPR size_t const c_nMinBitCut = 1;
65 static CDS_CONSTEXPR size_t const c_nHashSize = (c_bitstring_size + sizeof(uint_type) - 1) / sizeof(uint_type);
66 static CDS_CONSTEXPR size_t const c_nBitPerByte = 8;
67 static CDS_CONSTEXPR size_t const c_nBitPerHash = c_bitstring_size * c_nBitPerByte;
68 static CDS_CONSTEXPR size_t const c_nBitPerInt = sizeof( uint_type ) * c_nBitPerByte;
72 /// Initializises the splitter with reference to \p h and zero start bit offset
73 explicit split_bitstring( bitstring const& h )
74 : m_ptr(reinterpret_cast<uint_type const*>( &h ))
78 , m_last( m_ptr + c_nHashSize )
82 /// Initializises the splitter with reference to \p h and start bit offset \p nBitOffset
83 split_bitstring( bitstring const& h, size_t nBitOffset )
84 : m_ptr( reinterpret_cast<uint_type const*>( &h ) + nBitOffset / c_nBitPerInt )
85 , m_offset( nBitOffset )
86 , m_first( reinterpret_cast<uint_type const*>(&h))
88 , m_last( m_first + c_nHashSize )
93 /// Returns \p true if end-of-string is not reached yet
94 explicit operator bool() const
99 /// Returns \p true if end-of-stream encountered
102 return m_offset >= c_nBitPerHash;
105 /// Cuts next \p nBits from bit-string
107 Precondition: <tt>nBits <= sizeof(uint_type) * 8</tt>
109 This function does not manage out-of-bound condition.
110 To control that use \p safe_cut().
112 uint_type cut( size_t nBits )
115 assert( nBits <= c_nBitPerInt );
116 assert( m_offset + nBits <= c_nBitPerHash );
118 assert( m_ptr < m_last );
122 size_t const nRest = c_nBitPerInt - m_offset % c_nBitPerInt;
124 if ( nBits < nRest ) {
125 result = static_cast<uint_type>( *m_ptr << ( nRest - nBits ));
126 result = static_cast<uint_type>( result >> ( c_nBitPerInt - nBits ));
128 else if ( nBits == nRest ) {
129 result = static_cast<uint_type>( *m_ptr >> ( c_nBitPerInt - nRest ));
131 assert( m_offset % c_nBitPerInt == 0 );
134 uint_type const lsb = static_cast<uint_type>( *m_ptr >> ( c_nBitPerInt - nRest ));
138 result = static_cast<uint_type>( *m_ptr << ( c_nBitPerInt - nBits ));
139 result = static_cast<uint_type>( result >> ( c_nBitPerInt - nBits ));
140 result = static_cast<uint_type>( (result << nRest) + lsb );
143 assert( m_offset <= c_nBitPerHash );
145 assert( m_ptr <= m_last );
150 /// Cuts up to \p nBits from the bit-string
152 Analog of \p cut() but if \p nBits is more than the rest of bit-string,
153 only the rest is returned.
154 If \p eos() is \p true the function returns 0.
156 uint_type safe_cut( size_t nBits )
161 assert( nBits <= sizeof(uint_type) * c_nBitPerByte );
163 if ( m_offset + nBits > c_nBitPerHash )
164 nBits = c_nBitPerHash - m_offset;
165 return nBits ? cut( nBits ) : 0;
168 /// Resets the splitter
169 void reset() CDS_NOEXCEPT
175 /// Returns pointer to source bitstring
176 bitstring const * source() const
178 return reinterpret_cast<bitstring const *>( m_first );
181 /// Returns current bit offset from beginning of bit-string
182 size_t bit_offset() const
189 uint_type const* m_ptr; ///< current position in the hash
190 size_t m_offset; ///< current bit offset in bit-string
191 uint_type const* m_first; ///< first position
193 uint_type const* m_last; ///< last position
198 }} // namespace cds::algo
200 #endif // #ifndef CDSLIB_ALGO_SPLIT_BITSTRING_H