FreeRDP
bitstream.h
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/assert.h>
24 #include <winpr/winpr.h>
25 #include <winpr/wtypes.h>
26 
27 #include <winpr/crt.h>
28 #include <winpr/wlog.h>
29 
30 typedef struct
31 {
32  const BYTE* buffer;
33  BYTE* pointer;
34  UINT32 position;
35  UINT32 length;
36  UINT32 capacity;
37  UINT32 mask;
38  UINT32 offset;
39  UINT32 prefetch;
40  UINT32 accumulator;
41 } wBitStream;
42 
43 #define BITDUMP_MSB_FIRST 0x00000001
44 #define BITDUMP_STDERR 0x00000002
45 
46 #ifdef __cplusplus
47 extern "C"
48 {
49 #endif
50 
51  static INLINE void BitStream_Prefetch(wBitStream* _bs)
52  {
53  WINPR_ASSERT(_bs);
54 
55  (_bs->prefetch) = 0;
56  if (((UINT32)(_bs->pointer - _bs->buffer) + 4) < (_bs->capacity))
57  (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 4) << 24);
58  if (((UINT32)(_bs->pointer - _bs->buffer) + 5) < (_bs->capacity))
59  (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 5) << 16);
60  if (((UINT32)(_bs->pointer - _bs->buffer) + 6) < (_bs->capacity))
61  (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 6) << 8);
62  if (((UINT32)(_bs->pointer - _bs->buffer) + 7) < (_bs->capacity))
63  (_bs->prefetch) |= ((UINT32) * (_bs->pointer + 7) << 0);
64  }
65 
66  static INLINE void BitStream_Fetch(wBitStream* _bs)
67  {
68  WINPR_ASSERT(_bs);
69  (_bs->accumulator) = 0;
70  if (((UINT32)(_bs->pointer - _bs->buffer) + 0) < (_bs->capacity))
71  (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 0) << 24);
72  if (((UINT32)(_bs->pointer - _bs->buffer) + 1) < (_bs->capacity))
73  (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 1) << 16);
74  if (((UINT32)(_bs->pointer - _bs->buffer) + 2) < (_bs->capacity))
75  (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 2) << 8);
76  if (((UINT32)(_bs->pointer - _bs->buffer) + 3) < (_bs->capacity))
77  (_bs->accumulator) |= ((UINT32) * (_bs->pointer + 3) << 0);
78  BitStream_Prefetch(_bs);
79  }
80 
81  static INLINE void BitStream_Flush(wBitStream* _bs)
82  {
83  WINPR_ASSERT(_bs);
84  if (((UINT32)(_bs->pointer - _bs->buffer) + 0) < (_bs->capacity))
85  *(_bs->pointer + 0) = (BYTE)((UINT32)_bs->accumulator >> 24);
86  if (((UINT32)(_bs->pointer - _bs->buffer) + 1) < (_bs->capacity))
87  *(_bs->pointer + 1) = (BYTE)((UINT32)_bs->accumulator >> 16);
88  if (((UINT32)(_bs->pointer - _bs->buffer) + 2) < (_bs->capacity))
89  *(_bs->pointer + 2) = (BYTE)((UINT32)_bs->accumulator >> 8);
90  if (((UINT32)(_bs->pointer - _bs->buffer) + 3) < (_bs->capacity))
91  *(_bs->pointer + 3) = (BYTE)((UINT32)_bs->accumulator >> 0);
92  }
93 
94  static INLINE void BitStream_Shift(wBitStream* _bs, UINT32 _nbits)
95  {
96  WINPR_ASSERT(_bs);
97  if (_nbits == 0)
98  {
99  }
100  else if ((_nbits > 0) && (_nbits < 32))
101  {
102  _bs->accumulator <<= _nbits;
103  _bs->position += _nbits;
104  _bs->offset += _nbits;
105  if (_bs->offset < 32)
106  {
107  _bs->mask = (UINT32)((1UL << _nbits) - 1UL);
108  _bs->accumulator |= ((_bs->prefetch >> (32 - _nbits)) & _bs->mask);
109  _bs->prefetch <<= _nbits;
110  }
111  else
112  {
113  _bs->mask = (UINT32)((1UL << _nbits) - 1UL);
114  _bs->accumulator |= ((_bs->prefetch >> (32 - _nbits)) & _bs->mask);
115  _bs->prefetch <<= _nbits;
116  _bs->offset -= 32;
117  _bs->pointer += 4;
118  BitStream_Prefetch(_bs);
119  if (_bs->offset)
120  {
121  _bs->mask = (UINT32)((1UL << _bs->offset) - 1UL);
122  _bs->accumulator |= ((_bs->prefetch >> (32 - _bs->offset)) & _bs->mask);
123  _bs->prefetch <<= _bs->offset;
124  }
125  }
126  }
127  else
128  {
129  WLog_WARN("com.winpr.bitstream", "warning: BitStream_Shift(%u)", (unsigned)_nbits);
130  }
131  }
132 
133  static INLINE void BitStream_Shift32(wBitStream* _bs)
134  {
135  WINPR_ASSERT(_bs);
136  BitStream_Shift(_bs, 16);
137  BitStream_Shift(_bs, 16);
138  }
139 
140  static INLINE void BitStream_Write_Bits(wBitStream* _bs, UINT32 _bits, UINT32 _nbits)
141  {
142  WINPR_ASSERT(_bs);
143  _bs->position += _nbits;
144  _bs->offset += _nbits;
145  if (_bs->offset < 32)
146  {
147  _bs->accumulator |= (_bits << (32 - _bs->offset));
148  }
149  else
150  {
151  _bs->offset -= 32;
152  _bs->mask = ((1 << (_nbits - _bs->offset)) - 1);
153  _bs->accumulator |= ((_bits >> _bs->offset) & _bs->mask);
154  BitStream_Flush(_bs);
155  _bs->accumulator = 0;
156  _bs->pointer += 4;
157  if (_bs->offset)
158  {
159  _bs->mask = (UINT32)((1UL << _bs->offset) - 1);
160  _bs->accumulator |= ((_bits & _bs->mask) << (32 - _bs->offset));
161  }
162  }
163  }
164 
165  static INLINE size_t BitStream_GetRemainingLength(wBitStream* _bs)
166  {
167  WINPR_ASSERT(_bs);
168  return (_bs->length - _bs->position);
169  }
170 
171  WINPR_API void BitDump(const char* tag, UINT32 level, const BYTE* buffer, UINT32 length,
172  UINT32 flags);
173  WINPR_API UINT32 ReverseBits32(UINT32 bits, UINT32 nbits);
174 
175  WINPR_API void BitStream_Attach(wBitStream* bs, const BYTE* buffer, UINT32 capacity);
176 
177  WINPR_API void BitStream_Free(wBitStream* bs);
178 
179  WINPR_ATTR_MALLOC(BitStream_Free, 1)
180  WINPR_API wBitStream* BitStream_New(void);
181 
182 #ifdef __cplusplus
183 }
184 #endif
185 
186 #endif /* WINPR_UTILS_BITSTREAM_H */