root/libbase/BitsReader.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// BitsReader.h:  bits reader, for Gnash.
// 
//   Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010,
//   2011 Free Software Foundation, Inc
// 
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//


#ifndef BITSREADER_H
#define BITSREADER_H

#include "dsodefs.h"
#include "log.h"

#include <sstream>
#include <cassert>
#include <boost/cstdint.hpp> // for boost::uint32_t used in this file

namespace gnash {

/// BitsReader is used to encapsulate bit-packed buffer reads.
//
/// TODO: implement boundary checking, maybe by throwing an exception
///       when attempts are made to read past end of buffer
///
class DSOEXPORT BitsReader 
{
public:
        typedef unsigned char byte;

        /// Ownership of buffer left to caller
        BitsReader(const byte* input, size_t len)
                :
                start(input),
                ptr(start),
                end(start+len),
                usedBits(0)
        {
        }

        /// Create a BitsReader reading a subset of another
        //
        /// The starting pointer will be taken from the parent
        /// reader cursor, including used bits, use align() if
        /// need to discard the left over ones.
        ///
        /// length will be given explicitly.
        ///
        BitsReader(const BitsReader& from, size_t len)
                :
                start(from.ptr),
                ptr(start),
                end(start+len),
                usedBits(from.usedBits) 
        {
        }

        ~BitsReader() {}

        size_t size() const
        {
                return end-start;
        }

        /// Set a new buffer to work with
        void setBuffer(byte* input, size_t len)
        {
                start = ptr = input;
                end = start+len;
                usedBits = 0;
        }

        /// \brief
        /// Reads a bit-packed unsigned integer from the stream
        /// and returns it.  The given bitcount determines the
        /// number of bits to read.
        unsigned read_uint(unsigned short bitcount);

        /// \brief
        /// Reads a single bit off the stream
        /// and returns it.  
        bool read_bit();

        /// \brief
        /// Reads a bit-packed little-endian signed integer
        /// from the stream.  The given bitcount determines the
        /// number of bits to read.
        boost::int32_t read_sint(unsigned short bitcount);

        /// Read a byte as an unsigned int (aligned)
        boost::uint8_t  read_u8()
        {
                align();
                return *ptr++;
        }

        /// Read one bytes as a signed int (aligned)
    boost::int8_t read_s8()
        {
                return static_cast<boost::int8_t>(read_u8());
        }

        /// Read two bytes as an unsigned int (aligned)
        boost::uint16_t read_u16()
        {
                align();
                assert(ptr+2 < end);
                boost::uint16_t result = *ptr++;
                result |= *ptr++ << 8;
                return result ;
        }

        /// Read two bytes as a signed int (aligned)
        boost::int16_t  read_s16()
        {
                return static_cast<boost::int16_t>(read_u16());
        }

        /// Read four bytes as an unsigned int (aligned)
        boost::uint32_t read_u32()
        {
                align();
                assert(ptr+4 < end);
                boost::uint32_t result = *ptr++;
                result |= *ptr++ << 8;
                result |= *ptr++ << 16;
                result |= *ptr++ << 24;
                return(result);
        }

        /// Read four bytes as an signed int (aligned)
        boost::int32_t read_s32()
        {
                return static_cast<boost::int32_t>(read_u32());
        }

        /// \brief
        /// Discard any unused bit in the current byte
        /// and advance to next
        void align()
        {
                if ( usedBits ) advanceToNextByte();
        }

        /// Checks if the stream contains X bits
        bool gotBits(boost::uint32_t nbits)
        {
                boost::uint32_t gotbits = 8-usedBits +8*(end-ptr-1);
                if (gotbits > nbits) return true;
                else return false;
        }

private:

        void advanceToNextByte()
        {
                if ( ++ptr == end )
                {
                        log_debug("Going round");
                        ptr=start;
                }
                usedBits=0;
        }

        /// Pointer to first byte
        const byte* start;

        /// Pointer to current byte
        const byte* ptr;

        /// Pointer to one past last byte
        const byte* end;

        /// Number of used bits in current byte
        unsigned usedBits;

};


}       // end namespace gnash


#endif // BITSREADER_H


// Local Variables:
// mode: C++
// c-basic-offset: 8 
// tab-width: 8
// indent-tabs-mode: t
// End:

/* [<][>][^][v][top][bottom][index][help] */