//Editor-Info: -*- C++ -*-
//
//Subject: TOVE project / CODEC
//
//File: bithandler.cpp
//
//Version: $Revision: 1.2 $
//
//Date: $Date: 1998/10/19 08:46:02 $
//
//Organisation:
//      Helsinki University of Technology
//      Laboratory of Telecommunications and Multimedia
//
//Author:
//      Timo Pärnänen
//
//Description:
//      See corresponding header file
//
//Copyright:
//      Copyright 1999 Helsinki University of Technology
//      ALL RIGHTS RESERVED BETWEEN JANUARY 1996 AND JUNE 1999.
//
//Licence:
//
//
//History: 
//
//

#include "bithandler.h"

pfBitHandler :: pfBitHandler(void)
    : _frame(),
      _currentByte(0),
      _encPosition(1),
      _decPosition(8),
      _extBit(0),
      _currentExt(0),
      _evenOdd(0)
{
    return;
}

pfBitHandler :: ~pfBitHandler(void)
{
    return;    
}

//
//Function: start
//
//Description:
//    initialize data members
//

void pfBitHandler :: start(pfFrame &frame_)
{
    _currentByte = 0;
    _encPosition = 1;
    _decPosition = 8;
    _extBit = 0;
    _currentExt = 0;
    _evenOdd = 0;
    _frame = frame_;
    return;
}

//
//Function: getFrame
//
//Description:
//    return frame
//

pfFrame pfBitHandler :: getFrame(void)
{
    return _frame;
}

//
//Function: frameLength
//
//Description:
//    return length of frame
//

pfLong pfBitHandler :: frameLength(void)
{
    return _frame.length();
}

//
//Function: read
//
//Description:
//    read one octet from offSet position of frame
//

pfByte pfBitHandler :: read(int offSet_)
{
    return _frame.read(offSet_);
}

//
//Function: encode
//
//Description:
//    Encode given field_ to _currentByte and put byte to _frame if
//    it's full.
//

void pfBitHandler :: putBits(int amount_, pfLong field_)
{
    if (amount_ > 0)
    {
        if (_encPosition == 1)
        {
            _currentByte = 0;
        }
        int free = MAXBIT - _encPosition + 1;
        
        // Decoding field which length is more than there is free in current
        // byte. First fill the current byte and then continue to next byte.
        if (amount_ > free )
        {
            // fill the current byte and put it to frame
            putBitsToByte(free, field_);
            _frame.putFirst(_currentByte);
            field_ = field_ >> free;
            amount_ = amount_ - free;
            int fullOctets = amount_ / MAXBIT;
            // fill the full octets and put them to frame
            for (int i = 1; i <= fullOctets; i++)
            {
                _currentByte = field_ | 0;
                _frame.putFirst(_currentByte);
                field_ = field_ >> MAXBIT;
            }
            _encPosition = 1;
            _currentByte = 0;
            amount_ = amount_ % MAXBIT;
            if (amount_ > 0)        // put rest of field to new byte
            {
                putBitsToByte(amount_, field_);
            }
        }
        else        // there is enough room to field in current byte
        {
            putBitsToByte( amount_, field_);
        }
        
        if (_encPosition > MAXBIT)   // if byte is full put it to frame
        {
            _frame.putFirst(_currentByte);
            _encPosition = 1;
            _currentByte = 0;
        }
    }
    return;
}

//
//Function: decode
//
//Description:
//    Decode field_ from _currentByte and get new bytes from frame if
//    necessary.
//

pfLong pfBitHandler :: getBits(int amount_)
{
    pfLong bitField = 0;

    if (amount_ > 0)
    {
        if (_decPosition == MAXBIT)
        {
            _currentByte = _frame.getFirst();
        }    
        
        // Decode field which need more than current byte from frame.    
        if (amount_ > _decPosition)
        {
            amount_ = amount_ - _decPosition; // rest of lenght   
            // end of first octet, _decPosition indicates lenght here
            getBitsFromByte(_decPosition, bitField);
            int fullOctets = amount_ / MAXBIT;
            // get all needed full octets 
            for (int i = 1; i <= fullOctets; i++)
            {
                _currentByte = _frame.getFirst();
                bitField = bitField << MAXBIT;
                bitField = bitField | _currentByte;
            }
            _decPosition = MAXBIT;
            amount_ = amount_ % MAXBIT;
            
            if (amount_ > 0)    // take last bits of field from frame
            {
                _currentByte = _frame.getFirst();
                bitField = bitField << amount_;
                getBitsFromByte(amount_, bitField);
            }
            else
            {
                _currentByte = 0;
            }
        }
        else    // only current byte is needed from frame
        {
            getBitsFromByte(amount_, bitField);
            if (_decPosition == 0)
            {
                _decPosition = MAXBIT;
                _currentByte = 0;
            }
        }
    }
    return bitField;
}

