stream.h (15713B)
1/* 2 * WinPR: Windows Portable Runtime 3 * Stream Utils 4 * 5 * Copyright 2011 Vic Lee 6 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com> 7 * Copyright 2017 Armin Novak <armin.novak@thincast.com> 8 * Copyright 2017 Thincast Technologies GmbH 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 */ 22 23#ifndef WINPR_UTILS_STREAM_H 24#define WINPR_UTILS_STREAM_H 25 26#include <winpr/winpr.h> 27#include <winpr/wtypes.h> 28#include <winpr/endian.h> 29#include <winpr/synch.h> 30#include <winpr/assert.h> 31 32#ifdef __cplusplus 33extern "C" 34{ 35#endif 36 37 typedef struct _wStreamPool wStreamPool; 38 39 struct _wStream 40 { 41 BYTE* buffer; 42 BYTE* pointer; 43 size_t length; 44 size_t capacity; 45 46 DWORD count; 47 wStreamPool* pool; 48 BOOL isAllocatedStream; 49 BOOL isOwner; 50 }; 51 typedef struct _wStream wStream; 52 53 WINPR_API BOOL Stream_EnsureCapacity(wStream* s, size_t size); 54 WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size); 55 56 WINPR_API wStream* Stream_New(BYTE* buffer, size_t size); 57 WINPR_API void Stream_StaticInit(wStream* s, BYTE* buffer, size_t size); 58 WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer); 59 60#define Stream_CheckAndLogRequiredLength(tag, s, len) \ 61 Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, len, "%s(%s:%d)", __FUNCTION__, \ 62 __FILE__, __LINE__) 63 WINPR_API BOOL Stream_CheckAndLogRequiredLengthEx(const char* tag, DWORD level, wStream* s, 64 UINT64 len, const char* fmt, ...); 65 WINPR_API BOOL Stream_CheckAndLogRequiredLengthExVa(const char* tag, DWORD level, wStream* s, 66 UINT64 len, const char* fmt, va_list args); 67 WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s, 68 UINT64 len, const char* fmt, ...); 69 WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s, 70 UINT64 len, const char* fmt, 71 va_list args); 72 73 static INLINE void Stream_Seek(wStream* s, size_t _offset) 74 { 75 s->pointer += (_offset); 76 } 77 78 static INLINE void Stream_Rewind(wStream* s, size_t _offset) 79 { 80 s->pointer -= (_offset); 81 } 82 83#define _stream_read_n8(_t, _s, _v, _p) \ 84 do \ 85 { \ 86 (_v) = (_t)(*(_s)->pointer); \ 87 if (_p) \ 88 Stream_Seek(_s, sizeof(_t)); \ 89 } while (0) 90 91#define _stream_read_n16_le(_t, _s, _v, _p) \ 92 do \ 93 { \ 94 (_v) = (_t)((*(_s)->pointer) + (((UINT16)(*((_s)->pointer + 1))) << 8)); \ 95 if (_p) \ 96 Stream_Seek(_s, sizeof(_t)); \ 97 } while (0) 98 99#define _stream_read_n16_be(_t, _s, _v, _p) \ 100 do \ 101 { \ 102 (_v) = (_t)((((UINT16)(*(_s)->pointer)) << 8) + (UINT16)(*((_s)->pointer + 1))); \ 103 if (_p) \ 104 Stream_Seek(_s, sizeof(_t)); \ 105 } while (0) 106 107#define _stream_read_n32_le(_t, _s, _v, _p) \ 108 do \ 109 { \ 110 (_v) = (_t)((UINT32)(*(_s)->pointer) + (((UINT32)(*((_s)->pointer + 1))) << 8) + \ 111 (((UINT32)(*((_s)->pointer + 2))) << 16) + \ 112 ((((UINT32) * ((_s)->pointer + 3))) << 24)); \ 113 if (_p) \ 114 Stream_Seek(_s, sizeof(_t)); \ 115 } while (0) 116 117#define _stream_read_n32_be(_t, _s, _v, _p) \ 118 do \ 119 { \ 120 (_v) = (_t)(((((UINT32) * ((_s)->pointer))) << 24) + \ 121 (((UINT32)(*((_s)->pointer + 1))) << 16) + \ 122 (((UINT32)(*((_s)->pointer + 2))) << 8) + (((UINT32)(*((_s)->pointer + 3))))); \ 123 if (_p) \ 124 Stream_Seek(_s, sizeof(_t)); \ 125 } while (0) 126 127#define _stream_read_n64_le(_t, _s, _v, _p) \ 128 do \ 129 { \ 130 (_v) = (_t)( \ 131 (UINT64)(*(_s)->pointer) + (((UINT64)(*((_s)->pointer + 1))) << 8) + \ 132 (((UINT64)(*((_s)->pointer + 2))) << 16) + (((UINT64)(*((_s)->pointer + 3))) << 24) + \ 133 (((UINT64)(*((_s)->pointer + 4))) << 32) + (((UINT64)(*((_s)->pointer + 5))) << 40) + \ 134 (((UINT64)(*((_s)->pointer + 6))) << 48) + (((UINT64)(*((_s)->pointer + 7))) << 56)); \ 135 if (_p) \ 136 Stream_Seek(_s, sizeof(_t)); \ 137 } while (0) 138 139#define _stream_read_n64_be(_t, _s, _v, _p) \ 140 do \ 141 { \ 142 (_v) = (_t)( \ 143 (((UINT64)(*((_s)->pointer))) << 56) + (((UINT64)(*((_s)->pointer + 1))) << 48) + \ 144 (((UINT64)(*((_s)->pointer + 2))) << 40) + (((UINT64)(*((_s)->pointer + 3))) << 32) + \ 145 (((UINT64)(*((_s)->pointer + 4))) << 24) + (((UINT64)(*((_s)->pointer + 5))) << 16) + \ 146 (((UINT64)(*((_s)->pointer + 6))) << 8) + (((UINT64)(*((_s)->pointer + 7))))); \ 147 if (_p) \ 148 Stream_Seek(_s, sizeof(_t)); \ 149 } while (0) 150 151#define Stream_Read_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, TRUE) 152#define Stream_Read_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, TRUE) 153 154#define Stream_Read_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, TRUE) 155#define Stream_Read_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, TRUE) 156 157#define Stream_Read_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, TRUE) 158#define Stream_Read_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, TRUE) 159 160#define Stream_Read_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, TRUE) 161#define Stream_Read_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, TRUE) 162 163#define Stream_Read_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, TRUE) 164#define Stream_Read_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, TRUE) 165 166#define Stream_Read_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, TRUE) 167#define Stream_Read_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, TRUE) 168 169#define Stream_Read_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, TRUE) 170#define Stream_Read_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, TRUE) 171 172 static INLINE void Stream_Read(wStream* _s, void* _b, size_t _n) 173 { 174 memcpy(_b, (_s->pointer), (_n)); 175 Stream_Seek(_s, _n); 176 } 177 178#define Stream_Peek_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, FALSE) 179#define Stream_Peek_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, FALSE) 180 181#define Stream_Peek_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, FALSE) 182#define Stream_Peek_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, FALSE) 183 184#define Stream_Peek_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, FALSE) 185#define Stream_Peek_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, FALSE) 186 187#define Stream_Peek_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, FALSE) 188#define Stream_Peek_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, FALSE) 189 190#define Stream_Peek_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, FALSE) 191#define Stream_Peek_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, FALSE) 192 193#define Stream_Peek_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, FALSE) 194#define Stream_Peek_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, FALSE) 195 196#define Stream_Peek_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, FALSE) 197#define Stream_Peek_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, FALSE) 198 199 static INLINE void Stream_Peek(wStream* _s, void* _b, size_t _n) 200 { 201 memcpy(_b, (_s->pointer), (_n)); 202 } 203 204 static INLINE void Stream_Write_UINT8(wStream* _s, UINT8 _v) 205 { 206 *_s->pointer++ = (UINT8)(_v); 207 } 208 209 static INLINE void Stream_Write_INT16(wStream* _s, INT16 _v) 210 { 211 *_s->pointer++ = (_v)&0xFF; 212 *_s->pointer++ = ((_v) >> 8) & 0xFF; 213 } 214 215 static INLINE void Stream_Write_UINT16(wStream* _s, UINT16 _v) 216 { 217 *_s->pointer++ = (_v)&0xFF; 218 *_s->pointer++ = ((_v) >> 8) & 0xFF; 219 } 220 221 static INLINE void Stream_Write_UINT16_BE(wStream* _s, UINT16 _v) 222 { 223 *_s->pointer++ = ((_v) >> 8) & 0xFF; 224 *_s->pointer++ = (_v)&0xFF; 225 } 226 227 static INLINE void Stream_Write_INT32(wStream* _s, INT32 _v) 228 { 229 *_s->pointer++ = (_v)&0xFF; 230 *_s->pointer++ = ((_v) >> 8) & 0xFF; 231 *_s->pointer++ = ((_v) >> 16) & 0xFF; 232 *_s->pointer++ = ((_v) >> 24) & 0xFF; 233 } 234 235 static INLINE void Stream_Write_UINT32(wStream* _s, UINT32 _v) 236 { 237 *_s->pointer++ = (_v)&0xFF; 238 *_s->pointer++ = ((_v) >> 8) & 0xFF; 239 *_s->pointer++ = ((_v) >> 16) & 0xFF; 240 *_s->pointer++ = ((_v) >> 24) & 0xFF; 241 } 242 243 static INLINE void Stream_Write_UINT32_BE(wStream* _s, UINT32 _v) 244 { 245 Stream_Write_UINT16_BE(_s, ((_v) >> 16 & 0xFFFF)); 246 Stream_Write_UINT16_BE(_s, ((_v)&0xFFFF)); 247 } 248 249 static INLINE void Stream_Write_UINT64(wStream* _s, UINT64 _v) 250 { 251 *_s->pointer++ = (UINT64)(_v)&0xFF; 252 *_s->pointer++ = ((UINT64)(_v) >> 8) & 0xFF; 253 *_s->pointer++ = ((UINT64)(_v) >> 16) & 0xFF; 254 *_s->pointer++ = ((UINT64)(_v) >> 24) & 0xFF; 255 *_s->pointer++ = ((UINT64)(_v) >> 32) & 0xFF; 256 *_s->pointer++ = ((UINT64)(_v) >> 40) & 0xFF; 257 *_s->pointer++ = ((UINT64)(_v) >> 48) & 0xFF; 258 *_s->pointer++ = ((UINT64)(_v) >> 56) & 0xFF; 259 } 260 static INLINE void Stream_Write(wStream* _s, const void* _b, size_t _n) 261 { 262 if (_n > 0) 263 { 264 memcpy(_s->pointer, (_b), (_n)); 265 Stream_Seek(_s, _n); 266 } 267 } 268 269#define Stream_Seek_UINT8(_s) Stream_Seek(_s, 1) 270#define Stream_Seek_UINT16(_s) Stream_Seek(_s, 2) 271#define Stream_Seek_UINT32(_s) Stream_Seek(_s, 4) 272#define Stream_Seek_UINT64(_s) Stream_Seek(_s, 8) 273 274#define Stream_Rewind_UINT8(_s) Stream_Rewind(_s, 1) 275#define Stream_Rewind_UINT16(_s) Stream_Rewind(_s, 2) 276#define Stream_Rewind_UINT32(_s) Stream_Rewind(_s, 4) 277#define Stream_Rewind_UINT64(_s) Stream_Rewind(_s, 8) 278 279 static INLINE void Stream_Zero(wStream* _s, size_t _n) 280 { 281 memset(_s->pointer, '\0', (_n)); 282 Stream_Seek(_s, _n); 283 } 284 285 static INLINE void Stream_Fill(wStream* _s, int _v, size_t _n) 286 { 287 memset(_s->pointer, _v, (_n)); 288 Stream_Seek(_s, _n); 289 } 290 291 static INLINE void Stream_Copy(wStream* _src, wStream* _dst, size_t _n) 292 { 293 memcpy(_dst->pointer, _src->pointer, _n); 294 Stream_Seek(_dst, _n); 295 Stream_Seek(_src, _n); 296 } 297 298 static INLINE BYTE* Stream_Buffer(wStream* _s) 299 { 300 return _s->buffer; 301 } 302 303#define Stream_GetBuffer(_s, _b) _b = Stream_Buffer(_s) 304 static INLINE void Stream_SetBuffer(wStream* _s, BYTE* _b) 305 { 306 _s->buffer = _b; 307 } 308 309 static INLINE BYTE* Stream_Pointer(wStream* _s) 310 { 311 return _s->pointer; 312 } 313 314#define Stream_GetPointer(_s, _p) _p = Stream_Pointer(_s) 315 static INLINE void Stream_SetPointer(wStream* _s, BYTE* _p) 316 { 317 _s->pointer = _p; 318 } 319 320 static INLINE size_t Stream_Length(wStream* _s) 321 { 322 return _s->length; 323 } 324 325#define Stream_GetLength(_s, _l) _l = Stream_Length(_s) 326 static INLINE void Stream_SetLength(wStream* _s, size_t _l) 327 { 328 _s->length = _l; 329 } 330 331 static INLINE size_t Stream_Capacity(wStream* _s) 332 { 333 return _s->capacity; 334 } 335 336#define Stream_GetCapacity(_s, _c) _c = Stream_Capacity(_s); 337 static INLINE void Stream_SetCapacity(wStream* _s, size_t _c) 338 { 339 _s->capacity = _c; 340 } 341 342 static INLINE size_t Stream_GetPosition(wStream* _s) 343 { 344 return (_s->pointer - _s->buffer); 345 } 346 347 static INLINE void Stream_SetPosition(wStream* _s, size_t _p) 348 { 349 _s->pointer = _s->buffer + (_p); 350 } 351 352 static INLINE void Stream_SealLength(wStream* _s) 353 { 354 _s->length = (_s->pointer - _s->buffer); 355 } 356 357 static INLINE size_t Stream_GetRemainingCapacity(wStream* _s) 358 { 359 return (_s->capacity - (_s->pointer - _s->buffer)); 360 } 361 362 static INLINE size_t Stream_GetRemainingLength(wStream* _s) 363 { 364 return (_s->length - (_s->pointer - _s->buffer)); 365 } 366 367 static INLINE void Stream_Clear(wStream* _s) 368 { 369 memset(_s->buffer, 0, _s->capacity); 370 } 371 372 static INLINE BOOL Stream_SafeSeek(wStream* s, size_t size) 373 { 374 if (Stream_GetRemainingLength(s) < size) 375 return FALSE; 376 377 Stream_Seek(s, size); 378 return TRUE; 379 } 380 381 static INLINE BOOL Stream_Read_UTF16_String(wStream* s, WCHAR* dst, size_t length) 382 { 383 size_t x; 384 385 if (!s || !dst) 386 return FALSE; 387 388 if (Stream_GetRemainingLength(s) / sizeof(WCHAR) < length) 389 return FALSE; 390 391 for (x = 0; x < length; x++) 392 Stream_Read_UINT16(s, dst[x]); 393 394 return TRUE; 395 } 396 397 static INLINE BOOL Stream_Write_UTF16_String(wStream* s, const WCHAR* src, size_t length) 398 { 399 size_t x; 400 401 if (!s || !src) 402 return FALSE; 403 404 if (Stream_GetRemainingCapacity(s) / sizeof(WCHAR) < length) 405 return FALSE; 406 407 for (x = 0; x < length; x++) 408 Stream_Write_UINT16(s, src[x]); 409 410 return TRUE; 411 } 412 413 /* StreamPool */ 414 415 struct _wStreamPool 416 { 417 int aSize; 418 int aCapacity; 419 wStream** aArray; 420 421 int uSize; 422 int uCapacity; 423 wStream** uArray; 424 425 CRITICAL_SECTION lock; 426 BOOL synchronized; 427 size_t defaultSize; 428 }; 429 430 WINPR_API wStream* StreamPool_Take(wStreamPool* pool, size_t size); 431 WINPR_API void StreamPool_Return(wStreamPool* pool, wStream* s); 432 433 WINPR_API void Stream_AddRef(wStream* s); 434 WINPR_API void Stream_Release(wStream* s); 435 436 WINPR_API wStream* StreamPool_Find(wStreamPool* pool, BYTE* ptr); 437 WINPR_API void StreamPool_AddRef(wStreamPool* pool, BYTE* ptr); 438 WINPR_API void StreamPool_Release(wStreamPool* pool, BYTE* ptr); 439 440 WINPR_API void StreamPool_Clear(wStreamPool* pool); 441 442 WINPR_API wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize); 443 WINPR_API void StreamPool_Free(wStreamPool* pool); 444 445#ifdef __cplusplus 446} 447#endif 448 449#endif /* WINPR_UTILS_STREAM_H */