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