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