• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
29const static int16 NO_BITS_IN_BYTE = 8;
30const static uint8 BYTE_MASK = 0xff;
31
32#include "oscl_mem_basic_functions.h"
33
34OSCL_INLINE bool OsclBinStream::good()
35{
36    return state == GOOD_STATE;
37}
38
39OSCL_INLINE bool OsclBinStream::eof()
40{
41    return state == EOF_STATE;
42}
43
44OSCL_INLINE bool OsclBinStream::fail()
45{
46    return state == FAIL_STATE;
47}
48
49OSCL_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
62OSCL_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
81OSCL_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
93OSCL_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
139OSCL_INLINE uint32 OsclBinStream::PositionInBlock()
140{
141    return pPosition - pBasePosition;
142}
143
144OSCL_INLINE void OsclBinStream::seekFromCurrentPosition(int32 offset)
145{
146    Seek(tellg() + offset);
147}
148
149OSCL_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
168OSCL_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*/
186OSCL_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
205OSCL_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*/
252OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(int8 & data)
253{
254    data = int8(Read_uint8());
255    return *this;
256}
257
258OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(uint8 & data)
259{
260    data = Read_uint8();
261    return *this;
262}
263
264OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(int16 & data)
265{
266    data = int16(Read_uint16());
267
268    return *this;
269}
270
271OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(uint16 & data)
272{
273    data = Read_uint16();
274
275    return *this;
276}
277
278OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(int32 & data)
279{
280    data = int32(Read_uint32());
281    return *this;
282}
283
284OSCL_INLINE OsclBinIStreamLittleEndian & OsclBinIStreamLittleEndian::operator>>(uint32 & data)
285{
286    data = Read_uint32();
287    return *this;
288}
289
290OSCL_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
313OSCL_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*/
359OSCL_INLINE void OsclBinIStreamBigEndian::Read(int8 & data)
360{
361    data = int8(Read_uint8());
362}
363
364OSCL_INLINE void OsclBinIStreamBigEndian::Read(uint8 & data)
365{
366    data = Read_uint8();
367}
368
369OSCL_INLINE void OsclBinIStreamBigEndian::Read(int16 & data)
370{
371    data = int16(Read_uint16());
372}
373
374OSCL_INLINE void OsclBinIStreamBigEndian::Read(uint16 & data)
375{
376    data = Read_uint16();
377}
378
379OSCL_INLINE void OsclBinIStreamBigEndian::Read(int32 & data)
380{
381    data = int32(Read_uint32());
382}
383
384OSCL_INLINE void OsclBinIStreamBigEndian::Read(uint32 & data)
385{
386    data = Read_uint32();
387}
388
389OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(int8 & data)
390{
391    data = int8(Read_uint8());
392    return *this;
393}
394
395OSCL_INLINE OsclBinIStream & OsclBinIStreamBigEndian::operator>>(uint8 & data)
396{
397    data = Read_uint8();
398    return *this;
399}
400
401OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(int16 & data)
402{
403    data = int16(Read_uint16());
404    return *this;
405}
406
407OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(uint16 & data)
408{
409    data = Read_uint16();
410    return *this;
411}
412
413OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(int32 & data)
414{
415    data = int32(Read_uint32());
416    return *this;
417}
418
419OSCL_INLINE OsclBinIStreamBigEndian & OsclBinIStreamBigEndian::operator>>(uint32 & data)
420{
421    data = Read_uint32();
422    return *this;
423}
424
425OSCL_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
449OSCL_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
487OSCL_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*/
504OSCL_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
514OSCL_INLINE OsclBinOStreamLittleEndian & OsclBinOStreamLittleEndian::operator<<(const uint8 & data)
515{
516    if (ReserveSpace(sizeof(data)))
517    {
518        *pPosition++ = data;
519    }
520    return *this;
521}
522
523OSCL_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
533OSCL_INLINE OsclBinOStreamLittleEndian & OsclBinOStreamLittleEndian::operator<<(const uint16 & data)
534{
535    if (ReserveSpace(sizeof(data)))
536    {
537        WriteUnsignedShort(data);
538    }
539    return *this;
540}
541
542OSCL_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
552OSCL_INLINE OsclBinOStreamLittleEndian & OsclBinOStreamLittleEndian::operator<<(const uint32 & data)
553{
554    if (ReserveSpace(sizeof(data)))
555    {
556        WriteUnsignedLong(data);
557    }
558
559    return *this;
560}
561
562OSCL_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
577OSCL_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
596OSCL_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
607OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const uint8 & data)
608{
609    if (ReserveSpace(sizeof(data)))
610    {
611        *pPosition++ = data;
612    }
613    return *this;
614}
615
616OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const int16 & data)
617{
618    if (ReserveSpace(sizeof(data)))
619    {
620        WriteUnsignedShort((uint16)data);
621    }
622    return *this;
623}
624
625OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const uint16 & data)
626{
627    if (ReserveSpace(sizeof(data)))
628    {
629        WriteUnsignedShort(data);
630    }
631    return *this;
632}
633
634OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const int32 & data)
635{
636    if (ReserveSpace(sizeof(data)))
637    {
638        WriteUnsignedLong(uint32(data));
639    }
640    return *this;
641}
642
643OSCL_INLINE OsclBinOStreamBigEndian & OsclBinOStreamBigEndian::operator<<(const uint32 & data)
644{
645    if (ReserveSpace(sizeof(data)))
646    {
647        WriteUnsignedLong(data);
648    }
649
650    return *this;
651}
652
653OSCL_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
668OSCL_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