File indexing completed on 2025-01-05 03:56:35

0001 /*
0002  * The Progressive Graphics File; http://www.libpgf.org
0003  *
0004  * $Date: 2006-06-04 22:05:59 +0200 (So, 04 Jun 2006) $
0005  * $Revision: 229 $
0006  *
0007  * This file Copyright (C) 2006 xeraina GmbH, Switzerland
0008  *
0009  * This program is free software; you can redistribute it and/or
0010  * modify it under the terms of the GNU LESSER GENERAL PUBLIC LICENSE
0011  * as published by the Free Software Foundation; either version 2.1
0012  * of the License, or (at your option) any later version.
0013  *
0014  * This program is distributed in the hope that it will be useful,
0015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017  * GNU General Public License for more details.
0018  *
0019  * You should have received a copy of the GNU General Public License
0020  * along with this program; if not, write to the Free Software
0021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
0022  */
0023 
0024 //////////////////////////////////////////////////////////////////////
0025 /// @file Bitstream.h
0026 /// @brief PGF bit-stream operations
0027 /// @author C. Stamm
0028 
0029 #ifndef PGF_BITSTREAM_H
0030 #define PGF_BITSTREAM_H
0031 
0032 #include "PGFtypes.h"
0033 
0034 //////////////////////////////////////////////////////////////////////
0035 // constants
0036 //static const WordWidth = 32;
0037 //static const WordWidthLog = 5;
0038 static const UINT32 Filled = 0xFFFFFFFF;
0039 
0040 /// @brief Make 64 bit unsigned integer from two 32 bit unsigned integers
0041 #define MAKEU64(a, b) ((UINT64) (((UINT32) (a)) | ((UINT64) ((UINT32) (b))) << 32))
0042 
0043 /*
0044 static UINT8 lMask[] = {
0045     0x00,                       // 00000000
0046     0x80,                       // 10000000
0047     0xc0,                       // 11000000
0048     0xe0,                       // 11100000
0049     0xf0,                       // 11110000
0050     0xf8,                       // 11111000
0051     0xfc,                       // 11111100
0052     0xfe,                       // 11111110
0053     0xff,                       // 11111111
0054 };
0055 */
0056 // these procedures have to be inlined because of performance reasons
0057 
0058 //////////////////////////////////////////////////////////////////////
0059 /// Set one bit of a bit stream to 1
0060 /// @param stream A bit stream stored in array of unsigned integers
0061 /// @param pos A valid zero-based position in the bit stream
0062 inline void SetBit(UINT32* stream, UINT32 pos) {
0063     stream[pos >> WordWidthLog] |= (1 << (pos%WordWidth));
0064 }
0065 
0066 //////////////////////////////////////////////////////////////////////
0067 /// Set one bit of a bit stream to 0
0068 /// @param stream A bit stream stored in array of unsigned integers
0069 /// @param pos A valid zero-based position in the bit stream
0070 inline void ClearBit(UINT32* stream, UINT32 pos) {
0071     stream[pos >> WordWidthLog] &= ~(1 << (pos%WordWidth));
0072 }
0073 
0074 //////////////////////////////////////////////////////////////////////
0075 /// Return one bit of a bit stream
0076 /// @param stream A bit stream stored in array of unsigned integers
0077 /// @param pos A valid zero-based position in the bit stream
0078 /// @return bit at position pos of bit stream stream
0079 inline bool GetBit(UINT32* stream, UINT32 pos)  {
0080     return (stream[pos >> WordWidthLog] & (1 << (pos%WordWidth))) > 0;
0081 
0082 }
0083 
0084 //////////////////////////////////////////////////////////////////////
0085 /// Compare k-bit binary representation of stream at position pos with val
0086 /// @param stream A bit stream stored in array of unsigned integers
0087 /// @param pos A valid zero-based position in the bit stream
0088 /// @param k Number of bits to compare
0089 /// @param val Value to compare with
0090 /// @return true if equal
0091 inline bool CompareBitBlock(UINT32* stream, UINT32 pos, UINT32 k, UINT32 val) {
0092     const UINT32 iLoInt = pos >> WordWidthLog;
0093     const UINT32 iHiInt = (pos + k - 1) >> WordWidthLog;
0094     ASSERT(iLoInt <= iHiInt);
0095     const UINT32 mask = (Filled >> (WordWidth - k));
0096 
0097     if (iLoInt == iHiInt) {
0098         // fits into one integer
0099         val &= mask;
0100         val <<= (pos%WordWidth);
0101         return (stream[iLoInt] & val) == val;
0102     } else {
0103         // must be splitted over integer boundary
0104         UINT64 v1 = MAKEU64(stream[iLoInt], stream[iHiInt]);
0105         UINT64 v2 = UINT64(val & mask) << (pos%WordWidth);
0106         return (v1 & v2) == v2;
0107     }
0108 }
0109 
0110 //////////////////////////////////////////////////////////////////////
0111 /// Store k-bit binary representation of val in stream at position pos
0112 /// @param stream A bit stream stored in array of unsigned integers
0113 /// @param pos A valid zero-based position in the bit stream
0114 /// @param val Value to store in stream at position pos
0115 /// @param k Number of bits of integer representation of val
0116 inline void SetValueBlock(UINT32* stream, UINT32 pos, UINT32 val, UINT32 k) {
0117     const UINT32 offset = pos%WordWidth;
0118     const UINT32 iLoInt = pos >> WordWidthLog;
0119     const UINT32 iHiInt = (pos + k - 1) >> WordWidthLog;
0120     ASSERT(iLoInt <= iHiInt);
0121     const UINT32 loMask = Filled << offset;
0122     const UINT32 hiMask = Filled >> (WordWidth - 1 - ((pos + k - 1)%WordWidth));
0123 
0124     if (iLoInt == iHiInt) {
0125         // fits into one integer
0126         stream[iLoInt] &= ~(loMask & hiMask); // clear bits
0127         stream[iLoInt] |= val << offset; // write value
0128     } else {
0129         // must be splitted over integer boundary
0130         stream[iLoInt] &= ~loMask; // clear bits
0131         stream[iLoInt] |= val << offset; // write lower part of value
0132         stream[iHiInt] &= ~hiMask; // clear bits
0133         stream[iHiInt] |= val >> (WordWidth - offset); // write higher part of value
0134     }
0135 }
0136 
0137 //////////////////////////////////////////////////////////////////////
0138 /// Read k-bit number from stream at position pos
0139 /// @param stream A bit stream stored in array of unsigned integers
0140 /// @param pos A valid zero-based position in the bit stream
0141 /// @param k Number of bits to read: 1 <= k <= 32
0142 inline UINT32 GetValueBlock(UINT32* stream, UINT32 pos, UINT32 k) {
0143     UINT32 count, hiCount;
0144     const UINT32 iLoInt = pos >> WordWidthLog;              // integer of first bit
0145     const UINT32 iHiInt = (pos + k - 1) >> WordWidthLog;        // integer of last bit
0146     const UINT32 loMask = Filled << (pos%WordWidth);
0147     const UINT32 hiMask = Filled >> (WordWidth - 1 - ((pos + k - 1)%WordWidth));
0148 
0149     if (iLoInt == iHiInt) {
0150         // inside integer boundary
0151         count = stream[iLoInt] & (loMask & hiMask);
0152         count >>= pos%WordWidth;
0153     } else {
0154         // overlapping integer boundary
0155         count = stream[iLoInt] & loMask;
0156         count >>= pos%WordWidth;
0157         hiCount = stream[iHiInt] & hiMask;
0158         hiCount <<= WordWidth - (pos%WordWidth);
0159         count |= hiCount;
0160     }
0161     return count;
0162 }
0163 
0164 //////////////////////////////////////////////////////////////////////
0165 /// Clear block of size at least len at position pos in stream
0166 /// @param stream A bit stream stored in array of unsigned integers
0167 /// @param pos A valid zero-based position in the bit stream
0168 /// @param len Number of bits set to 0
0169 inline void ClearBitBlock(UINT32* stream, UINT32 pos, UINT32 len) {
0170     ASSERT(len > 0);
0171     const UINT32 iFirstInt = pos >> WordWidthLog;
0172     const UINT32 iLastInt = (pos + len - 1) >> WordWidthLog;
0173 
0174     const UINT32 startMask = Filled << (pos%WordWidth);
0175 //  const UINT32 endMask=Filled>>(WordWidth-1-((pos+len-1)%WordWidth));
0176 
0177     if (iFirstInt == iLastInt) {
0178         stream[iFirstInt] &= ~(startMask /*& endMask*/);
0179     } else {
0180         stream[iFirstInt] &= ~startMask;
0181         for (UINT32 i = iFirstInt + 1; i <= iLastInt; i++) { // changed <=
0182             stream[i] = 0;
0183         }
0184         //stream[iLastInt] &= ~endMask;
0185     }
0186 }
0187 
0188 //////////////////////////////////////////////////////////////////////
0189 /// Set block of size at least len at position pos in stream
0190 /// @param stream A bit stream stored in array of unsigned integers
0191 /// @param pos A valid zero-based position in the bit stream
0192 /// @param len Number of bits set to 1
0193 inline void SetBitBlock(UINT32* stream, UINT32 pos, UINT32 len) {
0194     ASSERT(len > 0);
0195 
0196     const UINT32 iFirstInt = pos >> WordWidthLog;
0197     const UINT32 iLastInt = (pos + len - 1) >> WordWidthLog;
0198 
0199     const UINT32 startMask = Filled << (pos%WordWidth);
0200 //  const UINT32 endMask=Filled>>(WordWidth-1-((pos+len-1)%WordWidth));
0201 
0202     if (iFirstInt == iLastInt) {
0203         stream[iFirstInt] |= (startMask /*& endMask*/);
0204     } else {
0205         stream[iFirstInt] |= startMask;
0206         for (UINT32 i = iFirstInt + 1; i <= iLastInt; i++) { // changed <=
0207             stream[i] = Filled;
0208         }
0209         //stream[iLastInt] &= ~endMask;
0210     }
0211 }
0212 
0213 //////////////////////////////////////////////////////////////////////
0214 /// Returns the distance to the next 1 in stream at position pos.
0215 /// If no 1 is found within len bits, then len is returned.
0216 /// @param stream A bit stream stored in array of unsigned integers
0217 /// @param pos A valid zero-based position in the bit stream
0218 /// @param len size of search area (in bits)
0219 /// return The distance to the next 1 in stream at position pos
0220 inline UINT32 SeekBitRange(UINT32* stream, UINT32 pos, UINT32 len) {
0221     UINT32 count = 0;
0222     UINT32 testMask = 1 << (pos%WordWidth);
0223     UINT32* word = stream + (pos >> WordWidthLog);
0224 
0225     while (((*word & testMask) == 0) && (count < len)) {
0226         count++;
0227         testMask <<= 1;
0228         if (!testMask) {
0229             word++; testMask = 1;
0230 
0231             // fast steps if all bits in a word are zero
0232             while ((count + WordWidth <= len) && (*word == 0)) {
0233                 word++;
0234                 count += WordWidth;
0235             }
0236         }
0237     }
0238 
0239     return count;
0240 }
0241 
0242 //////////////////////////////////////////////////////////////////////
0243 /// Returns the distance to the next 0 in stream at position pos.
0244 /// If no 0 is found within len bits, then len is returned.
0245 /// @param stream A bit stream stored in array of unsigned integers
0246 /// @param pos A valid zero-based position in the bit stream
0247 /// @param len size of search area (in bits)
0248 /// return The distance to the next 0 in stream at position pos
0249 inline UINT32 SeekBit1Range(UINT32* stream, UINT32 pos, UINT32 len) {
0250     UINT32 count = 0;
0251     UINT32 testMask = 1 << (pos%WordWidth);
0252     UINT32* word = stream + (pos >> WordWidthLog);
0253 
0254     while (((*word & testMask) != 0) && (count < len)) {
0255         count++;
0256         testMask <<= 1;
0257         if (!testMask) {
0258             word++; testMask = 1;
0259 
0260             // fast steps if all bits in a word are one
0261             while ((count + WordWidth <= len) && (*word == Filled)) {
0262                 word++;
0263                 count += WordWidth;
0264             }
0265         }
0266     }
0267     return count;
0268 }
0269 /*
0270 //////////////////////////////////////////////////////////////////////
0271 /// BitCopy: copies k bits from source to destination
0272 /// Note: only 8 bits are copied at a time, if speed is an issue, a more
0273 /// complicated but faster 64 bit algorithm should be used.
0274 inline void BitCopy(const UINT8 *sStream, UINT32 sPos, UINT8 *dStream, UINT32 dPos, UINT32 k) {
0275     ASSERT(k > 0);
0276 
0277     div_t divS = div(sPos, 8);
0278     div_t divD = div(dPos, 8);
0279     UINT32 sOff = divS.rem;
0280     UINT32 dOff = divD.rem;
0281     INT32 tmp = div(dPos + k - 1, 8).quot;
0282 
0283     const UINT8 *sAddr = sStream + divS.quot;
0284     UINT8 *dAddrS = dStream + divD.quot;
0285     UINT8 *dAddrE = dStream + tmp;
0286     UINT8 eMask;
0287 
0288     UINT8 destSB = *dAddrS;
0289     UINT8 destEB = *dAddrE;
0290     UINT8 *dAddr;
0291     UINT8 prec;
0292     INT32 shiftl, shiftr;
0293 
0294     if (dOff > sOff) {
0295         prec = 0;
0296         shiftr = dOff - sOff;
0297         shiftl = 8 - dOff + sOff;
0298     } else {
0299         prec = *sAddr << (sOff - dOff);
0300         shiftr = 8 - sOff + dOff;
0301         shiftl = sOff - dOff;
0302         sAddr++;
0303     }
0304 
0305     for (dAddr = dAddrS; dAddr < dAddrE; dAddr++, sAddr++) {
0306         *dAddr = prec | (*sAddr >> shiftr);
0307         prec = *sAddr << shiftl;
0308     }
0309 
0310     if ((sPos + k)%8 == 0) {
0311         *dAddr = prec;
0312     } else {
0313         *dAddr = prec | (*sAddr >> shiftr);
0314     }
0315 
0316     eMask = lMask[dOff];
0317     *dAddrS = (destSB & eMask) | (*dAddrS & (~eMask));
0318 
0319     INT32 mind = (dPos + k) % 8;
0320     eMask = (mind) ? lMask[mind] : lMask[8];
0321     *dAddrE = (destEB & (~eMask)) | (*dAddrE & eMask);
0322 }
0323 */
0324 //////////////////////////////////////////////////////////////////////
0325 /// Compute bit position of the next 32-bit word
0326 /// @param pos current bit stream position
0327 /// @return bit position of next 32-bit word
0328 inline UINT32 AlignWordPos(UINT32 pos) {
0329 //  return ((pos + WordWidth - 1) >> WordWidthLog) << WordWidthLog;
0330     return DWWIDTHBITS(pos);
0331 }
0332 
0333 //////////////////////////////////////////////////////////////////////
0334 /// Compute number of the 32-bit words
0335 /// @param pos Current bit stream position
0336 /// @return Number of 32-bit words
0337 inline UINT32 NumberOfWords(UINT32 pos) {
0338     return (pos + WordWidth - 1) >> WordWidthLog;
0339 }
0340 
0341 #endif //PGF_BITSTREAM_H