FreeRDP
Loading...
Searching...
No Matches
encoded_types.c
1
21#include <freerdp/config.h>
22
23#include <freerdp/channels/log.h>
24#include <freerdp/utils/encoded_types.h>
25#include <math.h>
26
27#define TAG CHANNELS_TAG("encoded_types")
28
29typedef enum
30{
31 ONE_BYTE_VAL,
32 TWO_BYTE_VAL,
33 THREE_BYTE_VAL,
34 FOUR_BYTE_VAL,
35 FIVE_BYTE_VAL,
36 SIX_BYTE_VAL,
37 SEVEN_BYTE_VAL,
38 EIGHT_BYTE_VAL,
39} EncodedTypeByteCount;
40
41typedef enum
42{
43 POSITIVE_VAL,
44 NEGATIVE_VAL,
45} EncodedTypeSign;
46
47typedef struct
48{
49 EncodedTypeByteCount c;
50 EncodedTypeSign s;
51 BYTE val1;
52 BYTE val2;
53 BYTE val3;
54 BYTE val4;
55} FOUR_BYTE_SIGNED_INTEGER;
56
57typedef struct
58{
59 EncodedTypeByteCount c;
60 EncodedTypeSign s;
61 BYTE e;
62 BYTE val1;
63 BYTE val2;
64 BYTE val3;
65 BYTE val4;
66} FOUR_BYTE_FLOAT;
67
68static inline FOUR_BYTE_SIGNED_INTEGER FOUR_BYTE_SIGNED_INTEGER_init(void)
69{
70 const FOUR_BYTE_SIGNED_INTEGER empty = {
71 .c = ONE_BYTE_VAL, .s = POSITIVE_VAL, .val1 = 0, .val2 = 0, .val3 = 0, .val4 = 0
72 };
73 return empty;
74}
75
76static inline FOUR_BYTE_FLOAT FOUR_BYTE_FLOAT_init(void)
77{
78 const FOUR_BYTE_FLOAT empty = {
79 .c = ONE_BYTE_VAL, .s = POSITIVE_VAL, .e = 0, .val1 = 0, .val2 = 0, .val3 = 0, .val4 = 0
80 };
81 return empty;
82}
83
84BOOL freerdp_read_four_byte_signed_integer(wStream* s, INT32* value)
85{
86 FOUR_BYTE_SIGNED_INTEGER si = FOUR_BYTE_SIGNED_INTEGER_init();
87 BYTE byte = 0;
88
89 WINPR_ASSERT(s);
90 WINPR_ASSERT(value);
91
92 *value = 0;
93
94 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
95 return FALSE;
96
97 Stream_Read_UINT8(s, byte);
98
99 si.c = (EncodedTypeByteCount)((byte & 0xC0) >> 6);
100 si.s = (EncodedTypeSign)((byte & 0x20) >> 5);
101 si.val1 = (byte & 0x1F);
102
103 if (!Stream_CheckAndLogRequiredLength(TAG, s, si.c))
104 return FALSE;
105
106 switch (si.c)
107 {
108 case ONE_BYTE_VAL:
109 *value = si.val1;
110 break;
111 case TWO_BYTE_VAL:
112 Stream_Read_UINT8(s, si.val2);
113 *value = (((INT32)si.val1) << 8) | ((INT32)si.val2);
114 break;
115 case THREE_BYTE_VAL:
116 Stream_Read_UINT8(s, si.val2);
117 Stream_Read_UINT8(s, si.val3);
118 *value = (((INT32)si.val1) << 16) | (((INT32)si.val2) << 8) | ((INT32)si.val3);
119 break;
120 case FOUR_BYTE_VAL:
121 Stream_Read_UINT8(s, si.val2);
122 Stream_Read_UINT8(s, si.val3);
123 Stream_Read_UINT8(s, si.val4);
124 *value = (((INT32)si.val1) << 24) | (((INT32)si.val2) << 16) | (((INT32)si.val3) << 8) |
125 ((INT32)si.val4);
126 break;
127 case FIVE_BYTE_VAL:
128 case SIX_BYTE_VAL:
129 case SEVEN_BYTE_VAL:
130 case EIGHT_BYTE_VAL:
131 default:
132 WLog_ERR(TAG, "Invalid byte count value in si.c: %u", si.c);
133 return FALSE;
134 }
135
136 if (si.s == NEGATIVE_VAL)
137 *value *= -1;
138
139 return TRUE;
140}
141
142BOOL freerdp_write_four_byte_signed_integer(wStream* s, INT32 value)
143{
144 FOUR_BYTE_SIGNED_INTEGER si = FOUR_BYTE_SIGNED_INTEGER_init();
145
146 WINPR_ASSERT(s);
147 if (value > FREERDP_FOUR_BYTE_SIGNED_INT_MAX)
148 return FALSE;
149 if (value < FREERDP_FOUR_BYTE_SIGNED_INT_MIN)
150 return FALSE;
151
152 if (value < 0)
153 {
154 si.s = NEGATIVE_VAL;
155 value = -value;
156 }
157
158 if (value <= 0x1F)
159 {
160 si.c = ONE_BYTE_VAL;
161 si.val1 = value & 0x1f;
162 }
163 else if (value <= 0x1FFF)
164 {
165 si.c = TWO_BYTE_VAL;
166 si.val1 = (value >> 8) & 0x1f;
167 si.val2 = value & 0xff;
168 }
169 else if (value <= 0x1FFFFF)
170 {
171 si.c = THREE_BYTE_VAL;
172 si.val1 = (value >> 16) & 0x1f;
173 si.val2 = (value >> 8) & 0xff;
174 si.val3 = value & 0xff;
175 }
176 else if (value <= 0x1FFFFFFF)
177 {
178 si.c = FOUR_BYTE_VAL;
179 si.val1 = (value >> 24) & 0x1f;
180 si.val2 = (value >> 16) & 0xff;
181 si.val3 = (value >> 8) & 0xff;
182 si.val4 = value & 0xff;
183 }
184 else
185 {
186 WLog_ERR(TAG, "Invalid byte count for value %" PRId32, value);
187 return FALSE;
188 }
189
190 if (!Stream_EnsureRemainingCapacity(s, si.c + 1))
191 return FALSE;
192
193 const BYTE byte = ((si.c << 6) & 0xC0) | ((si.s << 5) & 0x20) | (si.val1 & 0x1F);
194 Stream_Write_UINT8(s, byte);
195
196 switch (si.c)
197 {
198 case ONE_BYTE_VAL:
199 break;
200 case TWO_BYTE_VAL:
201 Stream_Write_UINT8(s, si.val2);
202 break;
203 case THREE_BYTE_VAL:
204 Stream_Write_UINT8(s, si.val2);
205 Stream_Write_UINT8(s, si.val3);
206 break;
207 case FOUR_BYTE_VAL:
208 Stream_Write_UINT8(s, si.val2);
209 Stream_Write_UINT8(s, si.val3);
210 Stream_Write_UINT8(s, si.val4);
211 break;
212 case FIVE_BYTE_VAL:
213 case SIX_BYTE_VAL:
214 case SEVEN_BYTE_VAL:
215 case EIGHT_BYTE_VAL:
216 default:
217 WLog_ERR(TAG, "Invalid byte count value in si.c: %u", si.c);
218 return FALSE;
219 }
220
221 return TRUE;
222}
223
224BOOL freerdp_read_four_byte_float(wStream* s, double* value)
225{
226 return freerdp_read_four_byte_float_exp(s, value, NULL);
227}
228
229BOOL freerdp_read_four_byte_float_exp(wStream* s, double* value, BYTE* exp)
230{
231 FOUR_BYTE_FLOAT f = FOUR_BYTE_FLOAT_init();
232 UINT32 base = 0;
233 BYTE byte = 0;
234
235 WINPR_ASSERT(s);
236 WINPR_ASSERT(value);
237
238 *value = 0.0;
239
240 if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
241 return FALSE;
242
243 Stream_Read_UINT8(s, byte);
244
245 f.c = (EncodedTypeByteCount)((byte & 0xC0) >> 6);
246 f.s = (EncodedTypeSign)((byte & 0x20) >> 5);
247 f.e = (byte & 0x1C) >> 2;
248 f.val1 = (byte & 0x03);
249
250 if (!Stream_CheckAndLogRequiredLength(TAG, s, f.c))
251 return FALSE;
252
253 switch (f.c)
254 {
255 case ONE_BYTE_VAL:
256 base = f.val1;
257 break;
258 case TWO_BYTE_VAL:
259 Stream_Read_UINT8(s, f.val2);
260 base = (((UINT32)f.val1) << 8) | ((UINT32)f.val2);
261 break;
262 case THREE_BYTE_VAL:
263 Stream_Read_UINT8(s, f.val2);
264 Stream_Read_UINT8(s, f.val3);
265 base = (((UINT32)f.val1) << 16) | (((UINT32)f.val2) << 8) | ((UINT32)f.val3);
266 break;
267 case FOUR_BYTE_VAL:
268 Stream_Read_UINT8(s, f.val2);
269 Stream_Read_UINT8(s, f.val3);
270 Stream_Read_UINT8(s, f.val4);
271 base = (((UINT32)f.val1) << 24) | (((UINT32)f.val2) << 16) | (((UINT32)f.val3) << 8) |
272 ((UINT32)f.val4);
273 break;
274 case FIVE_BYTE_VAL:
275 case SIX_BYTE_VAL:
276 case SEVEN_BYTE_VAL:
277 case EIGHT_BYTE_VAL:
278 default:
279 WLog_ERR(TAG, "Invalid byte count value in f.c: %u", f.c);
280 return FALSE;
281 }
282
283 *value = base;
284 *value /= pow(10, f.e);
285
286 if (f.s == NEGATIVE_VAL)
287 *value *= -1.0;
288
289 if (exp)
290 *exp = f.e;
291
292 return TRUE;
293}
294
295BOOL freerdp_write_four_byte_float(wStream* s, double value)
296{
297 FOUR_BYTE_FLOAT si = FOUR_BYTE_FLOAT_init();
298
299 WINPR_ASSERT(s);
300
301 if (value > FREERDP_FOUR_BYTE_FLOAT_MAX)
302 return FALSE;
303 if (value < FREERDP_FOUR_BYTE_FLOAT_MIN)
304 return FALSE;
305
306 if (value < 0)
307 {
308 si.s = NEGATIVE_VAL;
309 value = -value;
310 }
311
312 int exp = 0;
313 double ival = FP_NAN;
314 const double aval = fabs(value);
315 const double frac = modf(aval, &ival);
316 if (frac != 0.0)
317 {
318 const double maxfrac = frac * 10000000.0;
319 if (maxfrac <= 1.0)
320 exp = 0;
321 else if (maxfrac <= 10.0)
322 exp = 1;
323 else if (maxfrac <= 100.0)
324 exp = 2;
325 else if (maxfrac <= 1000.0)
326 exp = 3;
327 else if (maxfrac <= 10000.0)
328 exp = 4;
329 else if (maxfrac <= 100000.0)
330 exp = 5;
331 else if (maxfrac <= 1000000.0)
332 exp = 6;
333 else
334 exp = 7;
335 }
336
337 UINT64 base = (UINT64)llround(aval);
338 while (exp >= 0)
339 {
340 const double div = pow(10.0, exp);
341 const double dval = (aval * div);
342 base = (UINT64)dval;
343 if (base <= 0x03ffffff)
344 break;
345 exp--;
346 }
347
348 if (exp < 0)
349 return FALSE;
350
351 si.e = (BYTE)exp;
352 if (base <= 0x03)
353 {
354 si.c = ONE_BYTE_VAL;
355 si.val1 = base & 0x03;
356 }
357 else if (base <= 0x03ff)
358 {
359 si.c = TWO_BYTE_VAL;
360 si.val1 = (base >> 8) & 0x03;
361 si.val2 = base & 0xff;
362 }
363 else if (base <= 0x03ffff)
364 {
365 si.c = THREE_BYTE_VAL;
366 si.val1 = (base >> 16) & 0x03;
367 si.val2 = (base >> 8) & 0xff;
368 si.val3 = base & 0xff;
369 }
370 else if (base <= 0x03ffffff)
371 {
372 si.c = FOUR_BYTE_VAL;
373 si.val1 = (base >> 24) & 0x03;
374 si.val2 = (base >> 16) & 0xff;
375 si.val3 = (base >> 8) & 0xff;
376 si.val4 = base & 0xff;
377 }
378 else
379 {
380 WLog_ERR(TAG, "Invalid byte count for value %lf", value);
381 return FALSE;
382 }
383
384 if (!Stream_EnsureRemainingCapacity(s, si.c + 1))
385 return FALSE;
386
387 const BYTE byte =
388 ((si.c << 6) & 0xC0) | ((si.s << 5) & 0x20) | ((si.e << 2) & 0x1c) | (si.val1 & 0x03);
389 Stream_Write_UINT8(s, byte);
390
391 switch (si.c)
392 {
393 case ONE_BYTE_VAL:
394 break;
395 case TWO_BYTE_VAL:
396 Stream_Write_UINT8(s, si.val2);
397 break;
398 case THREE_BYTE_VAL:
399 Stream_Write_UINT8(s, si.val2);
400 Stream_Write_UINT8(s, si.val3);
401 break;
402 case FOUR_BYTE_VAL:
403 Stream_Write_UINT8(s, si.val2);
404 Stream_Write_UINT8(s, si.val3);
405 Stream_Write_UINT8(s, si.val4);
406 break;
407 case FIVE_BYTE_VAL:
408 case SIX_BYTE_VAL:
409 case SEVEN_BYTE_VAL:
410 case EIGHT_BYTE_VAL:
411 default:
412 WLog_ERR(TAG, "Invalid byte count value in si.c: %u", si.c);
413 return FALSE;
414 }
415
416 return TRUE;
417}