//
//Function: skip
//
//Description:
//    Skip amount_ bits when decoding.
//

void pfBitHandler :: skip(int amount_)
{
    getBits(amount_);
    return;
}

//
//Function: putSpare
//
//Description:
//    Put amount_ zero bits to _currentByte when encoding.
//

void pfBitHandler :: putSpare(int amount_)
{
    putBits(amount_, 0);
    return;
}

//
//Function: getExtension
//
//Description:
//    Get extension bit from frame when decoding and update
//    extension "memory".
//

// void pfBitHandler :: getExtension(void)
// {
//     _currentExt = _extBit;
//     _extBit = getBits(1);
//     return;
// }

void pfBitHandler :: getExtension(void)
{
    _currentExt = _extBit;
    if (_currentExt == 0)
    {
        _extBit = getBits(1);
    }
    return;
}
    
//
//Function: putExtension
//
//Description:
//    Put extension bit to frame when encoding.
//

void pfBitHandler :: putExtension(pfLong value_)
{
    putBits(1, value_);
    return;
}

//
//Function: getBitsInExtension
//
//Description:
//    Get bits from frame in the area of extension (mecganism) block.
//

pfLong pfBitHandler :: getBitsInExtension(int amount_)
{
    if (_currentExt == 0)
    {
        return getBits(amount_);
    }
    return 0; // should return 0 or -1 or default value or something else ?!?
}

//
//Function: getSkipInExtension
//
//Description:
//    Skips bits in the area of extension block
//

void pfBitHandler :: skipInExtension(int amount_)
{
    if (_currentExt == 0)
    {
        skip(amount_);
    }
    return;
}

//
//Function: isInExtension
//
//Description:
//    Indicates if the execution is in active extension block
//

bool pfBitHandler :: isInExtension(void)
{
    bool result = (_currentExt == 0);
    return result;
}

//
//Function: endExtension
//
//Description:
//    Reset extension "memory", use this when the end of current extension
//    block is reached in decoding phase. 
//
// void pfBitHandler :: endExtension(void)
// {
//     while (_extBit == 0 && (frameLength() > 0))
//     {
//         _extBit = getBits(1);
//         skip(7);
//     }
//     _extBit = 0;
//     _currentExt = 0;    
//     return;
// }

void pfBitHandler :: endExtension(void)
{
    _extBit = 0;
    return;
}


//
//Function: getEvenOdd
//
//Description:
//    Get one bit from frame and store it to _evenodd bit when decoding. 
//

void pfBitHandler :: getEvenOdd(void)
{
    _evenOdd = getBits(1);
    return;
}

//
//Function: putEvenOdd
//
//Description:
//    Put "evenodd" bit to frame when encoding.
//

void pfBitHandler :: putEvenOdd(int value_)
{
    putBits(1, value_);
    return;
}

//
//Function: isValid
//
//Description:
//    Compare to values and return boolean value for result.
//

bool pfBitHandler :: isValid(pfLong value_, pfLong invalid_)
{
    if (value_ == invalid_)
    {
        return 0;
    }
    return 1;
}

//
//Function: setDefault
//
//Description:
//    Compare to values and update the first one with default if values
//    are different.
//

void pfBitHandler :: setDefault(pfLong &value_, pfLong invalid_,
                                pfLong default_)
{
    if (value_ == invalid_)
    {
        value_ = default_;
    }
    return;
}

//
//Function: putBitsToByte
//
//Description
//    Get amount_ righmost bits from field_ and set them to the left end
//    of _currentByte starting in _encPosition_. Update also encoding.
//    position.
//

void pfBitHandler :: putBitsToByte(int amount_, pfLong field_)
{
    pfByte tmp = (field_ & ~(~0 << amount_)) << (_encPosition - 1);
    _currentByte = tmp | _currentByte;
    _encPosition = _encPosition + amount_;
    return;
}

//
//Function: getBitsFromByte
//
//Description
//    Get amount_ rightmost bits from _currentByte starting in _decPosition
//    and set them to the right end of field_. Update also decoding position.
//

void pfBitHandler :: getBitsFromByte(int amount_, pfLong &field_)
{
    pfByte tmp = (_currentByte >> (_decPosition - amount_)) & ~(~0 << amount_);
    field_ = field_ | tmp;
    _decPosition = _decPosition - amount_;
    return;    
}

