You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
341 lines
12 KiB
341 lines
12 KiB
/* |
|
* The Progressive Graphics File; http://www.libpgf.org |
|
* |
|
* $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $ |
|
* $Revision: 229 $ |
|
* |
|
* This file Copyright (C) 2006 xeraina GmbH, Switzerland |
|
* |
|
* This program is free software; you can redistribute it and/or |
|
* modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE |
|
* as published by the Free Software Foundation; either version 2.1 |
|
* of the License, or (at your option) any later version. |
|
* |
|
* This program is distributed in the hope that it will be useful, |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
* GNU General Public License for more details. |
|
* |
|
* You should have received a copy of the GNU General Public License |
|
* along with this program; if not, write to the Free Software |
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
|
*/ |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// @file Bitstream.h |
|
/// @brief PGF bit-stream operations |
|
/// @author C. Stamm |
|
|
|
#ifndef PGF_BITSTREAM_H |
|
#define PGF_BITSTREAM_H |
|
|
|
#include "PGFtypes.h" |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
// constants |
|
//static const WordWidth = 32; |
|
//static const WordWidthLog = 5; |
|
static const UINT32 Filled = 0xFFFFFFFF; |
|
|
|
/// @brief Make 64 bit unsigned integer from two 32 bit unsigned integers |
|
#define MAKEU64(a, b) ((UINT64) (((UINT32) (a)) | ((UINT64) ((UINT32) (b))) << 32)) |
|
|
|
/* |
|
static UINT8 lMask[] = { |
|
0x00, // 00000000 |
|
0x80, // 10000000 |
|
0xc0, // 11000000 |
|
0xe0, // 11100000 |
|
0xf0, // 11110000 |
|
0xf8, // 11111000 |
|
0xfc, // 11111100 |
|
0xfe, // 11111110 |
|
0xff, // 11111111 |
|
}; |
|
*/ |
|
// these procedures have to be inlined because of performance reasons |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Set one bit of a bit stream to 1 |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
inline void SetBit(UINT32* stream, UINT32 pos) { |
|
stream[pos >> WordWidthLog] |= (1 << (pos%WordWidth)); |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Set one bit of a bit stream to 0 |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
inline void ClearBit(UINT32* stream, UINT32 pos) { |
|
stream[pos >> WordWidthLog] &= ~(1 << (pos%WordWidth)); |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Return one bit of a bit stream |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
/// @return bit at position pos of bit stream stream |
|
inline bool GetBit(UINT32* stream, UINT32 pos) { |
|
return (stream[pos >> WordWidthLog] & (1 << (pos%WordWidth))) > 0; |
|
|
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Compare k-bit binary representation of stream at position pos with val |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
/// @param k Number of bits to compare |
|
/// @param val Value to compare with |
|
/// @return true if equal |
|
inline bool CompareBitBlock(UINT32* stream, UINT32 pos, UINT32 k, UINT32 val) { |
|
const UINT32 iLoInt = pos >> WordWidthLog; |
|
const UINT32 iHiInt = (pos + k - 1) >> WordWidthLog; |
|
ASSERT(iLoInt <= iHiInt); |
|
const UINT32 mask = (Filled >> (WordWidth - k)); |
|
|
|
if (iLoInt == iHiInt) { |
|
// fits into one integer |
|
val &= mask; |
|
val <<= (pos%WordWidth); |
|
return (stream[iLoInt] & val) == val; |
|
} else { |
|
// must be splitted over integer boundary |
|
UINT64 v1 = MAKEU64(stream[iLoInt], stream[iHiInt]); |
|
UINT64 v2 = UINT64(val & mask) << (pos%WordWidth); |
|
return (v1 & v2) == v2; |
|
} |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Store k-bit binary representation of val in stream at position pos |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
/// @param val Value to store in stream at position pos |
|
/// @param k Number of bits of integer representation of val |
|
inline void SetValueBlock(UINT32* stream, UINT32 pos, UINT32 val, UINT32 k) { |
|
const UINT32 offset = pos%WordWidth; |
|
const UINT32 iLoInt = pos >> WordWidthLog; |
|
const UINT32 iHiInt = (pos + k - 1) >> WordWidthLog; |
|
ASSERT(iLoInt <= iHiInt); |
|
const UINT32 loMask = Filled << offset; |
|
const UINT32 hiMask = Filled >> (WordWidth - 1 - ((pos + k - 1)%WordWidth)); |
|
|
|
if (iLoInt == iHiInt) { |
|
// fits into one integer |
|
stream[iLoInt] &= ~(loMask & hiMask); // clear bits |
|
stream[iLoInt] |= val << offset; // write value |
|
} else { |
|
// must be splitted over integer boundary |
|
stream[iLoInt] &= ~loMask; // clear bits |
|
stream[iLoInt] |= val << offset; // write lower part of value |
|
stream[iHiInt] &= ~hiMask; // clear bits |
|
stream[iHiInt] |= val >> (WordWidth - offset); // write higher part of value |
|
} |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Read k-bit number from stream at position pos |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
/// @param k Number of bits to read: 1 <= k <= 32 |
|
inline UINT32 GetValueBlock(UINT32* stream, UINT32 pos, UINT32 k) { |
|
UINT32 count, hiCount; |
|
const UINT32 iLoInt = pos >> WordWidthLog; // integer of first bit |
|
const UINT32 iHiInt = (pos + k - 1) >> WordWidthLog; // integer of last bit |
|
const UINT32 loMask = Filled << (pos%WordWidth); |
|
const UINT32 hiMask = Filled >> (WordWidth - 1 - ((pos + k - 1)%WordWidth)); |
|
|
|
if (iLoInt == iHiInt) { |
|
// inside integer boundary |
|
count = stream[iLoInt] & (loMask & hiMask); |
|
count >>= pos%WordWidth; |
|
} else { |
|
// overlapping integer boundary |
|
count = stream[iLoInt] & loMask; |
|
count >>= pos%WordWidth; |
|
hiCount = stream[iHiInt] & hiMask; |
|
hiCount <<= WordWidth - (pos%WordWidth); |
|
count |= hiCount; |
|
} |
|
return count; |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Clear block of size at least len at position pos in stream |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
/// @param len Number of bits set to 0 |
|
inline void ClearBitBlock(UINT32* stream, UINT32 pos, UINT32 len) { |
|
ASSERT(len > 0); |
|
const UINT32 iFirstInt = pos >> WordWidthLog; |
|
const UINT32 iLastInt = (pos + len - 1) >> WordWidthLog; |
|
|
|
const UINT32 startMask = Filled << (pos%WordWidth); |
|
// const UINT32 endMask=Filled>>(WordWidth-1-((pos+len-1)%WordWidth)); |
|
|
|
if (iFirstInt == iLastInt) { |
|
stream[iFirstInt] &= ~(startMask /*& endMask*/); |
|
} else { |
|
stream[iFirstInt] &= ~startMask; |
|
for (UINT32 i = iFirstInt + 1; i <= iLastInt; i++) { // changed <= |
|
stream[i] = 0; |
|
} |
|
//stream[iLastInt] &= ~endMask; |
|
} |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Set block of size at least len at position pos in stream |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
/// @param len Number of bits set to 1 |
|
inline void SetBitBlock(UINT32* stream, UINT32 pos, UINT32 len) { |
|
ASSERT(len > 0); |
|
|
|
const UINT32 iFirstInt = pos >> WordWidthLog; |
|
const UINT32 iLastInt = (pos + len - 1) >> WordWidthLog; |
|
|
|
const UINT32 startMask = Filled << (pos%WordWidth); |
|
// const UINT32 endMask=Filled>>(WordWidth-1-((pos+len-1)%WordWidth)); |
|
|
|
if (iFirstInt == iLastInt) { |
|
stream[iFirstInt] |= (startMask /*& endMask*/); |
|
} else { |
|
stream[iFirstInt] |= startMask; |
|
for (UINT32 i = iFirstInt + 1; i <= iLastInt; i++) { // changed <= |
|
stream[i] = Filled; |
|
} |
|
//stream[iLastInt] &= ~endMask; |
|
} |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Returns the distance to the next 1 in stream at position pos. |
|
/// If no 1 is found within len bits, then len is returned. |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
/// @param len size of search area (in bits) |
|
/// return The distance to the next 1 in stream at position pos |
|
inline UINT32 SeekBitRange(UINT32* stream, UINT32 pos, UINT32 len) { |
|
UINT32 count = 0; |
|
UINT32 testMask = 1 << (pos%WordWidth); |
|
UINT32* word = stream + (pos >> WordWidthLog); |
|
|
|
while (((*word & testMask) == 0) && (count < len)) { |
|
count++; |
|
testMask <<= 1; |
|
if (!testMask) { |
|
word++; testMask = 1; |
|
|
|
// fast steps if all bits in a word are zero |
|
while ((count + WordWidth <= len) && (*word == 0)) { |
|
word++; |
|
count += WordWidth; |
|
} |
|
} |
|
} |
|
|
|
return count; |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Returns the distance to the next 0 in stream at position pos. |
|
/// If no 0 is found within len bits, then len is returned. |
|
/// @param stream A bit stream stored in array of unsigned integers |
|
/// @param pos A valid zero-based position in the bit stream |
|
/// @param len size of search area (in bits) |
|
/// return The distance to the next 0 in stream at position pos |
|
inline UINT32 SeekBit1Range(UINT32* stream, UINT32 pos, UINT32 len) { |
|
UINT32 count = 0; |
|
UINT32 testMask = 1 << (pos%WordWidth); |
|
UINT32* word = stream + (pos >> WordWidthLog); |
|
|
|
while (((*word & testMask) != 0) && (count < len)) { |
|
count++; |
|
testMask <<= 1; |
|
if (!testMask) { |
|
word++; testMask = 1; |
|
|
|
// fast steps if all bits in a word are one |
|
while ((count + WordWidth <= len) && (*word == Filled)) { |
|
word++; |
|
count += WordWidth; |
|
} |
|
} |
|
} |
|
return count; |
|
} |
|
/* |
|
////////////////////////////////////////////////////////////////////// |
|
/// BitCopy: copies k bits from source to destination |
|
/// Note: only 8 bits are copied at a time, if speed is an issue, a more |
|
/// complicated but faster 64 bit algorithm should be used. |
|
inline void BitCopy(const UINT8 *sStream, UINT32 sPos, UINT8 *dStream, UINT32 dPos, UINT32 k) { |
|
ASSERT(k > 0); |
|
|
|
div_t divS = div(sPos, 8); |
|
div_t divD = div(dPos, 8); |
|
UINT32 sOff = divS.rem; |
|
UINT32 dOff = divD.rem; |
|
INT32 tmp = div(dPos + k - 1, 8).quot; |
|
|
|
const UINT8 *sAddr = sStream + divS.quot; |
|
UINT8 *dAddrS = dStream + divD.quot; |
|
UINT8 *dAddrE = dStream + tmp; |
|
UINT8 eMask; |
|
|
|
UINT8 destSB = *dAddrS; |
|
UINT8 destEB = *dAddrE; |
|
UINT8 *dAddr; |
|
UINT8 prec; |
|
INT32 shiftl, shiftr; |
|
|
|
if (dOff > sOff) { |
|
prec = 0; |
|
shiftr = dOff - sOff; |
|
shiftl = 8 - dOff + sOff; |
|
} else { |
|
prec = *sAddr << (sOff - dOff); |
|
shiftr = 8 - sOff + dOff; |
|
shiftl = sOff - dOff; |
|
sAddr++; |
|
} |
|
|
|
for (dAddr = dAddrS; dAddr < dAddrE; dAddr++, sAddr++) { |
|
*dAddr = prec | (*sAddr >> shiftr); |
|
prec = *sAddr << shiftl; |
|
} |
|
|
|
if ((sPos + k)%8 == 0) { |
|
*dAddr = prec; |
|
} else { |
|
*dAddr = prec | (*sAddr >> shiftr); |
|
} |
|
|
|
eMask = lMask[dOff]; |
|
*dAddrS = (destSB & eMask) | (*dAddrS & (~eMask)); |
|
|
|
INT32 mind = (dPos + k) % 8; |
|
eMask = (mind) ? lMask[mind] : lMask[8]; |
|
*dAddrE = (destEB & (~eMask)) | (*dAddrE & eMask); |
|
} |
|
*/ |
|
////////////////////////////////////////////////////////////////////// |
|
/// Compute bit position of the next 32-bit word |
|
/// @param pos current bit stream position |
|
/// @return bit position of next 32-bit word |
|
inline UINT32 AlignWordPos(UINT32 pos) { |
|
// return ((pos + WordWidth - 1) >> WordWidthLog) << WordWidthLog; |
|
return DWWIDTHBITS(pos); |
|
} |
|
|
|
////////////////////////////////////////////////////////////////////// |
|
/// Compute number of the 32-bit words |
|
/// @param pos Current bit stream position |
|
/// @return Number of 32-bit words |
|
inline UINT32 NumberOfWords(UINT32 pos) { |
|
return (pos + WordWidth - 1) >> WordWidthLog; |
|
} |
|
|
|
#endif //PGF_BITSTREAM_H
|
|
|