You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
342 lines
12 KiB
C
342 lines
12 KiB
C
/*
|
|
* 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
|