FreeRDP
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Modules Pages
include/winpr/stream.h
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#include <winpr/cast.h>
32#include <winpr/wlog.h>
33
34#ifdef __cplusplus
35extern "C"
36{
37#endif
38
39 typedef struct s_wStreamPool wStreamPool;
40
41 typedef struct
42 {
43 BYTE* buffer;
44 BYTE* pointer;
45 size_t length;
46 size_t capacity;
47
48 DWORD count;
49 wStreamPool* pool;
50 BOOL isAllocatedStream;
51 BOOL isOwner;
52 } wStream;
53
54 static INLINE size_t Stream_Capacity(const wStream* _s);
55 WINPR_API size_t Stream_GetRemainingCapacity(const wStream* _s);
56 WINPR_API size_t Stream_GetRemainingLength(const wStream* _s);
57
58 WINPR_API BOOL Stream_EnsureCapacity(wStream* s, size_t size);
59 WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size);
60
61#define WINPR_STREAM_CAST(t, val) WINPR_CXX_COMPAT_CAST(t, val)
62
63#define Stream_CheckAndLogRequiredCapacityOfSize(tag, s, nmemb, size) \
64 Stream_CheckAndLogRequiredCapacityEx(tag, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
65 __func__, __FILE__, (size_t)__LINE__)
66#define Stream_CheckAndLogRequiredCapacity(tag, s, len) \
67 Stream_CheckAndLogRequiredCapacityOfSize((tag), (s), (len), 1)
68
69 WINPR_API BOOL Stream_CheckAndLogRequiredCapacityEx(const char* tag, DWORD level, wStream* s,
70 size_t nmemb, size_t size, const char* fmt,
71 ...);
72 WINPR_API BOOL Stream_CheckAndLogRequiredCapacityExVa(const char* tag, DWORD level, wStream* s,
73 size_t nmemb, size_t size,
74 const char* fmt, va_list args);
75
76#define Stream_CheckAndLogRequiredCapacityOfSizeWLog(log, s, nmemb, size) \
77 Stream_CheckAndLogRequiredCapacityWLogEx(log, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
78 __func__, __FILE__, (size_t)__LINE__)
79
80#define Stream_CheckAndLogRequiredCapacityWLog(log, s, len) \
81 Stream_CheckAndLogRequiredCapacityOfSizeWLog((log), (s), (len), 1)
82
83 WINPR_API BOOL Stream_CheckAndLogRequiredCapacityWLogEx(wLog* log, DWORD level, wStream* s,
84 size_t nmemb, size_t size,
85 const char* fmt, ...);
86 WINPR_API BOOL Stream_CheckAndLogRequiredCapacityWLogExVa(wLog* log, DWORD level, wStream* s,
87 size_t nmemb, size_t size,
88 const char* fmt, va_list args);
89
90 WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer);
91
92 WINPR_ATTR_MALLOC(Stream_Free, 1)
93 WINPR_API wStream* Stream_New(BYTE* buffer, size_t size);
94 WINPR_API wStream* Stream_StaticConstInit(wStream* s, const BYTE* buffer, size_t size);
95 WINPR_API wStream* Stream_StaticInit(wStream* s, BYTE* buffer, size_t size);
96
97#define Stream_CheckAndLogRequiredLengthOfSize(tag, s, nmemb, size) \
98 Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
99 __func__, __FILE__, (size_t)__LINE__)
100#define Stream_CheckAndLogRequiredLength(tag, s, len) \
101 Stream_CheckAndLogRequiredLengthOfSize(tag, s, len, 1)
102
103 WINPR_API BOOL Stream_CheckAndLogRequiredLengthEx(const char* tag, DWORD level, wStream* s,
104 size_t nmemb, size_t size, const char* fmt,
105 ...);
106 WINPR_API BOOL Stream_CheckAndLogRequiredLengthExVa(const char* tag, DWORD level, wStream* s,
107 size_t nmemb, size_t size, const char* fmt,
108 va_list args);
109
110#define Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, nmemb, size) \
111 Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
112 __func__, __FILE__, (size_t)__LINE__)
113#define Stream_CheckAndLogRequiredLengthWLog(log, s, len) \
114 Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, len, 1)
115
116 WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s,
117 size_t nmemb, size_t size,
118 const char* fmt, ...);
119 WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s,
120 size_t nmemb, size_t size,
121 const char* fmt, va_list args);
122
123 static INLINE void Stream_Seek(wStream* s, size_t _offset)
124 {
125 WINPR_ASSERT(s);
126 WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= _offset);
127 s->pointer += (_offset);
128 }
129
130 static INLINE void Stream_Rewind(wStream* s, size_t _offset)
131 {
132 size_t cur = 0;
133 WINPR_ASSERT(s);
134 WINPR_ASSERT(s->buffer <= s->pointer);
135 cur = WINPR_STREAM_CAST(size_t, s->pointer - s->buffer);
136 WINPR_ASSERT(cur >= _offset);
137 if (cur >= _offset)
138 s->pointer -= (_offset);
139 else
140 s->pointer = s->buffer;
141 }
142
143 static INLINE UINT8 stream_read_u8(wStream* _s, BOOL seek)
144 {
145 WINPR_ASSERT(_s);
146 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= sizeof(UINT8));
147
148 const UINT8 v = winpr_Data_Get_UINT8(_s->pointer);
149 if (seek)
150 Stream_Seek(_s, sizeof(UINT8));
151 return v;
152 }
153
154 static INLINE INT8 stream_read_i8(wStream* _s, BOOL seek)
155 {
156 const INT8 v = winpr_Data_Get_INT8(_s->pointer);
157 if (seek)
158 Stream_Seek(_s, sizeof(INT8));
159 return v;
160 }
161
162 static INLINE UINT16 stream_read_u16_le(wStream* _s, BOOL seek)
163 {
164 const size_t typesize = sizeof(UINT16);
165 WINPR_ASSERT(_s);
166 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
167
168 const UINT16 v = winpr_Data_Get_UINT16(_s->pointer);
169 if (seek)
170 Stream_Seek(_s, typesize);
171 return v;
172 }
173
174 static INLINE UINT16 stream_read_u16_be(wStream* _s, BOOL seek)
175 {
176 const size_t typesize = sizeof(UINT16);
177 WINPR_ASSERT(_s);
178 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
179
180 const UINT16 v = winpr_Data_Get_UINT16_BE(_s->pointer);
181 if (seek)
182 Stream_Seek(_s, typesize);
183 return v;
184 }
185
186 static INLINE INT16 stream_read_i16_le(wStream* _s, BOOL seek)
187 {
188 const size_t typesize = sizeof(INT16);
189 WINPR_ASSERT(_s);
190 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
191
192 const INT16 v = winpr_Data_Get_INT16(_s->pointer);
193 if (seek)
194 Stream_Seek(_s, typesize);
195 return v;
196 }
197
198 static INLINE INT16 stream_read_i16_be(wStream* _s, BOOL seek)
199 {
200 const size_t typesize = sizeof(INT16);
201 WINPR_ASSERT(_s);
202 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
203
204 const INT16 v = winpr_Data_Get_INT16_BE(_s->pointer);
205 if (seek)
206 Stream_Seek(_s, typesize);
207 return v;
208 }
209
210 static INLINE UINT32 stream_read_u32_le(wStream* _s, BOOL seek)
211 {
212 const size_t typesize = sizeof(UINT32);
213 WINPR_ASSERT(_s);
214 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
215
216 const UINT32 v = winpr_Data_Get_UINT32(_s->pointer);
217 if (seek)
218 Stream_Seek(_s, typesize);
219 return v;
220 }
221
222 static INLINE UINT32 stream_read_u32_be(wStream* _s, BOOL seek)
223 {
224 const size_t typesize = sizeof(UINT32);
225 WINPR_ASSERT(_s);
226 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
227
228 const UINT32 v = winpr_Data_Get_UINT32_BE(_s->pointer);
229 if (seek)
230 Stream_Seek(_s, typesize);
231 return v;
232 }
233
234 static INLINE INT32 stream_read_i32_le(wStream* _s, BOOL seek)
235 {
236 const size_t typesize = sizeof(INT32);
237 WINPR_ASSERT(_s);
238 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
239
240 const INT32 v = winpr_Data_Get_INT32(_s->pointer);
241 if (seek)
242 Stream_Seek(_s, typesize);
243 return v;
244 }
245
246 static INLINE INT32 stream_read_i32_be(wStream* _s, BOOL seek)
247 {
248 const size_t typesize = sizeof(INT32);
249 WINPR_ASSERT(_s);
250 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
251
252 const INT32 v = winpr_Data_Get_INT32_BE(_s->pointer);
253 if (seek)
254 Stream_Seek(_s, typesize);
255 return v;
256 }
257
258 static INLINE UINT64 stream_read_u64_le(wStream* _s, BOOL seek)
259 {
260 const size_t typesize = sizeof(UINT64);
261 WINPR_ASSERT(_s);
262 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
263
264 const UINT64 v = winpr_Data_Get_UINT64(_s->pointer);
265 if (seek)
266 Stream_Seek(_s, typesize);
267 return v;
268 }
269
270 static INLINE UINT64 stream_read_u64_be(wStream* _s, BOOL seek)
271 {
272 const size_t typesize = sizeof(UINT64);
273 WINPR_ASSERT(_s);
274 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
275
276 const UINT64 v = winpr_Data_Get_UINT64_BE(_s->pointer);
277 if (seek)
278 Stream_Seek(_s, typesize);
279 return v;
280 }
281
282 static INLINE INT64 stream_read_i64_le(wStream* _s, BOOL seek)
283 {
284 const size_t typesize = sizeof(INT64);
285 WINPR_ASSERT(_s);
286 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
287
288 const INT64 v = winpr_Data_Get_INT64(_s->pointer);
289 if (seek)
290 Stream_Seek(_s, typesize);
291 return v;
292 }
293
294 static INLINE INT64 stream_read_i64_be(wStream* _s, BOOL seek)
295 {
296 const size_t typesize = sizeof(INT64);
297 WINPR_ASSERT(_s);
298 WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
299
300 const INT64 v = winpr_Data_Get_INT64_BE(_s->pointer);
301 if (seek)
302 Stream_Seek(_s, typesize);
303 return v;
304 }
305
312 static INLINE UINT8 Stream_Get_UINT8(wStream* _s)
313 {
314 return stream_read_u8(_s, TRUE);
315 }
316
323 static INLINE INT8 Stream_Get_INT8(wStream* _s)
324 {
325 return stream_read_i8(_s, TRUE);
326 }
327
334 static INLINE UINT16 Stream_Get_UINT16(wStream* _s)
335 {
336 return stream_read_u16_le(_s, TRUE);
337 }
338
345 static INLINE INT16 Stream_Get_INT16(wStream* _s)
346 {
347 return stream_read_i16_le(_s, TRUE);
348 }
349
356 static INLINE UINT16 Stream_Get_UINT16_BE(wStream* _s)
357 {
358 return stream_read_u16_be(_s, TRUE);
359 }
360
367 static INLINE INT16 Stream_Get_INT16_BE(wStream* _s)
368 {
369 return stream_read_i16_be(_s, TRUE);
370 }
371
378 static INLINE UINT32 Stream_Get_UINT32(wStream* _s)
379 {
380 return stream_read_u32_le(_s, TRUE);
381 }
382
389 static INLINE INT32 Stream_Get_INT32(wStream* _s)
390 {
391 return stream_read_i32_le(_s, TRUE);
392 }
393
400 static INLINE UINT32 Stream_Get_UINT32_BE(wStream* _s)
401 {
402 return stream_read_u32_be(_s, TRUE);
403 }
404
411 static INLINE INT32 Stream_Get_INT32_BE(wStream* _s)
412 {
413 return stream_read_i32_be(_s, TRUE);
414 }
415
422 static INLINE UINT64 Stream_Get_UINT64(wStream* _s)
423 {
424 return stream_read_u64_le(_s, TRUE);
425 }
426
433 static INLINE INT64 Stream_Get_INT64(wStream* _s)
434 {
435 return stream_read_i64_le(_s, TRUE);
436 }
437
444 static INLINE UINT64 Stream_Get_UINT64_BE(wStream* _s)
445 {
446 return stream_read_u64_be(_s, TRUE);
447 }
448
455 static INLINE INT64 Stream_Get_INT64_BE(wStream* _s)
456 {
457 return stream_read_i64_be(_s, TRUE);
458 }
459
466 static INLINE UINT8 Stream_Peek_Get_UINT8(wStream* _s)
467 {
468 return stream_read_u8(_s, FALSE);
469 }
470
477 static INLINE INT8 Stream_Peek_Get_INT8(wStream* _s)
478 {
479 return stream_read_i8(_s, FALSE);
480 }
481
488 static INLINE UINT16 Stream_Peek_Get_UINT16(wStream* _s)
489 {
490 return stream_read_u16_le(_s, FALSE);
491 }
492
499 static INLINE INT16 Stream_Peek_Get_INT16(wStream* _s)
500 {
501 return stream_read_i16_le(_s, FALSE);
502 }
503
510 static INLINE UINT16 Stream_Peek_Get_UINT16_BE(wStream* _s)
511 {
512 return stream_read_u16_be(_s, FALSE);
513 }
514
521 static INLINE INT16 Stream_Peek_Get_INT16_BE(wStream* _s)
522 {
523 return stream_read_i16_be(_s, FALSE);
524 }
525
532 static INLINE UINT32 Stream_Peek_Get_UINT32(wStream* _s)
533 {
534 return stream_read_u32_le(_s, FALSE);
535 }
536
543 static INLINE INT32 Stream_Peek_Get_INT32(wStream* _s)
544 {
545 return stream_read_i32_le(_s, FALSE);
546 }
547
554 static INLINE UINT32 Stream_Peek_Get_UINT32_BE(wStream* _s)
555 {
556 return stream_read_u32_be(_s, FALSE);
557 }
558
565 static INLINE INT32 Stream_Peek_Get_INT32_BE(wStream* _s)
566 {
567 return stream_read_i32_be(_s, FALSE);
568 }
569
576 static INLINE UINT64 Stream_Peek_Get_UINT64(wStream* _s)
577 {
578 return stream_read_u64_le(_s, FALSE);
579 }
580
587 static INLINE INT64 Stream_Peek_Get_INT64(wStream* _s)
588 {
589 return stream_read_i64_le(_s, FALSE);
590 }
591
598 static INLINE UINT64 Stream_Peek_Get_UINT64_BE(wStream* _s)
599 {
600 return stream_read_u64_be(_s, FALSE);
601 }
602
609 static INLINE INT64 Stream_Peek_Get_INT64_BE(wStream* _s)
610 {
611 return stream_read_i64_be(_s, FALSE);
612 }
613
614#define Stream_Read_UINT8(_s, _v) \
615 do \
616 { \
617 _v = stream_read_u8(_s, TRUE); \
618 } while (0)
619
620#define Stream_Read_INT8(_s, _v) \
621 do \
622 { \
623 _v = stream_read_i8(_s, TRUE); \
624 } while (0)
625
626#define Stream_Read_UINT16(_s, _v) \
627 do \
628 { \
629 _v = stream_read_u16_le(_s, TRUE); \
630 } while (0)
631
632#define Stream_Read_INT16(_s, _v) \
633 do \
634 { \
635 _v = stream_read_i16_le(_s, TRUE); \
636 } while (0)
637
638#define Stream_Read_UINT16_BE(_s, _v) \
639 do \
640 { \
641 _v = stream_read_u16_be(_s, TRUE); \
642 } while (0)
643
644#define Stream_Read_INT16_BE(_s, _v) \
645 do \
646 { \
647 _v = stream_read_i16_be(_s, TRUE); \
648 } while (0)
649
650#define Stream_Read_UINT32(_s, _v) \
651 do \
652 { \
653 _v = stream_read_u32_le(_s, TRUE); \
654 } while (0)
655
656#define Stream_Read_INT32(_s, _v) \
657 do \
658 { \
659 _v = stream_read_i32_le(_s, TRUE); \
660 } while (0)
661
662#define Stream_Read_UINT32_BE(_s, _v) \
663 do \
664 { \
665 _v = stream_read_u32_be(_s, TRUE); \
666 } while (0)
667
668#define Stream_Read_INT32_BE(_s, _v) \
669 do \
670 { \
671 _v = stream_read_i32_be(_s, TRUE); \
672 } while (0)
673
674#define Stream_Read_UINT64(_s, _v) \
675 do \
676 { \
677 _v = stream_read_u64_le(_s, TRUE); \
678 } while (0)
679
680#define Stream_Read_INT64(_s, _v) \
681 do \
682 { \
683 _v = stream_read_i64_le(_s, TRUE); \
684 } while (0)
685
686#define Stream_Read_UINT64_BE(_s, _v) \
687 do \
688 { \
689 _v = stream_read_u64_be(_s, TRUE); \
690 } while (0)
691
692#define Stream_Read_INT64_BE(_s, _v) \
693 do \
694 { \
695 _v = stream_read_i64_be(_s, TRUE); \
696 } while (0)
697
698 static INLINE void Stream_Read(wStream* _s, void* _b, size_t _n)
699 {
700 WINPR_ASSERT(_s);
701 WINPR_ASSERT(_b || (_n == 0));
702 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
703 memcpy(_b, (_s->pointer), (_n));
704 Stream_Seek(_s, _n);
705 }
706
707#define Stream_Peek_UINT8(_s, _v) \
708 do \
709 { \
710 _v = stream_read_u8(_s, FALSE); \
711 } while (0)
712
713#define Stream_Peek_INT8(_s, _v) \
714 do \
715 { \
716 _v = stream_read_i8(_s, FALSE); \
717 } while (0)
718
719#define Stream_Peek_UINT16(_s, _v) \
720 do \
721 { \
722 _v = stream_read_u16_le(_s, FALSE); \
723 } while (0)
724
725#define Stream_Peek_INT16(_s, _v) \
726 do \
727 { \
728 _v = stream_read_i16_le(_s, FALSE); \
729 } while (0)
730
731#define Stream_Peek_UINT16_BE(_s, _v) \
732 do \
733 { \
734 _v = stream_read_u16_be(_s, FALSE); \
735 } while (0)
736
737#define Stream_Peek_INT16_BE(_s, _v) \
738 do \
739 { \
740 _v = stream_read_i16_be(_s, FALSE); \
741 } while (0)
742
743#define Stream_Peek_UINT32(_s, _v) \
744 do \
745 { \
746 _v = stream_read_u32_le(_s, FALSE); \
747 } while (0)
748
749#define Stream_Peek_INT32(_s, _v) \
750 do \
751 { \
752 _v = stream_read_i32_le(_s, FALSE); \
753 } while (0)
754
755#define Stream_Peek_UINT32_BE(_s, _v) \
756 do \
757 { \
758 _v = stream_read_u32_be(_s, FALSE); \
759 } while (0)
760
761#define Stream_Peek_INT32_BE(_s, _v) \
762 do \
763 { \
764 _v = stream_read_i32_be(_s, FALSE); \
765 } while (0)
766
767#define Stream_Peek_UINT64(_s, _v) \
768 do \
769 { \
770 _v = stream_read_u64_le(_s, FALSE); \
771 } while (0)
772
773#define Stream_Peek_INT64(_s, _v) \
774 do \
775 { \
776 _v = stream_read_i64_le(_s, FALSE); \
777 } while (0)
778
779#define Stream_Peek_UINT64_BE(_s, _v) \
780 do \
781 { \
782 _v = stream_read_u64_be(_s, FALSE); \
783 } while (0)
784
785#define Stream_Peek_INT64_BE(_s, _v) \
786 do \
787 { \
788 _v = stream_read_i64_be(_s, FALSE); \
789 } while (0)
790
791 static INLINE void Stream_Peek(const wStream* _s, void* _b, size_t _n)
792 {
793 WINPR_ASSERT(_s);
794 WINPR_ASSERT(_b || (_n == 0));
795 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
796 memcpy(_b, (_s->pointer), (_n));
797 }
798
799#define Stream_Write_INT8(s, v) \
800 do \
801 { \
802 WINPR_ASSERT((v) <= INT8_MAX); \
803 WINPR_ASSERT((v) >= INT8_MIN); \
804 Stream_Write_INT8_unchecked((s), (v)); \
805 } while (0)
806
814 static INLINE void Stream_Write_INT8_unchecked(wStream* _s, INT8 _v)
815 {
816 WINPR_ASSERT(_s);
817 WINPR_ASSERT(_s->pointer);
818 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 1);
819
820 winpr_Data_Write_INT8(_s->pointer, _v);
821 _s->pointer += 1;
822 }
823
824#define Stream_Write_UINT8(s, v) \
825 do \
826 { \
827 WINPR_ASSERT((v) <= UINT8_MAX); \
828 WINPR_ASSERT((v) >= 0); \
829 Stream_Write_UINT8_unchecked((s), (v)); \
830 } while (0)
831
839 static INLINE void Stream_Write_UINT8_unchecked(wStream* _s, UINT8 _v)
840 {
841 WINPR_ASSERT(_s);
842 WINPR_ASSERT(_s->pointer);
843 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 1);
844
845 winpr_Data_Write_UINT8(_s->pointer, _v);
846 _s->pointer += 1;
847 }
848
849#define Stream_Write_INT16(s, v) \
850 do \
851 { \
852 WINPR_ASSERT((v) >= INT16_MIN); \
853 WINPR_ASSERT((v) <= INT16_MAX); \
854 Stream_Write_INT16_unchecked((s), (v)); \
855 } while (0)
856
865 static INLINE void Stream_Write_INT16_unchecked(wStream* _s, INT16 _v)
866 {
867 WINPR_ASSERT(_s);
868 WINPR_ASSERT(_s->pointer);
869 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
870
871 winpr_Data_Write_INT16(_s->pointer, _v);
872 _s->pointer += 2;
873 }
874
875#define Stream_Write_UINT16(s, v) \
876 do \
877 { \
878 WINPR_ASSERT((v) <= UINT16_MAX); \
879 WINPR_ASSERT((v) >= 0); \
880 Stream_Write_UINT16_unchecked((s), (v)); \
881 } while (0)
882
891 static INLINE void Stream_Write_UINT16_unchecked(wStream* _s, UINT16 _v)
892 {
893 WINPR_ASSERT(_s);
894 WINPR_ASSERT(_s->pointer);
895 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
896
897 winpr_Data_Write_UINT16(_s->pointer, _v);
898 _s->pointer += 2;
899 }
900
901#define Stream_Write_UINT16_BE(s, v) \
902 do \
903 { \
904 WINPR_ASSERT((v) <= UINT16_MAX); \
905 WINPR_ASSERT((v) >= 0); \
906 Stream_Write_UINT16_BE_unchecked((s), (v)); \
907 } while (0)
908
917 static INLINE void Stream_Write_UINT16_BE_unchecked(wStream* _s, UINT16 _v)
918 {
919 WINPR_ASSERT(_s);
920 WINPR_ASSERT(_s->pointer);
921 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
922
923 winpr_Data_Write_UINT16_BE(_s->pointer, _v);
924 _s->pointer += 2;
925 }
926
927#define Stream_Write_INT16_BE(s, v) \
928 do \
929 { \
930 WINPR_ASSERT((v) <= INT16_MAX); \
931 WINPR_ASSERT((v) >= INT16_MIN); \
932 Stream_Write_INT16_BE_unchecked((s), (v)); \
933 } while (0)
934
945 static INLINE void Stream_Write_INT16_BE_unchecked(wStream* _s, INT16 _v)
946 {
947 WINPR_ASSERT(_s);
948 WINPR_ASSERT(_s->pointer);
949 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
950
951 winpr_Data_Write_INT16_BE(_s->pointer, _v);
952 _s->pointer += 2;
953 }
954
955#define Stream_Write_UINT24_BE(s, v) \
956 do \
957 { \
958 WINPR_ASSERT((v) <= 0xFFFFFF); \
959 WINPR_ASSERT((v) >= 0); \
960 Stream_Write_UINT24_BE_unchecked((s), (v)); \
961 } while (0)
962
971 static INLINE void Stream_Write_UINT24_BE_unchecked(wStream* _s, UINT32 _v)
972 {
973 WINPR_ASSERT(_s);
974 WINPR_ASSERT(_s->pointer);
975 WINPR_ASSERT(_v <= 0x00FFFFFF);
976 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 3);
977
978 *_s->pointer++ = ((_v) >> 16) & 0xFF;
979 *_s->pointer++ = ((_v) >> 8) & 0xFF;
980 *_s->pointer++ = (_v) & 0xFF;
981 }
982
983#define Stream_Write_INT32(s, v) \
984 do \
985 { \
986 WINPR_ASSERT((v) <= INT32_MAX); \
987 WINPR_ASSERT((v) >= INT32_MIN); \
988 Stream_Write_INT32_unchecked((s), (v)); \
989 } while (0)
990
999 static INLINE void Stream_Write_INT32_unchecked(wStream* _s, INT32 _v)
1000 {
1001 WINPR_ASSERT(_s);
1002 WINPR_ASSERT(_s->pointer);
1003 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1004
1005 winpr_Data_Write_INT32(_s->pointer, _v);
1006 _s->pointer += 4;
1007 }
1008
1009#define Stream_Write_INT32_BE(s, v) \
1010 do \
1011 { \
1012 WINPR_ASSERT((v) <= INT32_MAX); \
1013 WINPR_ASSERT((v) >= INT32_MIN); \
1014 Stream_Write_INT32_BE_unchecked((s), (v)); \
1015 } while (0)
1016
1027 static INLINE void Stream_Write_INT32_BE_unchecked(wStream* _s, INT32 _v)
1028 {
1029 WINPR_ASSERT(_s);
1030 WINPR_ASSERT(_s->pointer);
1031 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1032
1033 winpr_Data_Write_INT32_BE(_s->pointer, _v);
1034 _s->pointer += 4;
1035 }
1036
1037#define Stream_Write_UINT32(s, v) \
1038 do \
1039 { \
1040 WINPR_ASSERT((v) <= UINT32_MAX); \
1041 WINPR_ASSERT((v) >= 0); \
1042 Stream_Write_UINT32_unchecked((s), (v)); \
1043 } while (0)
1044
1053 static INLINE void Stream_Write_UINT32_unchecked(wStream* _s, UINT32 _v)
1054 {
1055 WINPR_ASSERT(_s);
1056 WINPR_ASSERT(_s->pointer);
1057 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1058
1059 winpr_Data_Write_UINT32(_s->pointer, _v);
1060 _s->pointer += 4;
1061 }
1062
1063#define Stream_Write_UINT32_BE(s, v) \
1064 do \
1065 { \
1066 WINPR_ASSERT((v) <= UINT32_MAX); \
1067 WINPR_ASSERT((v) >= 0); \
1068 Stream_Write_UINT32_BE_unchecked((s), (v)); \
1069 } while (0)
1070
1079 static INLINE void Stream_Write_UINT32_BE_unchecked(wStream* _s, UINT32 _v)
1080 {
1081 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
1082
1083 winpr_Data_Write_UINT32_BE(_s->pointer, _v);
1084 _s->pointer += 4;
1085 }
1086
1093 static INLINE void Stream_Write_UINT64(wStream* _s, UINT64 _v)
1094 {
1095 WINPR_ASSERT(_s);
1096 WINPR_ASSERT(_s->pointer);
1097 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1098
1099 winpr_Data_Write_UINT64(_s->pointer, _v);
1100 _s->pointer += 8;
1101 }
1102
1109 static INLINE void Stream_Write_UINT64_BE(wStream* _s, UINT64 _v)
1110 {
1111 WINPR_ASSERT(_s);
1112 WINPR_ASSERT(_s->pointer);
1113 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1114
1115 winpr_Data_Write_UINT64_BE(_s->pointer, _v);
1116 _s->pointer += 8;
1117 }
1118
1126 static INLINE void Stream_Write_INT64(wStream* _s, INT64 _v)
1127 {
1128 WINPR_ASSERT(_s);
1129 WINPR_ASSERT(_s->pointer);
1130 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1131
1132 winpr_Data_Write_INT64(_s->pointer, _v);
1133 _s->pointer += 8;
1134 }
1135
1143 static INLINE void Stream_Write_INT64_BE(wStream* _s, INT64 _v)
1144 {
1145 WINPR_ASSERT(_s);
1146 WINPR_ASSERT(_s->pointer);
1147 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
1148
1149 winpr_Data_Write_INT64_BE(_s->pointer, _v);
1150 _s->pointer += 8;
1151 }
1152
1153 static INLINE void Stream_Write(wStream* _s, const void* _b, size_t _n)
1154 {
1155 if (_n > 0)
1156 {
1157 WINPR_ASSERT(_s);
1158 WINPR_ASSERT(_b);
1159 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
1160 memcpy(_s->pointer, (_b), (_n));
1161 Stream_Seek(_s, _n);
1162 }
1163 }
1164
1165 static INLINE void Stream_Seek_UINT8(wStream* _s)
1166 {
1167 Stream_Seek(_s, sizeof(UINT8));
1168 }
1169 static INLINE void Stream_Seek_UINT16(wStream* _s)
1170 {
1171 Stream_Seek(_s, sizeof(UINT16));
1172 }
1173 static INLINE void Stream_Seek_UINT32(wStream* _s)
1174 {
1175 Stream_Seek(_s, sizeof(UINT32));
1176 }
1177 static INLINE void Stream_Seek_UINT64(wStream* _s)
1178 {
1179 Stream_Seek(_s, sizeof(UINT64));
1180 }
1181
1182 static INLINE void Stream_Rewind_UINT8(wStream* _s)
1183 {
1184 Stream_Rewind(_s, sizeof(UINT8));
1185 }
1186 static INLINE void Stream_Rewind_UINT16(wStream* _s)
1187 {
1188 Stream_Rewind(_s, sizeof(UINT16));
1189 }
1190 static INLINE void Stream_Rewind_UINT32(wStream* _s)
1191 {
1192 Stream_Rewind(_s, sizeof(UINT32));
1193 }
1194 static INLINE void Stream_Rewind_UINT64(wStream* _s)
1195 {
1196 Stream_Rewind(_s, sizeof(UINT64));
1197 }
1198
1199 static INLINE void Stream_Fill(wStream* _s, int _v, size_t _n)
1200 {
1201 WINPR_ASSERT(_s);
1202 WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= (_n));
1203 memset(_s->pointer, _v, (_n));
1204 Stream_Seek(_s, _n);
1205 }
1206
1207 static INLINE void Stream_Zero(wStream* _s, size_t _n)
1208 {
1209 Stream_Fill(_s, '\0', _n);
1210 }
1211
1212 static INLINE void Stream_Copy(wStream* _src, wStream* _dst, size_t _n)
1213 {
1214 WINPR_ASSERT(_src);
1215 WINPR_ASSERT(_dst);
1216 WINPR_ASSERT(Stream_GetRemainingCapacity(_src) >= (_n));
1217 WINPR_ASSERT(Stream_GetRemainingCapacity(_dst) >= (_n));
1218
1219 memcpy(_dst->pointer, _src->pointer, _n);
1220 Stream_Seek(_dst, _n);
1221 Stream_Seek(_src, _n);
1222 }
1223
1228#define Stream_BufferAs(s, type) WINPR_STREAM_CAST(type*, Stream_Buffer(s))
1229
1230 static INLINE BYTE* Stream_Buffer(wStream* _s)
1231 {
1232 WINPR_ASSERT(_s);
1233 return _s->buffer;
1234 }
1235
1240#define Stream_ConstBufferAs(s, type) WINPR_STREAM_CAST(type*, Stream_ConstBuffer(s))
1241 static INLINE const BYTE* Stream_ConstBuffer(const wStream* _s)
1242 {
1243 WINPR_ASSERT(_s);
1244 return _s->buffer;
1245 }
1246
1247#define Stream_GetBuffer(_s, _b) _b = Stream_Buffer(_s)
1248
1253#define Stream_GetBufferAs(_s, _b) _b = Stream_BufferAs(_s, __typeof(_b))
1254
1255#define Stream_PointerAs(s, type) WINPR_STREAM_CAST(type*, Stream_Pointer(s))
1256
1257 static INLINE void* Stream_Pointer(wStream* _s)
1258 {
1259 WINPR_ASSERT(_s);
1260 return _s->pointer;
1261 }
1262
1263 static INLINE const void* Stream_ConstPointer(const wStream* _s)
1264 {
1265 WINPR_ASSERT(_s);
1266 return _s->pointer;
1267 }
1268
1269#define Stream_GetPointer(_s, _p) _p = Stream_Pointer(_s)
1270
1275#define Stream_GetPointerAs(_s, _p) _p = Stream_PointerAs(_s, __typeof(_p))
1276
1277#if defined(WITH_WINPR_DEPRECATED)
1278 WINPR_DEPRECATED_VAR("Use Stream_SetPosition instead",
1279 WINPR_API BOOL Stream_SetPointer(wStream* _s, BYTE* _p));
1280 WINPR_DEPRECATED_VAR("Use Stream_New(buffer, capacity) instead",
1281 WINPR_API BOOL Stream_SetBuffer(wStream* _s, BYTE* _b));
1282 WINPR_DEPRECATED_VAR("Use Stream_New(buffer, capacity) instead",
1283 WINPR_API void Stream_SetCapacity(wStream* _s, size_t capacity));
1284#endif
1285
1286 static INLINE size_t Stream_Length(const wStream* _s)
1287 {
1288 WINPR_ASSERT(_s);
1289 return _s->length;
1290 }
1291
1292#define Stream_GetLength(_s, _l) _l = Stream_Length(_s)
1293 WINPR_API BOOL Stream_SetLength(wStream* _s, size_t _l);
1294
1295 static INLINE size_t Stream_Capacity(const wStream* _s)
1296 {
1297 WINPR_ASSERT(_s);
1298 return _s->capacity;
1299 }
1300
1301#define Stream_GetCapacity(_s, _c) _c = Stream_Capacity(_s);
1302
1303 static INLINE size_t Stream_GetPosition(const wStream* _s)
1304 {
1305 WINPR_ASSERT(_s);
1306 WINPR_ASSERT(_s->buffer <= _s->pointer);
1307 return WINPR_STREAM_CAST(size_t, (_s->pointer - _s->buffer));
1308 }
1309
1310 WINPR_API BOOL Stream_SetPosition(wStream* _s, size_t _p);
1311
1312 WINPR_API void Stream_SealLength(wStream* _s);
1313
1314 static INLINE void Stream_Clear(wStream* _s)
1315 {
1316 WINPR_ASSERT(_s);
1317 memset(_s->buffer, 0, _s->capacity);
1318 }
1319
1320#define Stream_SafeSeek(s, size) Stream_SafeSeekEx(s, size, __FILE__, __LINE__, __func__)
1321 WINPR_API BOOL Stream_SafeSeekEx(wStream* s, size_t size, const char* file, size_t line,
1322 const char* fkt);
1323
1324 WINPR_API BOOL Stream_Read_UTF16_String(wStream* s, WCHAR* dst, size_t charLength);
1325 WINPR_API BOOL Stream_Write_UTF16_String(wStream* s, const WCHAR* src, size_t charLength);
1326
1336 WINPR_API char* Stream_Read_UTF16_String_As_UTF8(wStream* s, size_t wcharLength,
1337 size_t* pUtfCharLength);
1338
1348 WINPR_API SSIZE_T Stream_Read_UTF16_String_As_UTF8_Buffer(wStream* s, size_t wcharLength,
1349 char* utfBuffer,
1350 size_t utfBufferCharLength);
1351
1363 WINPR_API SSIZE_T Stream_Write_UTF16_String_From_UTF8(wStream* s, size_t wcharLength,
1364 const char* src, size_t length,
1365 BOOL fill);
1366
1367 /* StreamPool */
1368
1369 WINPR_API void StreamPool_Return(wStreamPool* pool, wStream* s);
1370
1376 WINPR_API void Stream_AddRef(wStream* s);
1377
1385 WINPR_API void Stream_Release(wStream* s);
1386
1387 WINPR_ATTR_MALLOC(Stream_Release, 1)
1388 WINPR_API wStream* StreamPool_Take(wStreamPool* pool, size_t size);
1389
1390 WINPR_API wStream* StreamPool_Find(wStreamPool* pool, const BYTE* ptr);
1391
1400 WINPR_API size_t StreamPool_UsedCount(wStreamPool* pool);
1401
1412 WINPR_API BOOL StreamPool_WaitForReturn(wStreamPool* pool, UINT32 timeoutMS);
1413
1414 WINPR_API void StreamPool_Clear(wStreamPool* pool);
1415
1416 WINPR_API void StreamPool_Free(wStreamPool* pool);
1417
1418 WINPR_ATTR_MALLOC(StreamPool_Free, 1)
1419 WINPR_API wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize);
1420
1421 WINPR_API char* StreamPool_GetStatistics(wStreamPool* pool, char* buffer, size_t size);
1422
1423#ifdef __cplusplus
1424}
1425#endif
1426
1427#endif /* WINPR_UTILS_STREAM_H */