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 // -*- c++ -*-
     19 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     20 
     21 //                 O S C L _ B I N _ S T R E A M
     22 
     23 // = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
     24 
     25 /*
     26 ** Constants
     27 */
     28 
     29 const static int16 NO_BITS_IN_BYTE = 8;
     30 const static uint8 BYTE_MASK = 0xff;
     31 
     32 #include "oscl_mem_basic_functions.h"
     33 
     34 OSCL_INLINE bool OsclBinStream::good()
     35 {
     36     return state == GOOD_STATE;
     37 }
     38 
     39 OSCL_INLINE bool OsclBinStream::eof()
     40 {
     41     return state == EOF_STATE;
     42 }
     43 
     44 OSCL_INLINE bool OsclBinStream::fail()
     45 {
     46     return state == FAIL_STATE;
     47 }
     48 
     49 OSCL_INLINE void OsclBinStream::Attach(void * buffer, uint32 l_length)
     50 {
     51     fragsLeft = 0;
     52     pBasePosition = (uint8 *)buffer;
     53     pPosition = pBasePosition;
     54     length = l_length;
     55     state = GOOD_STATE;
     56     specialFragBuffer.ptr = buffer;
     57     specialFragBuffer.len = l_length;
     58     numFrags = 1;
     59     firstFragPtr = &specialFragBuffer;
     60 }
     61 
     62 OSCL_INLINE void OsclBinStream::Attach(const uint32 numFragments, const OsclMemoryFragment * fragPtr)
     63 {
     64     pBasePosition = (uint8 *)fragPtr->ptr;
     65     pPosition = pBasePosition;
     66     numFrags = numFragments;
     67     firstFragPtr  = fragPtr;
     68     length = fragPtr->len;
     69     if (numFragments > 1)
     70     {
     71         fragsLeft = numFragments - 1;
     72         nextFragPtr = fragPtr + 1;
     73     }
     74     else
     75     {
     76         fragsLeft = 0;
     77     }
     78     state = GOOD_STATE;
     79 }
     80 
     81 OSCL_INLINE uint32 OsclBinStream::tellg()
     82 {
     83     uint32 pos = 0;
     84     for (int ii = 0; ii < numFrags - fragsLeft - 1; ii++)
     85     {
     86         pos += firstFragPtr[ii].len;
     87     }
     88     pos += PositionInBlock();
     89 
     90     return pos;
     91 }
     92 
     93 OSCL_INLINE void OsclBinStream::Seek(uint32 absPosition)
     94 {
     95     uint32 pos = 0;
     96     int fragIndex;
     97 
     98     for (fragIndex = 0;
     99             fragIndex < numFrags && absPosition >= pos + firstFragPtr[fragIndex].len;
    100             fragIndex++)
    101     {
    102         pos += firstFragPtr[fragIndex].len;
    103     }
    104 
    105     if (fragIndex >= numFrags)
    106     {
    107         fragsLeft = 0;
    108         pBasePosition = (uint8 *)firstFragPtr[numFrags-1].ptr;
    109         length = firstFragPtr[numFrags-1].len;
    110         pPosition = pBasePosition + length;
    111         if (absPosition == pos)
    112         {
    113             state = EOF_STATE;
    114         }
    115         else
    116         {
    117             state = FAIL_STATE;
    118         }
    119         return;
    120     }
    121 
    122     // otherwise there is more data
    123     nextFragPtr = &firstFragPtr[fragIndex + 1];
    124     fragsLeft = numFrags - fragIndex - 1;
    125     pBasePosition = (uint8 *)firstFragPtr[fragIndex].ptr;
    126     length = firstFragPtr[fragIndex].len;
    127     uint32 reqBytes = absPosition - pos;
    128     if (reqBytes <= length)
    129     {
    130         pPosition = pBasePosition + reqBytes;
    131     }
    132     else
    133     {
    134         pPosition = pBasePosition + length;
    135         state = FAIL_STATE;
    136     }
    137 }
    138 
    139 OSCL_INLINE uint32 OsclBinStream::PositionInBlock()
    140 {
    141     return pPosition - pBasePosition;
    142 }
    143 
    144 OSCL_INLINE void OsclBinStream::seekFromCurrentPosition(int32 offset)
    145 {
    146     Seek(tellg() + offset);
    147 }
    148 
    149 OSCL_INLINE bool OsclBinStream::ReserveSpace(uint32 size)
    150 {
    151     if (fail())
    152     {
    153         return false;
    154     }
    155     uint32 newSize = PositionInBlock() + size;
    156     if (newSize > length)
    157     {
    158         state = FAIL_STATE;
    159         return false;
    160     }
    161     if (newSize == length)
    162     {
    163         state = EOF_STATE;
    164     }
    165     return true;
    166 }
    167 
    168 OSCL_INLINE bool OsclBinStream::HaveRoomInCurrentBlock(uint32 size)
    169 {
    170     uint32 pos = PositionInBlock() + size;
    171     if (pos < length)
    172     {
    173         return true;
    174     }
    175     if (pos == length && fragsLeft == 0)
    176     {
    177         state = EOF_STATE;
    178     }
    179     return (pos <= length);
    180 }
    181 
    182 /*
    183 ** Class OsclBinIStream
    184 **      This class implements the basic stream functions for an input stream.
    185 */
    186 OSCL_INLINE uint8 OsclBinIStream::Read_uint8()
    187 {
    188     if (HaveRoomInCurrentBlock(sizeof(uint8)))
    189     {
    190         return (*pPosition++);
    191     }
    192     if (fragsLeft)
    193     {
    194         pBasePosition = (uint8 *)nextFragPtr->ptr;
    195         pPosition = pBasePosition;
    196         length = nextFragPtr->len;
    197         fragsLeft--;
    198         nextFragPtr++;
    199         return (*pPosition++);
    200     }
    201     state = FAIL_STATE;
    202     return 0;
    203 }
    204 
    205 OSCL_INLINE OsclBinIStream & OsclBinIStream::get(
    206     int8 * data,    /* Pointer to the place to store the bytes read */
    207     int32 size    /* Number of bytes to read */
    208 )
    209 {
    210     if (HaveRoomInCurrentBlock(size))
    211     {
    212         oscl_memcpy(data, pPosition, size);
    213         pPosition += size;
    214     }
    215     else
    216     {
    217         uint32 pos = PositionInBlock();
    218         uint32 bytesToCopy = length - pos;
    219         oscl_memcpy(data, pPosition, bytesToCopy);
    220         data += bytesToCopy;
    221         uint32 bytesLeft = size - bytesToCopy;
    222         while (bytesLeft > 0 && fragsLeft)
    223         {
    224             pBasePosition = (uint8 *)nextFragPtr->ptr;
    225             pPosition = pBasePosition;
    226             length = nextFragPtr->len;
    227             fragsLeft--;
    228             nextFragPtr++;
    229 
    230             if (bytesLeft <= length)
    231             {
    232                 bytesToCopy = bytesLeft;
    233             }
    234             else
    235             {
    236                 bytesToCopy = length;
    237             }
    238 
    239             oscl_memcpy(data, pPosition, bytesToCopy);
    240             data += bytesToCopy;
    241             pPosition += bytesToCopy;
    242             bytesLeft -= bytesToCopy;
    243         }
    244     }
    245     return *this;
    246 }
    247 
    248 /*
    249 ** Class OsclBinIStreamLittleEndian
    250 **      This class implements a binary input stream using little endian byte ordering
    251 */
    252 OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(int8 & data)
    253 {
    254     data = int8(Read_uint8());
    255     return *this;
    256 }
    257 
    258 OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(uint8 & data)
    259 {
    260     data = Read_uint8();
    261     return *this;
    262 }
    263 
    264 OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(int16 & data)
    265 {
    266     data = int16(Read_uint16());
    267 
    268     return *this;
    269 }
    270 
    271 OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(uint16 & data)
    272 {
    273     data = Read_uint16();
    274 
    275     return *this;
    276 }
    277 
    278 OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(int32 & data)
    279 {
    280     data = int32(Read_uint32());
    281     return *this;
    282 }
    283 
    284 OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(uint32 & data)
    285 {
    286     data = Read_uint32();
    287     return *this;
    288 }
    289 
    290 OSCL_INLINE uint16 OsclBinIStreamLittleEndian::Read_uint16()
    291 {
    292     if (HaveRoomInCurrentBlock(sizeof(uint16)))
    293     {
    294 #if defined(BYTE_ORDER_LITTLE_ENDIAN) && !defined(INTEGERS_WORD_ALIGNED)
    295         uint16 *ptr = (uint16 *)pPosition;
    296         pPosition += sizeof(uint16);
    297         return *ptr;
    298 #else
    299         uint16 byteB = *pPosition++;
    300         uint16 byteA = *pPosition++;
    301 
    302         return ((byteA << NO_BITS_IN_BYTE) | byteB);
    303 #endif
    304     }
    305     else
    306     {
    307         uint16 byteB = Read_uint8();
    308         uint16 byteA = Read_uint8();
    309         return ((byteA << NO_BITS_IN_BYTE) | byteB);
    310     }
    311 }
    312 
    313 OSCL_INLINE uint32 OsclBinIStreamLittleEndian::Read_uint32()
    314 {
    315     if (HaveRoomInCurrentBlock(sizeof(uint32)))
    316     {
    317 #if defined(BYTE_ORDER_LITTLE_ENDIAN) && !defined(INTEGERS_WORD_ALIGNED)
    318         uint32 *ptr = (uint32 *)pPosition;
    319         pPosition += sizeof(uint32);
    320         return *ptr;
    321 #else
    322         uint32 result;
    323         uint8 byteD = *pPosition++;
    324         uint8 byteC = *pPosition++;
    325         uint8 byteB = *pPosition++;
    326         uint8 byteA = *pPosition++;
    327 
    328         result = byteA;
    329         result = (result << NO_BITS_IN_BYTE) | byteB;
    330         result = (result << NO_BITS_IN_BYTE) | byteC;
    331         result = (result << NO_BITS_IN_BYTE) | byteD;
    332 
    333         return result;
    334 #endif
    335     }
    336     else
    337     {
    338         uint32 result;
    339         uint8 byteD = Read_uint8();
    340         uint8 byteC = Read_uint8();
    341         uint8 byteB = Read_uint8();
    342         uint8 byteA = Read_uint8();
    343 
    344         result = byteA;
    345         result = (result << NO_BITS_IN_BYTE) | byteB;
    346         result = (result << NO_BITS_IN_BYTE) | byteC;
    347         result = (result << NO_BITS_IN_BYTE) | byteD;
    348 
    349         return result;
    350     }
    351 }
    352 
    353 
    354 
    355 /*
    356 ** Class OsclBinIStreamBigEndian
    357 **      This class implements a binary input stream using big endian byte ordering
    358 */
    359 OSCL_INLINE void OsclBinIStreamBigEndian::Read(int8 & data)
    360 {
    361     data = int8(Read_uint8());
    362 }
    363 
    364 OSCL_INLINE void OsclBinIStreamBigEndian::Read(uint8 & data)
    365 {
    366     data = Read_uint8();
    367 }
    368 
    369 OSCL_INLINE void OsclBinIStreamBigEndian::Read(int16 & data)
    370 {
    371     data = int16(Read_uint16());
    372 }
    373 
    374 OSCL_INLINE void OsclBinIStreamBigEndian::Read(uint16 & data)
    375 {
    376     data = Read_uint16();
    377 }
    378 
    379 OSCL_INLINE void OsclBinIStreamBigEndian::Read(int32 & data)
    380 {
    381     data = int32(Read_uint32());
    382 }
    383 
    384 OSCL_INLINE void OsclBinIStreamBigEndian::Read(uint32 & data)
    385 {
    386     data = Read_uint32();
    387 }
    388 
    389 OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(int8 & data)
    390 {
    391     data = int8(Read_uint8());
    392     return *this;
    393 }
    394 
    395 OSCL_INLINE OsclBinIStream & OsclBinIStreamBigEndian::operator>>(uint8 & data)
    396 {
    397     data = Read_uint8();
    398     return *this;
    399 }
    400 
    401 OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(int16 & data)
    402 {
    403     data = int16(Read_uint16());
    404     return *this;
    405 }
    406 
    407 OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(uint16 & data)
    408 {
    409     data = Read_uint16();
    410     return *this;
    411 }
    412 
    413 OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(int32 & data)
    414 {
    415     data = int32(Read_uint32());
    416     return *this;
    417 }
    418 
    419 OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(uint32 & data)
    420 {
    421     data = Read_uint32();
    422     return *this;
    423 }
    424 
    425 OSCL_INLINE uint16 OsclBinIStreamBigEndian::Read_uint16()
    426 {
    427     if (HaveRoomInCurrentBlock(sizeof(uint16)))
    428     {
    429 #if defined(BYTE_ORDER_BIG_ENDIAN) && !defined(INTEGERS_WORD_ALIGNED)
    430         uint16 *ptr = (uint16 *)pPosition;
    431         pPosition += sizeof(uint16);
    432         return *ptr;
    433 #else
    434         uint16 byteA = *pPosition++;
    435         uint16 byteB = *pPosition++;
    436 
    437         return ((byteA << NO_BITS_IN_BYTE) | byteB);
    438 #endif
    439     }
    440     else
    441     {
    442         uint16 byteA = Read_uint8();
    443         uint16 byteB = Read_uint8();
    444 
    445         return ((byteA << NO_BITS_IN_BYTE) | byteB);
    446     }
    447 }
    448 
    449 OSCL_INLINE uint32 OsclBinIStreamBigEndian::Read_uint32()
    450 {
    451     if (HaveRoomInCurrentBlock(sizeof(uint32)))
    452     {
    453 #if defined(BYTE_ORDER_BIG_ENDIAN) && !defined(INTEGERS_WORD_ALIGNED)
    454         uint32 *ptr = (uint32 *)pPosition;
    455         pPosition += sizeof(uint32);
    456         return *ptr;
    457 #else
    458         uint32 result;
    459 
    460         result = *pPosition++;
    461         result = (result << NO_BITS_IN_BYTE) | *pPosition++;
    462         result = (result << NO_BITS_IN_BYTE) | *pPosition++;
    463         result = (result << NO_BITS_IN_BYTE) | *pPosition++;
    464 
    465         return result;
    466 #endif
    467     }
    468     else
    469     {
    470         uint32 result;
    471 
    472         result = Read_uint8();
    473         result = (result << NO_BITS_IN_BYTE) | Read_uint8();
    474         result = (result << NO_BITS_IN_BYTE) | Read_uint8();
    475         result = (result << NO_BITS_IN_BYTE) | Read_uint8();
    476 
    477         return result;
    478     }
    479 }
    480 
    481 
    482 /*
    483 ** Class OsclBinOStream
    484 **      This class implements the basic stream functions for an output stream.
    485 */
    486 
    487 OSCL_INLINE OsclBinOStream & OsclBinOStream::write(
    488     const int8 * data,      /* data to store */
    489     int32 size      /* length of data to store */
    490 )
    491 {
    492     if (ReserveSpace(size))
    493     {
    494         oscl_memcpy(pPosition, data, size);
    495         pPosition += size;
    496     }
    497     return *this;
    498 }
    499 
    500 /*
    501 ** Class OsclBinOStreamLittleEndian
    502 **      This class implements a binary output stream using little endian byte ordering
    503 */
    504 OSCL_INLINE OsclBinOStreamLittleEndian & OsclBinOStreamLittleEndian::operator<<(const int8 & data)
    505 {
    506     if (ReserveSpace(sizeof(data)))
    507     {
    508         *((int8 *)pPosition) = data;
    509         pPosition++;
    510     }
    511     return *this;
    512 }
    513 
    514 OSCL_INLINE OsclBinOStreamLittleEndian & OsclBinOStreamLittleEndian::operator<<(const uint8 & data)
    515 {
    516     if (ReserveSpace(sizeof(data)))
    517     {
    518         *pPosition++ = data;
    519     }
    520     return *this;
    521 }
    522 
    523 OSCL_INLINE OsclBinOStreamLittleEndian & OsclBinOStreamLittleEndian::operator<<(const int16 & data)
    524 {
    525     if (ReserveSpace(sizeof(data)))
    526     {
    527         WriteUnsignedShort((uint16)data);
    528     }
    529 
    530     return *this;
    531 }
    532 
    533 OSCL_INLINE OsclBinOStreamLittleEndian & OsclBinOStreamLittleEndian::operator<<(const uint16 & data)
    534 {
    535     if (ReserveSpace(sizeof(data)))
    536     {
    537         WriteUnsignedShort(data);
    538     }
    539     return *this;
    540 }
    541 
    542 OSCL_INLINE OsclBinOStreamLittleEndian & OsclBinOStreamLittleEndian::operator<<(const int32 & data)
    543 {
    544     if (ReserveSpace(sizeof(data)))
    545     {
    546         WriteUnsignedLong(uint32(data));
    547     }
    548 
    549     return *this;
    550 }
    551 
    552 OSCL_INLINE OsclBinOStreamLittleEndian & OsclBinOStreamLittleEndian::operator<<(const uint32 & data)
    553 {
    554     if (ReserveSpace(sizeof(data)))
    555     {
    556         WriteUnsignedLong(data);
    557     }
    558 
    559     return *this;
    560 }
    561 
    562 OSCL_INLINE void OsclBinOStreamLittleEndian::WriteUnsignedShort(const uint16 data)
    563 {
    564 #if defined(BYTE_ORDER_LITTLE_ENDIAN) && !defined(INTEGERS_WORD_ALIGNED)
    565     uint16 *ptr = (uint16 *)pPosition;
    566     pPosition += sizeof(uint16);
    567     *ptr = data;
    568 #else
    569     uint8 byteB = (uint8)data;
    570     uint8 byteA = data >> NO_BITS_IN_BYTE;
    571 
    572     *pPosition++ = byteB;
    573     *pPosition++ = byteA;
    574 #endif
    575 }
    576 
    577 OSCL_INLINE void OsclBinOStreamLittleEndian::WriteUnsignedLong(const uint32 data)
    578 {
    579 #if defined(BYTE_ORDER_LITTLE_ENDIAN) && !defined(INTEGERS_WORD_ALIGNED)
    580     uint32 *ptr = (uint32 *)pPosition;
    581     pPosition += sizeof(uint32);
    582     *ptr = data;
    583 #else
    584     uint32 temp = data;
    585     *pPosition++ = (uint8)temp;
    586     temp >>= NO_BITS_IN_BYTE;
    587     *pPosition++ = (uint8)temp;
    588     temp >>= NO_BITS_IN_BYTE;
    589     *pPosition++ = (uint8)temp;
    590     temp >>= NO_BITS_IN_BYTE;
    591     *pPosition++ = (uint8)temp;
    592 #endif
    593 }
    594 
    595 
    596 OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const int8 & data)
    597 {
    598     if (ReserveSpace(sizeof(data)))
    599     {
    600         *((int8 *)pPosition) = data;
    601         pPosition++;
    602     }
    603 
    604     return *this;
    605 }
    606 
    607 OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const uint8 & data)
    608 {
    609     if (ReserveSpace(sizeof(data)))
    610     {
    611         *pPosition++ = data;
    612     }
    613     return *this;
    614 }
    615 
    616 OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const int16 & data)
    617 {
    618     if (ReserveSpace(sizeof(data)))
    619     {
    620         WriteUnsignedShort((uint16)data);
    621     }
    622     return *this;
    623 }
    624 
    625 OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const uint16 & data)
    626 {
    627     if (ReserveSpace(sizeof(data)))
    628     {
    629         WriteUnsignedShort(data);
    630     }
    631     return *this;
    632 }
    633 
    634 OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const int32 & data)
    635 {
    636     if (ReserveSpace(sizeof(data)))
    637     {
    638         WriteUnsignedLong(uint32(data));
    639     }
    640     return *this;
    641 }
    642 
    643 OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const uint32 & data)
    644 {
    645     if (ReserveSpace(sizeof(data)))
    646     {
    647         WriteUnsignedLong(data);
    648     }
    649 
    650     return *this;
    651 }
    652 
    653 OSCL_INLINE void OsclBinOStreamBigEndian::WriteUnsignedShort(const uint16 data)
    654 {
    655 #if defined(BYTE_ORDER_BIG_ENDIAN) && !defined(INTEGERS_WORD_ALIGNED)
    656     uint16 *ptr = (uint16 *)pPosition;
    657     pPosition += sizeof(uint16);
    658     *ptr = data;
    659 #else
    660     uint8 byteB = (uint8)data;
    661     uint8 byteA = data >> NO_BITS_IN_BYTE;
    662 
    663     *pPosition++ = byteA;
    664     *pPosition++ = byteB;
    665 #endif
    666 }
    667 
    668 OSCL_INLINE void OsclBinOStreamBigEndian::WriteUnsignedLong(const uint32 data)
    669 {
    670 #if defined(BYTE_ORDER_BIG_ENDIAN) && !defined(INTEGERS_WORD_ALIGNED)
    671     uint32 *ptr = (uint32 *)pPosition;
    672     pPosition += sizeof(uint32);
    673     *ptr = data;
    674 #else
    675     uint32 temp = data;
    676     uint8 byteD = (uint8)temp;
    677     temp >>= NO_BITS_IN_BYTE;
    678     uint8 byteC = (uint8)temp;
    679     temp >>= NO_BITS_IN_BYTE;
    680     uint8 byteB = (uint8)temp;
    681     temp >>= NO_BITS_IN_BYTE;
    682     uint8 byteA = (uint8)temp;
    683 
    684     *pPosition++ = byteA;
    685     *pPosition++ = byteB;
    686     *pPosition++ = byteC;
    687     *pPosition++ = byteD;
    688 #endif
    689 }
    690