bitstream.h (5197B)
1/* 2 * WinPR: Windows Portable Runtime 3 * BitStream Utils 4 * 5 * Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com> 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 */ 19 20#ifndef WINPR_UTILS_BITSTREAM_H 21#define WINPR_UTILS_BITSTREAM_H 22 23#include <winpr/winpr.h> 24#include <winpr/wtypes.h> 25 26#include <winpr/crt.h> 27#include <winpr/wlog.h> 28 29struct _wBitStream 30{ 31 const BYTE* buffer; 32 BYTE* pointer; 33 UINT32 position; 34 UINT32 length; 35 UINT32 capacity; 36 UINT32 mask; 37 UINT32 offset; 38 UINT32 prefetch; 39 UINT32 accumulator; 40}; 41typedef struct _wBitStream wBitStream; 42 43#define BITDUMP_MSB_FIRST 0x00000001 44#define BITDUMP_STDERR 0x00000002 45 46#ifdef __cplusplus 47extern "C" 48{ 49#endif 50 51 static INLINE void BitStream_Prefetch(wBitStream* _bs) 52 { 53 (_bs->prefetch) = 0; 54 if (((UINT32)(_bs->pointer - _bs->buffer) + 4) < (_bs->capacity)) 55 (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 4) << 24); 56 if (((UINT32)(_bs->pointer - _bs->buffer) + 5) < (_bs->capacity)) 57 (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 5) << 16); 58 if (((UINT32)(_bs->pointer - _bs->buffer) + 6) < (_bs->capacity)) 59 (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 6) << 8); 60 if (((UINT32)(_bs->pointer - _bs->buffer) + 7) < (_bs->capacity)) 61 (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 7) << 0); 62 } 63 64 static INLINE void BitStream_Fetch(wBitStream* _bs) 65 { 66 (_bs->accumulator) = 0; 67 if (((UINT32)(_bs->pointer - _bs->buffer) + 0) < (_bs->capacity)) 68 (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 0) << 24); 69 if (((UINT32)(_bs->pointer - _bs->buffer) + 1) < (_bs->capacity)) 70 (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 1) << 16); 71 if (((UINT32)(_bs->pointer - _bs->buffer) + 2) < (_bs->capacity)) 72 (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 2) << 8); 73 if (((UINT32)(_bs->pointer - _bs->buffer) + 3) < (_bs->capacity)) 74 (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 3) << 0); 75 BitStream_Prefetch(_bs); 76 } 77 78 static INLINE void BitStream_Flush(wBitStream* _bs) 79 { 80 if (((UINT32)(_bs->pointer - _bs->buffer) + 0) < (_bs->capacity)) 81 *(_bs->pointer + 0) = ((UINT32)_bs->accumulator >> 24); 82 if (((UINT32)(_bs->pointer - _bs->buffer) + 1) < (_bs->capacity)) 83 *(_bs->pointer + 1) = ((UINT32)_bs->accumulator >> 16); 84 if (((UINT32)(_bs->pointer - _bs->buffer) + 2) < (_bs->capacity)) 85 *(_bs->pointer + 2) = ((UINT32)_bs->accumulator >> 8); 86 if (((UINT32)(_bs->pointer - _bs->buffer) + 3) < (_bs->capacity)) 87 *(_bs->pointer + 3) = ((UINT32)_bs->accumulator >> 0); 88 } 89 90 static INLINE void BitStream_Shift(wBitStream* _bs, UINT32 _nbits) 91 { 92 if (_nbits == 0) 93 { 94 } 95 else if ((_nbits > 0) && (_nbits < 32)) 96 { 97 _bs->accumulator <<= _nbits; 98 _bs->position += _nbits; 99 _bs->offset += _nbits; 100 if (_bs->offset < 32) 101 { 102 _bs->mask = ((1UL << _nbits) - 1); 103 _bs->accumulator |= ((_bs->prefetch >> (32 - _nbits)) & _bs->mask); 104 _bs->prefetch <<= _nbits; 105 } 106 else 107 { 108 _bs->mask = ((1UL << _nbits) - 1); 109 _bs->accumulator |= ((_bs->prefetch >> (32 - _nbits)) & _bs->mask); 110 _bs->prefetch <<= _nbits; 111 _bs->offset -= 32; 112 _bs->pointer += 4; 113 BitStream_Prefetch(_bs); 114 if (_bs->offset) 115 { 116 _bs->mask = ((1UL << _bs->offset) - 1); 117 _bs->accumulator |= ((_bs->prefetch >> (32 - _bs->offset)) & _bs->mask); 118 _bs->prefetch <<= _bs->offset; 119 } 120 } 121 } 122 else 123 { 124 WLog_WARN("com.winpr.bitstream", "warning: BitStream_Shift(%u)", (unsigned)_nbits); 125 } 126 } 127 128 static INLINE void BitStream_Shift32(wBitStream* _bs) 129 { 130 BitStream_Shift(_bs, 16); 131 BitStream_Shift(_bs, 16); 132 } 133 134 static INLINE void BitStream_Write_Bits(wBitStream* _bs, UINT32 _bits, UINT32 _nbits) 135 { 136 _bs->position += _nbits; 137 _bs->offset += _nbits; 138 if (_bs->offset < 32) 139 { 140 _bs->accumulator |= (_bits << (32 - _bs->offset)); 141 } 142 else 143 { 144 _bs->offset -= 32; 145 _bs->mask = ((1 << (_nbits - _bs->offset)) - 1); 146 _bs->accumulator |= ((_bits >> _bs->offset) & _bs->mask); 147 BitStream_Flush(_bs); 148 _bs->accumulator = 0; 149 _bs->pointer += 4; 150 if (_bs->offset) 151 { 152 _bs->mask = ((1UL << _bs->offset) - 1); 153 _bs->accumulator |= ((_bits & _bs->mask) << (32 - _bs->offset)); 154 } 155 } 156 } 157 158 static INLINE size_t BitStream_GetRemainingLength(wBitStream* _bs) 159 { 160 return (_bs->length - _bs->position); 161 } 162 163 WINPR_API void BitDump(const char* tag, UINT32 level, const BYTE* buffer, UINT32 length, 164 UINT32 flags); 165 WINPR_API UINT32 ReverseBits32(UINT32 bits, UINT32 nbits); 166 167 WINPR_API void BitStream_Attach(wBitStream* bs, const BYTE* buffer, UINT32 capacity); 168 169 WINPR_API wBitStream* BitStream_New(); 170 WINPR_API void BitStream_Free(wBitStream* bs); 171 172#ifdef __cplusplus 173} 174#endif 175 176#endif /* WINPR_UTILS_BITSTREAM_H */