aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/bit_io/bitinput.h
blob: 85711eb7f9a9d88ca7dc5edc03b40df26b42857d (plain) (tree)
1
2
3
4
5
6
7
8
9
10
            
                          
                                
                                    
 
                   
                  
                                             
 


                                               
                                                           
         
 


                                                     
 

                             
 


                                       

                                          

                                   
 


                                           
                                                             



                                                                               
 

                                           
                                              



                                      
 
                            
                                                 
                                               
 
                           
 
                                                                                                                       
 
                                        
 
                               
 

                                           
                                                            
                                          
 
                           
 
                                                   
 
                                        
 
                               
 

                                           
                                                                           



                                                      
 

                                                                                            
                                                        



                                           
 
                            
                                                           
                                          
 

                                                                                            
                                                                       



                                                      
 


                                                                                                         
                                                  
                         
 
                                                    
 
                           
 
                            
                                                     
                                               
 
                                            
                                            
 
                                                 
                                                  
 

                                                                           
                                                                                             





                                                           
 
#pragma once

#include "bitinput_impl.h"

#include <util/system/yassert.h>
#include <util/generic/vector.h>
#include <util/generic/yexception.h>

#include <iterator>

namespace NBitIO {
    // Based on junk/solar/codecs/bitstream.h

    class TBitInput: protected  TBitInputImpl {
    public:
        template <typename TVec>
        explicit TBitInput(const TVec& vec)
            : TBitInputImpl(std::begin(vec), std::end(vec))
        {
        }

        TBitInput(const char* start, const char* end)
            : TBitInputImpl(start, end)
        {
        }

        bool Eof() const {
            return EofImpl();
        }

        ui64 GetOffset() const {
            ui64 bo = BitOffset();
            return bo / 8 + !!(bo % 8);
        }

        using TBitInputImpl::GetBitLength;

        ui64 GetBitOffset() const {
            return BitOffset() % 8;
        }

    public:
        // Read with static number of bits.
        // Preserves what's in result.
        template <ui64 bits, typename T>
        Y_FORCE_INLINE bool ReadK(T& result, ui64 skipbits) {
            ui64 r64 = 0;
            bool ret = bits <= 56 ? ReadKImpl<bits>(r64) : ReadSafe(r64, bits);
            CopyToResultK<bits>(result, r64, skipbits);
            return ret;
        }

        // Read with static number of bits.
        // Zeroes other bits in result.
        template <ui64 bits, typename T>
        Y_FORCE_INLINE bool ReadK(T& result) {
            ui64 r = 0;
            bool res = ReadK<bits>(r);
            result = r;
            return res;
        }

        // Shortcut to impl.
        template <ui64 bits>
        Y_FORCE_INLINE bool ReadK(ui64& result) {
            if (bits <= 56)
                return ReadKImpl<bits>(result);

            ui64 r1 = 0ULL;
            ui64 r2 = 0ULL;

            bool ret1 = ReadKImpl<56ULL>(r1);
            bool ret2 = ReadKImpl<(bits > 56ULL ? bits - 56ULL : 0) /*or else we get negative param in template*/>(r2);

            result = (r2 << 56ULL) | r1;

            return ret1 & ret2;
        }

        // It's safe to read up to 64 bits.
        // Zeroes other bits in result.
        template <typename T>
        Y_FORCE_INLINE bool ReadSafe(T& result, ui64 bits) {
            if (bits <= 56ULL)
                return Read(result, bits);

            ui64 r1 = 0ULL;
            ui64 r2 = 0ULL;

            bool ret1 = ReadKImpl<56ULL>(r1);
            bool ret2 = ReadImpl(r2, bits - 56ULL);

            result = (r2 << 56ULL) | r1;

            return ret1 & ret2;
        }

        // It's safe to read up to 64 bits.
        // Preserves what's in result.
        template <typename T>
        Y_FORCE_INLINE bool ReadSafe(T& result, ui64 bits, ui64 skipbits) {
            ui64 r64 = 0;
            bool ret = ReadSafe(r64, bits);
            CopyToResult(result, r64, bits, skipbits);
            return ret;
        }

        // Do not try to read more than 56 bits at once. Split in two reads or use ReadSafe.
        // Zeroes other bits in result.
        template <typename T>
        Y_FORCE_INLINE bool Read(T& result, ui64 bits) {
            ui64 r64 = 0;
            bool ret = ReadImpl(r64, bits);
            result = r64;
            return ret;
        }

        // Shortcut to impl.
        Y_FORCE_INLINE bool Read(ui64& result, ui64 bits) {
            return ReadImpl(result, bits);
        }

        // Do not try to read more than 56 bits at once. Split in two reads or use ReadSafe.
        // Preserves what's in result.
        template <typename T>
        Y_FORCE_INLINE bool Read(T& result, ui64 bits, ui64 skipbits) {
            ui64 r64 = 0;
            bool ret = ReadImpl(r64, bits);
            CopyToResult(result, r64, bits, skipbits);
            return ret;
        }

        // Unsigned wordwise read. Underlying data is splitted in "words" of "bits(data) + 1(flag)" bits.
        // Like this: (unsigned char)0x2E<3> (0010 1110) <=> 1110 0101
        //                                                   fddd fddd
        template <ui64 bits, typename T>
        Y_FORCE_INLINE bool ReadWords(T& result) {
            ui64 r64 = 0;

            bool retCode = ReadWordsImpl<bits>(r64);
            result = r64;

            return retCode;
        }

        // Shortcut to impl.
        template <ui64 bits>
        Y_FORCE_INLINE bool ReadWords(ui64& result) {
            return ReadWordsImpl<bits>(result);
        }

        Y_FORCE_INLINE bool Back(int bits) {
            return Seek(BitOffset() - bits);
        }

        Y_FORCE_INLINE bool Seek(int bitoffset) {
            return TBitInputImpl::Seek(bitoffset);
        }

        // A way to read a portion of bits at random location.
        // Didn't want to complicate sequential read, neither to copypaste.
        template <typename T>
        Y_FORCE_INLINE bool ReadRandom(ui64 bitoffset, T& result, ui64 bits, ui64 skipbits) {
            const ui64 curr = BitOffset();
            Seek(bitoffset);
            bool ret = ReadSafe<T>(result, bits, skipbits);
            Seek(curr);
            return ret;
        }
    };
}