/*
 ** Copyright 2003-2010, VisualOn, Inc.
 **
 ** Licensed under the Apache License, Version 2.0 (the "License");
 ** you may not use this file except in compliance with the License.
 ** You may obtain a copy of the License at
 **
 **     http://www.apache.org/licenses/LICENSE-2.0
 **
 ** Unless required by applicable law or agreed to in writing, software
 ** distributed under the License is distributed on an "AS IS" BASIS,
 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
/*******************************************************************************
	File:		bitbuffer.c

	Content:	Bit Buffer Management functions

*******************************************************************************/

#include "bitbuffer.h"

/*****************************************************************************
*
* function name: updateBitBufWordPtr
* description:  update Bit Buffer pointer
*
*****************************************************************************/
static void updateBitBufWordPtr(HANDLE_BIT_BUF hBitBuf,
                                UWord8 **pBitBufWord,
                                Word16   cnt)
{
  *pBitBufWord += cnt;


  if(*pBitBufWord > hBitBuf->pBitBufEnd) {
    *pBitBufWord -= (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);
  }

  if(*pBitBufWord < hBitBuf->pBitBufBase) {
    *pBitBufWord += (hBitBuf->pBitBufEnd - hBitBuf->pBitBufBase + 1);
  }
}


/*****************************************************************************
*
* function name: CreateBitBuffer
* description:  create and init Bit Buffer Management
*
*****************************************************************************/
HANDLE_BIT_BUF CreateBitBuffer(HANDLE_BIT_BUF hBitBuf,
                               UWord8 *pBitBufBase,
                               Word16  bitBufSize)
{
  assert(bitBufSize*8 <= 32768);

  hBitBuf->pBitBufBase = pBitBufBase;
  hBitBuf->pBitBufEnd  = pBitBufBase + bitBufSize - 1;

  hBitBuf->pWriteNext  = pBitBufBase;

  hBitBuf->cache       = 0;

  hBitBuf->wBitPos     = 0;
  hBitBuf->cntBits     = 0;

  hBitBuf->size        = (bitBufSize << 3);
  hBitBuf->isValid     = 1;

  return hBitBuf;
}

/*****************************************************************************
*
* function name: DeleteBitBuffer
* description:  uninit Bit Buffer Management
*
*****************************************************************************/
void DeleteBitBuffer(HANDLE_BIT_BUF *hBitBuf)
{
  if(*hBitBuf)
	(*hBitBuf)->isValid = 0;
  *hBitBuf = NULL;
}

/*****************************************************************************
*
* function name: ResetBitBuf
* description:  reset Bit Buffer Management
*
*****************************************************************************/
void ResetBitBuf(HANDLE_BIT_BUF hBitBuf,
                 UWord8 *pBitBufBase,
                 Word16  bitBufSize)
{
  hBitBuf->pBitBufBase = pBitBufBase;
  hBitBuf->pBitBufEnd  = pBitBufBase + bitBufSize - 1;


  hBitBuf->pWriteNext  = pBitBufBase;

  hBitBuf->wBitPos     = 0;
  hBitBuf->cntBits     = 0;

  hBitBuf->cache	   = 0;
}

/*****************************************************************************
*
* function name: CopyBitBuf
* description:  copy Bit Buffer Management
*
*****************************************************************************/
void CopyBitBuf(HANDLE_BIT_BUF hBitBufSrc,
                HANDLE_BIT_BUF hBitBufDst)
{
  *hBitBufDst = *hBitBufSrc;
}

/*****************************************************************************
*
* function name: GetBitsAvail
* description:  get available bits
*
*****************************************************************************/
Word16 GetBitsAvail(HANDLE_BIT_BUF hBitBuf)
{
  return hBitBuf->cntBits;
}

/*****************************************************************************
*
* function name: WriteBits
* description:  write bits to the buffer
*
*****************************************************************************/
Word16 WriteBits(HANDLE_BIT_BUF hBitBuf,
                 UWord32 writeValue,
                 Word16 noBitsToWrite)
{
  Word16 wBitPos;

  assert(noBitsToWrite <= (Word16)sizeof(Word32)*8);

  if(noBitsToWrite == 0)
	  return noBitsToWrite;

  hBitBuf->cntBits += noBitsToWrite;

  wBitPos = hBitBuf->wBitPos;
  wBitPos += noBitsToWrite;
  writeValue &= ~((~0) << noBitsToWrite); // Mask out everything except the lowest noBitsToWrite bits
  writeValue <<= 32 - wBitPos;
  writeValue |= hBitBuf->cache;

  while (wBitPos >= 8)
  {
	  UWord8 tmp;
	  tmp = (UWord8)((writeValue >> 24) & 0xFF);

	  *hBitBuf->pWriteNext++ = tmp;
	  writeValue <<= 8;
	  wBitPos -= 8;
  }

  hBitBuf->wBitPos = wBitPos;
  hBitBuf->cache = writeValue;

  return noBitsToWrite;
}
