Home | History | Annotate | Download | only in src
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #ifndef   BITSTREAMPARSER_H_INCLUDED
     19 #include "bitstreamparser.h"
     20 #endif
     21 #ifndef   OSCL_ASSERT_H_INCLUDED
     22 #include "oscl_assert.h"
     23 #endif
     24 #ifndef   OSCL_BYTE_ORDER_H_INCLUDED
     25 #include "oscl_byte_order.h"
     26 #endif
     27 #ifndef   OSCL_DLL_H_INCLUDED
     28 #include "oscl_dll.h"
     29 #endif
     30 #ifndef   OSCL_ERROR_H_INCLUDED
     31 #include "oscl_error.h"
     32 #endif
     33 #ifndef   OSCL_ERROR_CODES_H_INCLUDED
     34 #include "oscl_error_codes.h"
     35 #endif
     36 #ifndef   OSCL_EXCEPTION_H_INCLUDED
     37 #include "oscl_exception.h"
     38 #endif
     39 
     40 
     41 OSCL_EXPORT_REF BitStreamParser::BitStreamParser(uint8* stream, uint32 size)
     42 {
     43     ResetBitStreamParser(stream, size);
     44 }
     45 
     46 OSCL_EXPORT_REF void BitStreamParser::ResetBitStreamParser(uint8* stream, uint32 size)
     47 {
     48     this->size = size;
     49     start   = OSCL_STATIC_CAST(uint8*, stream);
     50     bytepos = OSCL_STATIC_CAST(uint8*, start);
     51     bitpos  = MOST_SIG_BIT;
     52 }
     53 
     54 OSCL_EXPORT_REF uint32 BitStreamParser::ReadBits(uint8 numberOfBits)
     55 {
     56     //Initialize output to zero before shifting out bits.
     57     uint32 output = 0;
     58 
     59     OSCL_ASSERT(numberOfBits <= BITS_PER_UINT32);
     60     //In case OSCL_ASSERT is defined to do nothing, set the max size.
     61     if (numberOfBits > BITS_PER_UINT32) numberOfBits = BITS_PER_UINT32;
     62 
     63     //Note: Using the host's native shift operator will automatically
     64     //convert from big endian to host's endianness.
     65     while (numberOfBits)
     66     {
     67         // Make sure bytepos won't exceed the size of the buffer while reading
     68         if (bytepos >= (start + size))
     69         {
     70             OSCL_LEAVE(OsclErrOverflow);
     71         }
     72 
     73         //Optimize reads for special cases such as byte-aligned reads and
     74         //processing multiple bits at a time.
     75         if ((numberOfBits >= BITS_PER_UINT8) && (bitpos == MOST_SIG_BIT))
     76         {
     77             //This is the special case where a read is a whole byte (aligned).
     78             //Shift the output over 8 bits.
     79             output <<= BITS_PER_UINT8;
     80             //OR the current byte from the stream into the output.
     81             output |= *bytepos;
     82             //Advance the stream byte pointer.
     83             bytepos++;
     84             //Decrement the number of bits left to read.
     85             numberOfBits -= BITS_PER_UINT8;
     86         }
     87         else    //Read one or more bits at a time.
     88         {
     89             //Define the bitmask corresponding to the number of bits
     90             //to read from the current byte.
     91             //This is implemented as a static look-up table for efficiency.
     92             static const uint8 bitmask[] =
     93             {
     94                 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff
     95             };
     96 
     97             //Process the bits in the current byte...
     98 
     99             //Determine the number of bits remaining in the current byte of the stream.
    100             //This is the upper limit on the number of bits we will read
    101             //this through the loop.
    102             uint8 bitsFromThisByte = bitpos + 1;
    103             //If more bits remain then we need, only take what we need.
    104             if (bitsFromThisByte > numberOfBits) bitsFromThisByte = numberOfBits;
    105 
    106             //Shift the output value over to make room for the new bits to read.
    107             output <<= bitsFromThisByte;
    108             //OR in the bits from the stream.
    109             //This reads the current byte from the stream,
    110             //shifts it over so the bits we want are at the LS end,
    111             //and masks off all of the bits except the ones we want.
    112             output |= ((*bytepos) >> (bitpos - (bitsFromThisByte - 1))) & bitmask[bitsFromThisByte];
    113 
    114             //Decrement the numberOfBits remaining...
    115             numberOfBits -= bitsFromThisByte;
    116             //...and advance the bitpos and bytepos pointers.
    117             NextBits(bitsFromThisByte);
    118         }
    119     }
    120 
    121     return output;
    122 }
    123 
    124 
    125 OSCL_EXPORT_REF uint8 BitStreamParser::ReadUInt8(void)
    126 {
    127     //If bitpos is not on a byte boundary, have to use ReadBits...
    128     if (bitpos != MOST_SIG_BIT) return ReadBits(BITS_PER_UINT8);
    129 
    130     // Make sure the current bytepos doesn't exceed the size of the buffer
    131     if (bytepos >= (start + size))
    132     {
    133         OSCL_LEAVE(OsclErrOverflow);
    134     }
    135     uint8 read = *bytepos;
    136     bytepos++;
    137 
    138     return read;
    139 }
    140 
    141 
    142 OSCL_EXPORT_REF uint16 BitStreamParser::ReadUInt16(void)
    143 {
    144     uint16 read;
    145     ((uint8*)&read)[0] = ReadUInt8();
    146     ((uint8*)&read)[1] = ReadUInt8();
    147     big_endian_to_host((char*)&read, sizeof(read));
    148     return read;
    149 }
    150 
    151 
    152 OSCL_EXPORT_REF uint32 BitStreamParser::ReadUInt32(void)
    153 {
    154     uint32 read;
    155     ((uint8*)&read)[0] = ReadUInt8();
    156     ((uint8*)&read)[1] = ReadUInt8();
    157     ((uint8*)&read)[2] = ReadUInt8();
    158     ((uint8*)&read)[3] = ReadUInt8();
    159     big_endian_to_host((char*)&read, sizeof(read));
    160     return read;
    161 }
    162 
    163 
    164 OSCL_EXPORT_REF void BitStreamParser::WriteBits(uint8 numberOfBits, const uint8* data)
    165 {
    166     //This is not the most efficient algorithm, but it is the least complex.
    167     //Treat "data" as an input stream.
    168     BitStreamParser input(const_cast<uint8*>(data), BITS_TO_BYTES(numberOfBits));
    169     //Skip over the unused bits.
    170     input.NextBits(input.BitsLeft() - numberOfBits);
    171     //Loop through each bit to process...
    172     while (numberOfBits)
    173     {
    174         uint8 bitmask = 1 << bitpos;
    175         //READ
    176         uint8 byte = *bytepos;
    177         //MODIFY
    178         byte &= ~(bitmask);                      //Clear the bit being written.
    179         byte |= (input.ReadBits(1) << bitpos); //Write the bit.
    180         //WRITE
    181         *bytepos = byte;
    182         //Advance the bit pointer
    183         NextBit();
    184         numberOfBits--;
    185     }
    186 }
    187 
    188 
    189 OSCL_EXPORT_REF void BitStreamParser::WriteUInt8(uint8 data)
    190 {
    191     if (bitpos != MOST_SIG_BIT)
    192     {
    193         WriteBits(BITS_PER_BYTE, &data);
    194     }
    195     else
    196     {
    197         if (bytepos >= (start + size))
    198         {
    199             OSCL_LEAVE(OsclErrOverflow);
    200         }
    201         *bytepos = data;
    202         bytepos++;
    203     }
    204 }
    205 
    206 
    207 OSCL_EXPORT_REF void BitStreamParser::WriteUInt16(uint16 data)
    208 {
    209     uint16 be = data;
    210     host_to_big_endian((char*)&be, sizeof(be));
    211     WriteUInt8(((uint8*)&be)[0]);
    212     WriteUInt8(((uint8*)&be)[1]);
    213 }
    214 
    215 
    216 OSCL_EXPORT_REF void BitStreamParser::WriteUInt32(uint32 data)
    217 {
    218     uint32 be = data;
    219     host_to_big_endian((char*)&be, sizeof(be));
    220     WriteUInt8(((uint8*)&be)[0]);
    221     WriteUInt8(((uint8*)&be)[1]);
    222     WriteUInt8(((uint8*)&be)[2]);
    223     WriteUInt8(((uint8*)&be)[3]);
    224 }
    225 
    226 
    227 OSCL_EXPORT_REF void BitStreamParser::NextBits(uint32 numberOfBits)
    228 {
    229     //bitpos counts down from 7 to 0, so subtract it from 7 to get the ascending position.
    230     uint32 newbitpos = numberOfBits  + (MOST_SIG_BIT - bitpos);
    231     //Convert the ascending bit position to a descending position using only the least-significant bits.
    232     bitpos = MOST_SIG_BIT - (newbitpos & LEAST_SIG_3_BITS_MASK);
    233     //Calculate the number of bytes advanced.
    234     bytepos += (newbitpos / BITS_PER_BYTE);
    235     // Make sure bytepos won't exceed the size of the buffer while reading
    236     if (bytepos >= (start + size))
    237     {
    238         OSCL_LEAVE(OsclErrOverflow);
    239     }
    240 }
    241 
    242