Removed redundant spaces
[libcds.git] / cds / algo / split_bitstring.h
index 51590e2f1915f691632818b89358da8108051f2f..738accbb6c25ba42f3df20873c4c184491c2a478 100644 (file)
@@ -1,22 +1,50 @@
-//$$CDS-header$$
+/*
+    This file is a part of libcds - Concurrent Data Structures library
+
+    (C) Copyright Maxim Khizhinsky (libcds.dev@gmail.com) 2006-2016
+
+    Source code repo: http://github.com/khizmax/libcds/
+    Download: http://sourceforge.net/projects/libcds/files/
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright notice, this
+      list of conditions and the following disclaimer.
+
+    * Redistributions in binary form must reproduce the above copyright notice,
+      this list of conditions and the following disclaimer in the documentation
+      and/or other materials provided with the distribution.
+
+    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+    DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+    DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+    SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+    CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+    OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
 
 #ifndef CDSLIB_ALGO_SPLIT_BITSTRING_H
 #define CDSLIB_ALGO_SPLIT_BITSTRING_H
 
 #include <cds/algo/base.h>
 
-namespace cds { namespace algo { 
+namespace cds { namespace algo {
 
     /// Cuts a bit sequence from fixed-size bit-string
     /**
-        The splitter an be used as iterator over bit-string.
+        The splitter can be used as iterator over bit-string.
         Each call of \p cut() or \p safe_cut() cuts the bit count specified
         and keeps the position inside bit-string for the next call.
 
         The splitter stores a const reference to bit-string, not a copy.
-        The maximum count of bits that can be cut for single call is <tt> sizeof(UInt) * 8 </tt>
+        The maximum count of bits that can be cut in a single call is <tt> sizeof(UInt) * 8 </tt>
     */
-    template <typename BitString, typename UInt = size_t >
+    template <typename BitString, typename UInt = typename std::conditional< sizeof(BitString) % sizeof(size_t) == 0, size_t, unsigned >::type >
     class split_bitstring
     {
     public:
@@ -31,16 +59,27 @@ namespace cds { namespace algo {
         //@endcond
 
     public:
-        /// Initializises the splitter with reference to \p h
+        /// Initializises the splitter with reference to \p h and zero start bit offset
         explicit split_bitstring( bitstring const& h )
             : m_ptr(reinterpret_cast<uint_type const*>( &h ))
-            , m_pos(0)
+            , m_offset(0)
             , m_first( m_ptr )
 #   ifdef _DEBUG
             , m_last( m_ptr + c_nHashSize )
 #   endif
         {}
 
+        /// Initializises the splitter with reference to \p h and start bit offset \p nBitOffset
+        split_bitstring( bitstring const& h, size_t nBitOffset )
+            : m_ptr( reinterpret_cast<uint_type const*>( &h ) + nBitOffset / c_nBitPerInt )
+            , m_offset( nBitOffset )
+            , m_first( reinterpret_cast<uint_type const*>(&h))
+#   ifdef _DEBUG
+            , m_last( m_first + c_nHashSize )
+#   endif
+        {}
+
+
         /// Returns \p true if end-of-string is not reached yet
         explicit operator bool() const
         {
@@ -50,7 +89,7 @@ namespace cds { namespace algo {
         /// Returns \p true if end-of-stream encountered
         bool eos() const
         {
-            return m_pos >= c_nBitPerHash;
+            return m_offset >= c_nBitPerHash;
         }
 
         /// Cuts next \p nBits from bit-string
@@ -62,16 +101,16 @@ namespace cds { namespace algo {
         */
         uint_type cut( size_t nBits )
         {
-            assert( !eos() );
+            assert( !eos());
             assert( nBits <= c_nBitPerInt );
-            assert( m_pos + nBits <= c_nBitPerHash );
+            assert( m_offset + nBits <= c_nBitPerHash );
 #   ifdef _DEBUG
             assert( m_ptr < m_last );
 #   endif
             uint_type result;
 
-            size_t const nRest = c_nBitPerInt - m_pos % c_nBitPerInt;
-            m_pos += nBits;
+            uint_type const nRest = c_nBitPerInt - m_offset % c_nBitPerInt;
+            m_offset += nBits;
             if ( nBits < nRest ) {
                 result = *m_ptr << ( nRest - nBits );
                 result = result >> ( c_nBitPerInt - nBits );
@@ -79,9 +118,10 @@ namespace cds { namespace algo {
             else if ( nBits == nRest ) {
                 result = *m_ptr >> ( c_nBitPerInt - nRest );
                 ++m_ptr;
+                assert( m_offset % c_nBitPerInt == 0 );
             }
             else {
-                size_t const lsb = *m_ptr >> ( c_nBitPerInt - nRest );
+                uint_type const lsb = *m_ptr >> ( c_nBitPerInt - nRest );
                 nBits -= nRest;
                 ++m_ptr;
 
@@ -90,7 +130,7 @@ namespace cds { namespace algo {
                 result = (result << nRest) + lsb;
             }
 
-            assert( m_pos <= c_nBitPerHash );
+            assert( m_offset <= c_nBitPerHash );
 #   ifdef _DEBUG
             assert( m_ptr <= m_last );
 #   endif
@@ -105,30 +145,42 @@ namespace cds { namespace algo {
         */
         uint_type safe_cut( size_t nBits )
         {
-            if ( eos() )
+            if ( eos())
                 return 0;
 
             assert( nBits <= sizeof(uint_type) * c_nBitPerByte );
 
-            if ( m_pos + nBits > c_nBitPerHash )
-                nBits = c_nBitPerHash - m_pos;
+            if ( m_offset + nBits > c_nBitPerHash )
+                nBits = c_nBitPerHash - m_offset;
             return nBits ? cut( nBits ) : 0;
         }
 
         /// Resets the splitter
-        void reset()
+        void reset() CDS_NOEXCEPT
         {
             m_ptr = m_first;
-            m_pos = 0;
+            m_offset = 0;
+        }
+
+        /// Returns pointer to source bitstring
+        bitstring const * source() const
+        {
+            return reinterpret_cast<bitstring const *>( m_first );
+        }
+
+        /// Returns current bit offset from beginning of bit-string
+        size_t bit_offset() const
+        {
+            return m_offset;
         }
 
     private:
         //@cond
-        uint_type const* m_ptr;  ///< current position in the hash
-        size_t           m_pos;  ///< current position in bits
-        uint_type const* m_first; ///< first position
+        uint_type const* m_ptr;     ///< current position in the hash
+        size_t           m_offset;  ///< current bit offset in bit-string
+        uint_type const* m_first;   ///< first position
 #   ifdef _DEBUG
-        uint_type const* m_last;  ///< last position
+        uint_type const* m_last;    ///< last position
 #   endif
         //@endcond
     };