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 31 #ifdef __cplusplus 32 extern "C" 33 { 34 #endif 35 36 typedef struct _wStreamPool wStreamPool; 37 38 struct _wStream 39 { 40 BYTE* buffer; 41 BYTE* pointer; 42 size_t length; 43 size_t capacity; 44 45 DWORD count; 46 wStreamPool* pool; 47 BOOL isAllocatedStream; 48 BOOL isOwner; 49 }; 50 typedef struct _wStream wStream; 51 52 WINPR_API BOOL Stream_EnsureCapacity(wStream* s, size_t size); 53 WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size); 54 55 WINPR_API wStream* Stream_New(BYTE* buffer, size_t size); 56 WINPR_API void Stream_StaticInit(wStream* s, BYTE* buffer, size_t size); 57 WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer); 58 Stream_Seek(wStream * s,size_t _offset)59 static INLINE void Stream_Seek(wStream* s, size_t _offset) 60 { 61 s->pointer += (_offset); 62 } 63 Stream_Rewind(wStream * s,size_t _offset)64 static INLINE void Stream_Rewind(wStream* s, size_t _offset) 65 { 66 s->pointer -= (_offset); 67 } 68 69 #define _stream_read_n8(_t, _s, _v, _p) \ 70 do \ 71 { \ 72 (_v) = (_t)(*(_s)->pointer); \ 73 if (_p) \ 74 Stream_Seek(_s, sizeof(_t)); \ 75 } while (0) 76 77 #define _stream_read_n16_le(_t, _s, _v, _p) \ 78 do \ 79 { \ 80 (_v) = (_t)((*(_s)->pointer) + (((UINT16)(*((_s)->pointer + 1))) << 8)); \ 81 if (_p) \ 82 Stream_Seek(_s, sizeof(_t)); \ 83 } while (0) 84 85 #define _stream_read_n16_be(_t, _s, _v, _p) \ 86 do \ 87 { \ 88 (_v) = (_t)((((UINT16)(*(_s)->pointer)) << 8) + (UINT16)(*((_s)->pointer + 1))); \ 89 if (_p) \ 90 Stream_Seek(_s, sizeof(_t)); \ 91 } while (0) 92 93 #define _stream_read_n32_le(_t, _s, _v, _p) \ 94 do \ 95 { \ 96 (_v) = (_t)((UINT32)(*(_s)->pointer) + (((UINT32)(*((_s)->pointer + 1))) << 8) + \ 97 (((UINT32)(*((_s)->pointer + 2))) << 16) + \ 98 ((((UINT32) * ((_s)->pointer + 3))) << 24)); \ 99 if (_p) \ 100 Stream_Seek(_s, sizeof(_t)); \ 101 } while (0) 102 103 #define _stream_read_n32_be(_t, _s, _v, _p) \ 104 do \ 105 { \ 106 (_v) = (_t)(((((UINT32) * ((_s)->pointer))) << 24) + \ 107 (((UINT32)(*((_s)->pointer + 1))) << 16) + \ 108 (((UINT32)(*((_s)->pointer + 2))) << 8) + (((UINT32)(*((_s)->pointer + 3))))); \ 109 if (_p) \ 110 Stream_Seek(_s, sizeof(_t)); \ 111 } while (0) 112 113 #define _stream_read_n64_le(_t, _s, _v, _p) \ 114 do \ 115 { \ 116 (_v) = (_t)( \ 117 (UINT64)(*(_s)->pointer) + (((UINT64)(*((_s)->pointer + 1))) << 8) + \ 118 (((UINT64)(*((_s)->pointer + 2))) << 16) + (((UINT64)(*((_s)->pointer + 3))) << 24) + \ 119 (((UINT64)(*((_s)->pointer + 4))) << 32) + (((UINT64)(*((_s)->pointer + 5))) << 40) + \ 120 (((UINT64)(*((_s)->pointer + 6))) << 48) + (((UINT64)(*((_s)->pointer + 7))) << 56)); \ 121 if (_p) \ 122 Stream_Seek(_s, sizeof(_t)); \ 123 } while (0) 124 125 #define _stream_read_n64_be(_t, _s, _v, _p) \ 126 do \ 127 { \ 128 (_v) = (_t)( \ 129 (((UINT64)(*((_s)->pointer))) << 56) + (((UINT64)(*((_s)->pointer + 1))) << 48) + \ 130 (((UINT64)(*((_s)->pointer + 2))) << 40) + (((UINT64)(*((_s)->pointer + 3))) << 32) + \ 131 (((UINT64)(*((_s)->pointer + 4))) << 24) + (((UINT64)(*((_s)->pointer + 5))) << 16) + \ 132 (((UINT64)(*((_s)->pointer + 6))) << 8) + (((UINT64)(*((_s)->pointer + 7))))); \ 133 if (_p) \ 134 Stream_Seek(_s, sizeof(_t)); \ 135 } while (0) 136 137 #define Stream_Read_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, TRUE) 138 #define Stream_Read_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, TRUE) 139 140 #define Stream_Read_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, TRUE) 141 #define Stream_Read_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, TRUE) 142 143 #define Stream_Read_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, TRUE) 144 #define Stream_Read_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, TRUE) 145 146 #define Stream_Read_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, TRUE) 147 #define Stream_Read_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, TRUE) 148 149 #define Stream_Read_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, TRUE) 150 #define Stream_Read_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, TRUE) 151 152 #define Stream_Read_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, TRUE) 153 #define Stream_Read_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, TRUE) 154 155 #define Stream_Read_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, TRUE) 156 #define Stream_Read_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, TRUE) 157 Stream_Read(wStream * _s,void * _b,size_t _n)158 static INLINE void Stream_Read(wStream* _s, void* _b, size_t _n) 159 { 160 memcpy(_b, (_s->pointer), (_n)); 161 Stream_Seek(_s, _n); 162 } 163 164 #define Stream_Peek_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, FALSE) 165 #define Stream_Peek_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, FALSE) 166 167 #define Stream_Peek_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, FALSE) 168 #define Stream_Peek_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, FALSE) 169 170 #define Stream_Peek_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, FALSE) 171 #define Stream_Peek_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, FALSE) 172 173 #define Stream_Peek_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, FALSE) 174 #define Stream_Peek_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, FALSE) 175 176 #define Stream_Peek_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, FALSE) 177 #define Stream_Peek_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, FALSE) 178 179 #define Stream_Peek_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, FALSE) 180 #define Stream_Peek_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, FALSE) 181 182 #define Stream_Peek_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, FALSE) 183 #define Stream_Peek_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, FALSE) 184 Stream_Peek(wStream * _s,void * _b,size_t _n)185 static INLINE void Stream_Peek(wStream* _s, void* _b, size_t _n) 186 { 187 memcpy(_b, (_s->pointer), (_n)); 188 } 189 Stream_Write_UINT8(wStream * _s,UINT8 _v)190 static INLINE void Stream_Write_UINT8(wStream* _s, UINT8 _v) 191 { 192 *_s->pointer++ = (UINT8)(_v); 193 } 194 Stream_Write_INT16(wStream * _s,INT16 _v)195 static INLINE void Stream_Write_INT16(wStream* _s, INT16 _v) 196 { 197 *_s->pointer++ = (_v)&0xFF; 198 *_s->pointer++ = ((_v) >> 8) & 0xFF; 199 } 200 Stream_Write_UINT16(wStream * _s,UINT16 _v)201 static INLINE void Stream_Write_UINT16(wStream* _s, UINT16 _v) 202 { 203 *_s->pointer++ = (_v)&0xFF; 204 *_s->pointer++ = ((_v) >> 8) & 0xFF; 205 } 206 Stream_Write_UINT16_BE(wStream * _s,UINT16 _v)207 static INLINE void Stream_Write_UINT16_BE(wStream* _s, UINT16 _v) 208 { 209 *_s->pointer++ = ((_v) >> 8) & 0xFF; 210 *_s->pointer++ = (_v)&0xFF; 211 } 212 Stream_Write_INT32(wStream * _s,INT32 _v)213 static INLINE void Stream_Write_INT32(wStream* _s, INT32 _v) 214 { 215 *_s->pointer++ = (_v)&0xFF; 216 *_s->pointer++ = ((_v) >> 8) & 0xFF; 217 *_s->pointer++ = ((_v) >> 16) & 0xFF; 218 *_s->pointer++ = ((_v) >> 24) & 0xFF; 219 } 220 Stream_Write_UINT32(wStream * _s,UINT32 _v)221 static INLINE void Stream_Write_UINT32(wStream* _s, UINT32 _v) 222 { 223 *_s->pointer++ = (_v)&0xFF; 224 *_s->pointer++ = ((_v) >> 8) & 0xFF; 225 *_s->pointer++ = ((_v) >> 16) & 0xFF; 226 *_s->pointer++ = ((_v) >> 24) & 0xFF; 227 } 228 Stream_Write_UINT32_BE(wStream * _s,UINT32 _v)229 static INLINE void Stream_Write_UINT32_BE(wStream* _s, UINT32 _v) 230 { 231 Stream_Write_UINT16_BE(_s, ((_v) >> 16 & 0xFFFF)); 232 Stream_Write_UINT16_BE(_s, ((_v)&0xFFFF)); 233 } 234 Stream_Write_UINT64(wStream * _s,UINT64 _v)235 static INLINE void Stream_Write_UINT64(wStream* _s, UINT64 _v) 236 { 237 *_s->pointer++ = (UINT64)(_v)&0xFF; 238 *_s->pointer++ = ((UINT64)(_v) >> 8) & 0xFF; 239 *_s->pointer++ = ((UINT64)(_v) >> 16) & 0xFF; 240 *_s->pointer++ = ((UINT64)(_v) >> 24) & 0xFF; 241 *_s->pointer++ = ((UINT64)(_v) >> 32) & 0xFF; 242 *_s->pointer++ = ((UINT64)(_v) >> 40) & 0xFF; 243 *_s->pointer++ = ((UINT64)(_v) >> 48) & 0xFF; 244 *_s->pointer++ = ((UINT64)(_v) >> 56) & 0xFF; 245 } Stream_Write(wStream * _s,const void * _b,size_t _n)246 static INLINE void Stream_Write(wStream* _s, const void* _b, size_t _n) 247 { 248 if (_n > 0) 249 { 250 memcpy(_s->pointer, (_b), (_n)); 251 Stream_Seek(_s, _n); 252 } 253 } 254 255 #define Stream_Seek_UINT8(_s) Stream_Seek(_s, 1) 256 #define Stream_Seek_UINT16(_s) Stream_Seek(_s, 2) 257 #define Stream_Seek_UINT32(_s) Stream_Seek(_s, 4) 258 #define Stream_Seek_UINT64(_s) Stream_Seek(_s, 8) 259 260 #define Stream_Rewind_UINT8(_s) Stream_Rewind(_s, 1) 261 #define Stream_Rewind_UINT16(_s) Stream_Rewind(_s, 2) 262 #define Stream_Rewind_UINT32(_s) Stream_Rewind(_s, 4) 263 #define Stream_Rewind_UINT64(_s) Stream_Rewind(_s, 8) 264 Stream_Zero(wStream * _s,size_t _n)265 static INLINE void Stream_Zero(wStream* _s, size_t _n) 266 { 267 memset(_s->pointer, '\0', (_n)); 268 Stream_Seek(_s, _n); 269 } 270 Stream_Fill(wStream * _s,int _v,size_t _n)271 static INLINE void Stream_Fill(wStream* _s, int _v, size_t _n) 272 { 273 memset(_s->pointer, _v, (_n)); 274 Stream_Seek(_s, _n); 275 } 276 Stream_Copy(wStream * _src,wStream * _dst,size_t _n)277 static INLINE void Stream_Copy(wStream* _src, wStream* _dst, size_t _n) 278 { 279 memcpy(_dst->pointer, _src->pointer, _n); 280 Stream_Seek(_dst, _n); 281 Stream_Seek(_src, _n); 282 } 283 Stream_Buffer(wStream * _s)284 static INLINE BYTE* Stream_Buffer(wStream* _s) 285 { 286 return _s->buffer; 287 } 288 289 #define Stream_GetBuffer(_s, _b) _b = Stream_Buffer(_s) Stream_SetBuffer(wStream * _s,BYTE * _b)290 static INLINE void Stream_SetBuffer(wStream* _s, BYTE* _b) 291 { 292 _s->buffer = _b; 293 } 294 Stream_Pointer(wStream * _s)295 static INLINE BYTE* Stream_Pointer(wStream* _s) 296 { 297 return _s->pointer; 298 } 299 300 #define Stream_GetPointer(_s, _p) _p = Stream_Pointer(_s) Stream_SetPointer(wStream * _s,BYTE * _p)301 static INLINE void Stream_SetPointer(wStream* _s, BYTE* _p) 302 { 303 _s->pointer = _p; 304 } 305 Stream_Length(wStream * _s)306 static INLINE size_t Stream_Length(wStream* _s) 307 { 308 return _s->length; 309 } 310 311 #define Stream_GetLength(_s, _l) _l = Stream_Length(_s) Stream_SetLength(wStream * _s,size_t _l)312 static INLINE void Stream_SetLength(wStream* _s, size_t _l) 313 { 314 _s->length = _l; 315 } 316 Stream_Capacity(wStream * _s)317 static INLINE size_t Stream_Capacity(wStream* _s) 318 { 319 return _s->capacity; 320 } 321 322 #define Stream_GetCapacity(_s, _c) _c = Stream_Capacity(_s); Stream_SetCapacity(wStream * _s,size_t _c)323 static INLINE void Stream_SetCapacity(wStream* _s, size_t _c) 324 { 325 _s->capacity = _c; 326 } 327 Stream_GetPosition(wStream * _s)328 static INLINE size_t Stream_GetPosition(wStream* _s) 329 { 330 return (_s->pointer - _s->buffer); 331 } 332 Stream_SetPosition(wStream * _s,size_t _p)333 static INLINE void Stream_SetPosition(wStream* _s, size_t _p) 334 { 335 _s->pointer = _s->buffer + (_p); 336 } 337 Stream_SealLength(wStream * _s)338 static INLINE void Stream_SealLength(wStream* _s) 339 { 340 _s->length = (_s->pointer - _s->buffer); 341 } 342 Stream_GetRemainingCapacity(wStream * _s)343 static INLINE size_t Stream_GetRemainingCapacity(wStream* _s) 344 { 345 return (_s->capacity - (_s->pointer - _s->buffer)); 346 } 347 Stream_GetRemainingLength(wStream * _s)348 static INLINE size_t Stream_GetRemainingLength(wStream* _s) 349 { 350 return (_s->length - (_s->pointer - _s->buffer)); 351 } 352 Stream_Clear(wStream * _s)353 static INLINE void Stream_Clear(wStream* _s) 354 { 355 memset(_s->buffer, 0, _s->capacity); 356 } 357 Stream_SafeSeek(wStream * s,size_t size)358 static INLINE BOOL Stream_SafeSeek(wStream* s, size_t size) 359 { 360 if (Stream_GetRemainingLength(s) < size) 361 return FALSE; 362 363 Stream_Seek(s, size); 364 return TRUE; 365 } 366 Stream_Read_UTF16_String(wStream * s,WCHAR * dst,size_t length)367 static INLINE BOOL Stream_Read_UTF16_String(wStream* s, WCHAR* dst, size_t length) 368 { 369 size_t x; 370 371 if (!s || !dst) 372 return FALSE; 373 374 if (Stream_GetRemainingLength(s) / sizeof(WCHAR) < length) 375 return FALSE; 376 377 for (x = 0; x < length; x++) 378 Stream_Read_UINT16(s, dst[x]); 379 380 return TRUE; 381 } 382 Stream_Write_UTF16_String(wStream * s,const WCHAR * src,size_t length)383 static INLINE BOOL Stream_Write_UTF16_String(wStream* s, const WCHAR* src, size_t length) 384 { 385 size_t x; 386 387 if (!s || !src) 388 return FALSE; 389 390 if (Stream_GetRemainingCapacity(s) / sizeof(WCHAR) < length) 391 return FALSE; 392 393 for (x = 0; x < length; x++) 394 Stream_Write_UINT16(s, src[x]); 395 396 return TRUE; 397 } 398 399 /* StreamPool */ 400 401 struct _wStreamPool 402 { 403 int aSize; 404 int aCapacity; 405 wStream** aArray; 406 407 int uSize; 408 int uCapacity; 409 wStream** uArray; 410 411 CRITICAL_SECTION lock; 412 BOOL synchronized; 413 size_t defaultSize; 414 }; 415 416 WINPR_API wStream* StreamPool_Take(wStreamPool* pool, size_t size); 417 WINPR_API void StreamPool_Return(wStreamPool* pool, wStream* s); 418 419 WINPR_API void Stream_AddRef(wStream* s); 420 WINPR_API void Stream_Release(wStream* s); 421 422 WINPR_API wStream* StreamPool_Find(wStreamPool* pool, BYTE* ptr); 423 WINPR_API void StreamPool_AddRef(wStreamPool* pool, BYTE* ptr); 424 WINPR_API void StreamPool_Release(wStreamPool* pool, BYTE* ptr); 425 426 WINPR_API void StreamPool_Clear(wStreamPool* pool); 427 428 WINPR_API wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize); 429 WINPR_API void StreamPool_Free(wStreamPool* pool); 430 431 #ifdef __cplusplus 432 } 433 #endif 434 435 #endif /* WINPR_UTILS_STREAM_H */ 436