1456 lines
43 KiB
C
1456 lines
43 KiB
C
/*
|
|
* WinPR: Windows Portable Runtime
|
|
* Stream Utils
|
|
*
|
|
* Copyright 2011 Vic Lee
|
|
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
|
* Copyright 2017 Armin Novak <armin.novak@thincast.com>
|
|
* Copyright 2017 Thincast Technologies GmbH
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef WINPR_UTILS_STREAM_H
|
|
#define WINPR_UTILS_STREAM_H
|
|
|
|
#include <winpr/winpr.h>
|
|
#include <winpr/wtypes.h>
|
|
#include <winpr/endian.h>
|
|
#include <winpr/synch.h>
|
|
#include <winpr/assert.h>
|
|
#include <winpr/cast.h>
|
|
#include <winpr/wlog.h>
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
typedef struct s_wStreamPool wStreamPool;
|
|
|
|
typedef struct
|
|
{
|
|
BYTE* buffer;
|
|
BYTE* pointer;
|
|
size_t length;
|
|
size_t capacity;
|
|
|
|
DWORD count;
|
|
wStreamPool* pool;
|
|
BOOL isAllocatedStream;
|
|
BOOL isOwner;
|
|
} wStream;
|
|
|
|
/** @brief helper initializing a \b wStream context
|
|
*
|
|
* @return The initialized context
|
|
* @since version 3.24.0
|
|
*/
|
|
static inline wStream Stream_Init(void)
|
|
{
|
|
const wStream empty = { nullptr, nullptr, 0, 0, 0, nullptr, FALSE, FALSE };
|
|
return empty;
|
|
}
|
|
|
|
static inline size_t Stream_Capacity(const wStream* _s);
|
|
WINPR_API size_t Stream_GetRemainingCapacity(const wStream* _s);
|
|
WINPR_API size_t Stream_GetRemainingLength(const wStream* _s);
|
|
|
|
WINPR_API BOOL Stream_EnsureCapacity(wStream* s, size_t size);
|
|
WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size);
|
|
|
|
#define WINPR_STREAM_CAST(t, val) WINPR_CXX_COMPAT_CAST(t, val)
|
|
|
|
#define Stream_CheckAndLogRequiredCapacityOfSize(tag, s, nmemb, size) \
|
|
Stream_CheckAndLogRequiredCapacityEx(tag, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
|
|
__func__, __FILE__, (size_t)__LINE__)
|
|
#define Stream_CheckAndLogRequiredCapacity(tag, s, len) \
|
|
Stream_CheckAndLogRequiredCapacityOfSize((tag), (s), (len), 1)
|
|
|
|
WINPR_API BOOL Stream_CheckAndLogRequiredCapacityEx(const char* tag, DWORD level, wStream* s,
|
|
size_t nmemb, size_t size, const char* fmt,
|
|
...);
|
|
WINPR_API BOOL Stream_CheckAndLogRequiredCapacityExVa(const char* tag, DWORD level, wStream* s,
|
|
size_t nmemb, size_t size,
|
|
const char* fmt, va_list args);
|
|
|
|
#define Stream_CheckAndLogRequiredCapacityOfSizeWLog(log, s, nmemb, size) \
|
|
Stream_CheckAndLogRequiredCapacityWLogEx(log, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
|
|
__func__, __FILE__, (size_t)__LINE__)
|
|
|
|
#define Stream_CheckAndLogRequiredCapacityWLog(log, s, len) \
|
|
Stream_CheckAndLogRequiredCapacityOfSizeWLog((log), (s), (len), 1)
|
|
|
|
WINPR_API BOOL Stream_CheckAndLogRequiredCapacityWLogEx(wLog* log, DWORD level, wStream* s,
|
|
size_t nmemb, size_t size,
|
|
const char* fmt, ...);
|
|
WINPR_API BOOL Stream_CheckAndLogRequiredCapacityWLogExVa(wLog* log, DWORD level, wStream* s,
|
|
size_t nmemb, size_t size,
|
|
const char* fmt, va_list args);
|
|
|
|
WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer);
|
|
|
|
WINPR_ATTR_MALLOC(Stream_Free, 1)
|
|
WINPR_ATTR_NODISCARD
|
|
WINPR_API wStream* Stream_New(BYTE* buffer, size_t size);
|
|
WINPR_API wStream* Stream_StaticConstInit(wStream* s, const BYTE* buffer, size_t size);
|
|
WINPR_API wStream* Stream_StaticInit(wStream* s, BYTE* buffer, size_t size);
|
|
|
|
#define Stream_CheckAndLogRequiredLengthOfSize(tag, s, nmemb, size) \
|
|
Stream_CheckAndLogRequiredLengthEx(tag, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
|
|
__func__, __FILE__, (size_t)__LINE__)
|
|
#define Stream_CheckAndLogRequiredLength(tag, s, len) \
|
|
Stream_CheckAndLogRequiredLengthOfSize(tag, s, len, 1)
|
|
|
|
WINPR_API BOOL Stream_CheckAndLogRequiredLengthEx(const char* tag, DWORD level, wStream* s,
|
|
size_t nmemb, size_t size, const char* fmt,
|
|
...);
|
|
WINPR_API BOOL Stream_CheckAndLogRequiredLengthExVa(const char* tag, DWORD level, wStream* s,
|
|
size_t nmemb, size_t size, const char* fmt,
|
|
va_list args);
|
|
|
|
#define Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, nmemb, size) \
|
|
Stream_CheckAndLogRequiredLengthWLogEx(log, WLOG_WARN, s, nmemb, size, "%s(%s:%" PRIuz ")", \
|
|
__func__, __FILE__, (size_t)__LINE__)
|
|
#define Stream_CheckAndLogRequiredLengthWLog(log, s, len) \
|
|
Stream_CheckAndLogRequiredLengthOfSizeWLog(log, s, len, 1)
|
|
|
|
WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogEx(wLog* log, DWORD level, wStream* s,
|
|
size_t nmemb, size_t size,
|
|
const char* fmt, ...);
|
|
WINPR_API BOOL Stream_CheckAndLogRequiredLengthWLogExVa(wLog* log, DWORD level, wStream* s,
|
|
size_t nmemb, size_t size,
|
|
const char* fmt, va_list args);
|
|
|
|
static inline void Stream_Seek(wStream* s, size_t _offset)
|
|
{
|
|
WINPR_ASSERT(s);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(s) >= _offset);
|
|
s->pointer += (_offset);
|
|
}
|
|
|
|
static inline void Stream_Rewind(wStream* s, size_t _offset)
|
|
{
|
|
size_t cur = 0;
|
|
WINPR_ASSERT(s);
|
|
WINPR_ASSERT(s->buffer <= s->pointer);
|
|
cur = WINPR_STREAM_CAST(size_t, s->pointer - s->buffer);
|
|
WINPR_ASSERT(cur >= _offset);
|
|
if (cur >= _offset)
|
|
s->pointer -= (_offset);
|
|
else
|
|
s->pointer = s->buffer;
|
|
}
|
|
|
|
static inline UINT8 stream_read_u8(wStream* _s, BOOL seek)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= sizeof(UINT8));
|
|
|
|
const UINT8 v = winpr_Data_Get_UINT8(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, sizeof(UINT8));
|
|
return v;
|
|
}
|
|
|
|
static inline INT8 stream_read_i8(wStream* _s, BOOL seek)
|
|
{
|
|
const INT8 v = winpr_Data_Get_INT8(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, sizeof(INT8));
|
|
return v;
|
|
}
|
|
|
|
static inline UINT16 stream_read_u16_le(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(UINT16);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const UINT16 v = winpr_Data_Get_UINT16(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline UINT16 stream_read_u16_be(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(UINT16);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const UINT16 v = winpr_Data_Get_UINT16_BE(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline INT16 stream_read_i16_le(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(INT16);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const INT16 v = winpr_Data_Get_INT16(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline INT16 stream_read_i16_be(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(INT16);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const INT16 v = winpr_Data_Get_INT16_BE(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline UINT32 stream_read_u32_le(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(UINT32);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const UINT32 v = winpr_Data_Get_UINT32(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline UINT32 stream_read_u32_be(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(UINT32);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const UINT32 v = winpr_Data_Get_UINT32_BE(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline INT32 stream_read_i32_le(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(INT32);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const INT32 v = winpr_Data_Get_INT32(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline INT32 stream_read_i32_be(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(INT32);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const INT32 v = winpr_Data_Get_INT32_BE(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline UINT64 stream_read_u64_le(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(UINT64);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const UINT64 v = winpr_Data_Get_UINT64(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline UINT64 stream_read_u64_be(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(UINT64);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const UINT64 v = winpr_Data_Get_UINT64_BE(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline INT64 stream_read_i64_le(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(INT64);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const INT64 v = winpr_Data_Get_INT64(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
static inline INT64 stream_read_i64_be(wStream* _s, BOOL seek)
|
|
{
|
|
const size_t typesize = sizeof(INT64);
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingLength(_s) >= typesize);
|
|
|
|
const INT64 v = winpr_Data_Get_INT64_BE(_s->pointer);
|
|
if (seek)
|
|
Stream_Seek(_s, typesize);
|
|
return v;
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_UINT8
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT8 Stream_Get_UINT8(wStream* _s)
|
|
{
|
|
return stream_read_u8(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_INT8
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT8 Stream_Get_INT8(wStream* _s)
|
|
{
|
|
return stream_read_i8(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_UINT16
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT16 Stream_Get_UINT16(wStream* _s)
|
|
{
|
|
return stream_read_u16_le(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_INT16
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT16 Stream_Get_INT16(wStream* _s)
|
|
{
|
|
return stream_read_i16_le(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_UINT16 big endian
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT16 Stream_Get_UINT16_BE(wStream* _s)
|
|
{
|
|
return stream_read_u16_be(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_INT16 big endian
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT16 Stream_Get_INT16_BE(wStream* _s)
|
|
{
|
|
return stream_read_i16_be(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_UINT32
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT32 Stream_Get_UINT32(wStream* _s)
|
|
{
|
|
return stream_read_u32_le(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_INT32
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT32 Stream_Get_INT32(wStream* _s)
|
|
{
|
|
return stream_read_i32_le(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_UINT32 big endian
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT32 Stream_Get_UINT32_BE(wStream* _s)
|
|
{
|
|
return stream_read_u32_be(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_INT32 big endian
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT32 Stream_Get_INT32_BE(wStream* _s)
|
|
{
|
|
return stream_read_i32_be(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_UINT64
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT64 Stream_Get_UINT64(wStream* _s)
|
|
{
|
|
return stream_read_u64_le(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_INT64
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT64 Stream_Get_INT64(wStream* _s)
|
|
{
|
|
return stream_read_i64_le(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_UINT64 big endian
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT64 Stream_Get_UINT64_BE(wStream* _s)
|
|
{
|
|
return stream_read_u64_be(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Stream_Get_INT64 big endian
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT64 Stream_Get_INT64_BE(wStream* _s)
|
|
{
|
|
return stream_read_i64_be(_s, TRUE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a UINT8 from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT8 Stream_Peek_Get_UINT8(wStream* _s)
|
|
{
|
|
return stream_read_u8(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a INT8 from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT8 Stream_Peek_Get_INT8(wStream* _s)
|
|
{
|
|
return stream_read_i8(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a UINT16 from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT16 Stream_Peek_Get_UINT16(wStream* _s)
|
|
{
|
|
return stream_read_u16_le(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a INT16 from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT16 Stream_Peek_Get_INT16(wStream* _s)
|
|
{
|
|
return stream_read_i16_le(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a UINT16 big endian from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT16 Stream_Peek_Get_UINT16_BE(wStream* _s)
|
|
{
|
|
return stream_read_u16_be(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a INT16 big endian from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT16 Stream_Peek_Get_INT16_BE(wStream* _s)
|
|
{
|
|
return stream_read_i16_be(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a UINT32 from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT32 Stream_Peek_Get_UINT32(wStream* _s)
|
|
{
|
|
return stream_read_u32_le(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a INT32 from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT32 Stream_Peek_Get_INT32(wStream* _s)
|
|
{
|
|
return stream_read_i32_le(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a UINT32 big endian from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT32 Stream_Peek_Get_UINT32_BE(wStream* _s)
|
|
{
|
|
return stream_read_u32_be(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a INT32 big endian from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT32 Stream_Peek_Get_INT32_BE(wStream* _s)
|
|
{
|
|
return stream_read_i32_be(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a UINT64 from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT64 Stream_Peek_Get_UINT64(wStream* _s)
|
|
{
|
|
return stream_read_u64_le(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a INT64 from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT64 Stream_Peek_Get_INT64(wStream* _s)
|
|
{
|
|
return stream_read_i64_le(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a UINT64 big endian from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline UINT64 Stream_Peek_Get_UINT64_BE(wStream* _s)
|
|
{
|
|
return stream_read_u64_be(_s, FALSE);
|
|
}
|
|
|
|
/**
|
|
* @brief Read a INT64 big endian from the stream, do not increment stream position
|
|
* @param _s The stream to read from
|
|
* @return an integer
|
|
* @since version 3.9.0
|
|
*/
|
|
static inline INT64 Stream_Peek_Get_INT64_BE(wStream* _s)
|
|
{
|
|
return stream_read_i64_be(_s, FALSE);
|
|
}
|
|
|
|
#define Stream_Read_UINT8(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u8(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_INT8(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i8(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_UINT16(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u16_le(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_INT16(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i16_le(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_UINT16_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u16_be(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_INT16_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i16_be(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_UINT32(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u32_le(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_INT32(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i32_le(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_UINT32_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u32_be(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_INT32_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i32_be(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_UINT64(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u64_le(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_INT64(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i64_le(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_UINT64_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u64_be(_s, TRUE); \
|
|
} while (0)
|
|
|
|
#define Stream_Read_INT64_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i64_be(_s, TRUE); \
|
|
} while (0)
|
|
|
|
static inline void Stream_Read(wStream* _s, void* _b, size_t _n)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_b || (_n == 0));
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
|
|
memcpy(_b, (_s->pointer), (_n));
|
|
Stream_Seek(_s, _n);
|
|
}
|
|
|
|
#define Stream_Peek_UINT8(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u8(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_INT8(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i8(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_UINT16(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u16_le(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_INT16(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i16_le(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_UINT16_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u16_be(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_INT16_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i16_be(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_UINT32(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u32_le(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_INT32(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i32_le(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_UINT32_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u32_be(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_INT32_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i32_be(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_UINT64(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u64_le(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_INT64(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i64_le(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_UINT64_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_u64_be(_s, FALSE); \
|
|
} while (0)
|
|
|
|
#define Stream_Peek_INT64_BE(_s, _v) \
|
|
do \
|
|
{ \
|
|
_v = stream_read_i64_be(_s, FALSE); \
|
|
} while (0)
|
|
|
|
static inline void Stream_Peek(const wStream* _s, void* _b, size_t _n)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_b || (_n == 0));
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
|
|
memcpy(_b, (_s->pointer), (_n));
|
|
}
|
|
|
|
#define Stream_Write_INT8(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= INT8_MAX); \
|
|
WINPR_ASSERT((v) >= INT8_MIN); \
|
|
Stream_Write_INT8_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b INT8 to a \b wStream. The stream must be large enough to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_INT8 instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_INT8_unchecked(wStream* _s, INT8 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 1);
|
|
|
|
winpr_Data_Write_INT8(_s->pointer, _v);
|
|
_s->pointer += 1;
|
|
}
|
|
|
|
#define Stream_Write_UINT8(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= UINT8_MAX); \
|
|
WINPR_ASSERT((v) >= 0); \
|
|
Stream_Write_UINT8_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b UINT8 to a \b wStream. The stream must be large enough to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_UINT8 instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_UINT8_unchecked(wStream* _s, UINT8 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 1);
|
|
|
|
winpr_Data_Write_UINT8(_s->pointer, _v);
|
|
_s->pointer += 1;
|
|
}
|
|
|
|
#define Stream_Write_INT16(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) >= INT16_MIN); \
|
|
WINPR_ASSERT((v) <= INT16_MAX); \
|
|
Stream_Write_INT16_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b INT16 as \b little endian to a \b wStream. The stream must be large
|
|
* enough to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_INT16 instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_INT16_unchecked(wStream* _s, INT16 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
|
|
|
|
winpr_Data_Write_INT16(_s->pointer, _v);
|
|
_s->pointer += 2;
|
|
}
|
|
|
|
#define Stream_Write_UINT16(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= UINT16_MAX); \
|
|
WINPR_ASSERT((v) >= 0); \
|
|
Stream_Write_UINT16_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b UINT16 as \b little endian to a \b wStream. The stream must be large
|
|
* enough to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_UINT16 instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_UINT16_unchecked(wStream* _s, UINT16 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
|
|
|
|
winpr_Data_Write_UINT16(_s->pointer, _v);
|
|
_s->pointer += 2;
|
|
}
|
|
|
|
#define Stream_Write_UINT16_BE(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= UINT16_MAX); \
|
|
WINPR_ASSERT((v) >= 0); \
|
|
Stream_Write_UINT16_BE_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b UINT16 as \b big endian to a \b wStream. The stream must be large enough
|
|
* to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_UINT16_BE instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_UINT16_BE_unchecked(wStream* _s, UINT16 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
|
|
|
|
winpr_Data_Write_UINT16_BE(_s->pointer, _v);
|
|
_s->pointer += 2;
|
|
}
|
|
|
|
#define Stream_Write_INT16_BE(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= INT16_MAX); \
|
|
WINPR_ASSERT((v) >= INT16_MIN); \
|
|
Stream_Write_INT16_BE_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b UINT16 as \b big endian to a \b wStream. The stream must be large enough
|
|
* to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_UINT16_BE instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*
|
|
* @since version 3.10.0
|
|
*/
|
|
static inline void Stream_Write_INT16_BE_unchecked(wStream* _s, INT16 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 2);
|
|
|
|
winpr_Data_Write_INT16_BE(_s->pointer, _v);
|
|
_s->pointer += 2;
|
|
}
|
|
|
|
#define Stream_Write_UINT24_BE(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= 0xFFFFFF); \
|
|
WINPR_ASSERT((v) >= 0); \
|
|
Stream_Write_UINT24_BE_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b UINT24 as \b big endian to a \b wStream. The stream must be large enough
|
|
* to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_UINT24_BE instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_UINT24_BE_unchecked(wStream* _s, UINT32 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(_v <= 0x00FFFFFF);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 3);
|
|
|
|
*_s->pointer++ = ((_v) >> 16) & 0xFF;
|
|
*_s->pointer++ = ((_v) >> 8) & 0xFF;
|
|
*_s->pointer++ = (_v) & 0xFF;
|
|
}
|
|
|
|
#define Stream_Write_INT32(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= INT32_MAX); \
|
|
WINPR_ASSERT((v) >= INT32_MIN); \
|
|
Stream_Write_INT32_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b INT32 as \b little endian to a \b wStream. The stream must be large
|
|
* enough to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_INT32 instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_INT32_unchecked(wStream* _s, INT32 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
|
|
|
|
winpr_Data_Write_INT32(_s->pointer, _v);
|
|
_s->pointer += 4;
|
|
}
|
|
|
|
#define Stream_Write_INT32_BE(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= INT32_MAX); \
|
|
WINPR_ASSERT((v) >= INT32_MIN); \
|
|
Stream_Write_INT32_BE_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b INT32 as \b little endian to a \b wStream. The stream must be large
|
|
* enough to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_INT32 instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*
|
|
* @since version 3.10.0
|
|
*/
|
|
static inline void Stream_Write_INT32_BE_unchecked(wStream* _s, INT32 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
|
|
|
|
winpr_Data_Write_INT32_BE(_s->pointer, _v);
|
|
_s->pointer += 4;
|
|
}
|
|
|
|
#define Stream_Write_UINT32(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= UINT32_MAX); \
|
|
WINPR_ASSERT((v) >= 0); \
|
|
Stream_Write_UINT32_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b UINT32 as \b little endian to a \b wStream. The stream must be large
|
|
* enough to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_UINT32 instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_UINT32_unchecked(wStream* _s, UINT32 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
|
|
|
|
winpr_Data_Write_UINT32(_s->pointer, _v);
|
|
_s->pointer += 4;
|
|
}
|
|
|
|
#define Stream_Write_UINT32_BE(s, v) \
|
|
do \
|
|
{ \
|
|
WINPR_ASSERT((v) <= UINT32_MAX); \
|
|
WINPR_ASSERT((v) >= 0); \
|
|
Stream_Write_UINT32_BE_unchecked((s), (v)); \
|
|
} while (0)
|
|
|
|
/** @brief writes a \b UINT32 as \b big endian to a \b wStream. The stream must be large enough
|
|
* to hold the data.
|
|
*
|
|
* Do not use directly, use the define @ref Stream_Write_UINT32_BE instead
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_UINT32_BE_unchecked(wStream* _s, UINT32 _v)
|
|
{
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 4);
|
|
|
|
winpr_Data_Write_UINT32_BE(_s->pointer, _v);
|
|
_s->pointer += 4;
|
|
}
|
|
|
|
/** @brief writes a \b UINT64 as \b little endian to a \b wStream. The stream must be large
|
|
* enough to hold the data.
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_UINT64(wStream* _s, UINT64 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
|
|
|
|
winpr_Data_Write_UINT64(_s->pointer, _v);
|
|
_s->pointer += 8;
|
|
}
|
|
|
|
/** @brief writes a \b UINT64 as \b big endian to a \b wStream. The stream must be large enough
|
|
* to hold the data.
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
*/
|
|
static inline void Stream_Write_UINT64_BE(wStream* _s, UINT64 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
|
|
|
|
winpr_Data_Write_UINT64_BE(_s->pointer, _v);
|
|
_s->pointer += 8;
|
|
}
|
|
|
|
/** @brief writes a \b INT64 as \b little endian to a \b wStream. The stream must be large
|
|
* enough to hold the data.
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
* \since version 3.10.0
|
|
*/
|
|
static inline void Stream_Write_INT64(wStream* _s, INT64 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
|
|
|
|
winpr_Data_Write_INT64(_s->pointer, _v);
|
|
_s->pointer += 8;
|
|
}
|
|
|
|
/** @brief writes a \b INT64 as \b big endian to a \b wStream. The stream must be large enough
|
|
* to hold the data.
|
|
*
|
|
* \param _s The stream to write to, must not be \b nullptr
|
|
* \param _v The value to write
|
|
* \since version 3.10.0
|
|
*/
|
|
static inline void Stream_Write_INT64_BE(wStream* _s, INT64 _v)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->pointer);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= 8);
|
|
|
|
winpr_Data_Write_INT64_BE(_s->pointer, _v);
|
|
_s->pointer += 8;
|
|
}
|
|
|
|
static inline void Stream_Write(wStream* _s, const void* _b, size_t _n)
|
|
{
|
|
if (_n > 0)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_b);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= _n);
|
|
memcpy(_s->pointer, (_b), (_n));
|
|
Stream_Seek(_s, _n);
|
|
}
|
|
}
|
|
|
|
static inline void Stream_Seek_UINT8(wStream* _s)
|
|
{
|
|
Stream_Seek(_s, sizeof(UINT8));
|
|
}
|
|
static inline void Stream_Seek_UINT16(wStream* _s)
|
|
{
|
|
Stream_Seek(_s, sizeof(UINT16));
|
|
}
|
|
static inline void Stream_Seek_UINT32(wStream* _s)
|
|
{
|
|
Stream_Seek(_s, sizeof(UINT32));
|
|
}
|
|
static inline void Stream_Seek_UINT64(wStream* _s)
|
|
{
|
|
Stream_Seek(_s, sizeof(UINT64));
|
|
}
|
|
|
|
static inline void Stream_Rewind_UINT8(wStream* _s)
|
|
{
|
|
Stream_Rewind(_s, sizeof(UINT8));
|
|
}
|
|
static inline void Stream_Rewind_UINT16(wStream* _s)
|
|
{
|
|
Stream_Rewind(_s, sizeof(UINT16));
|
|
}
|
|
static inline void Stream_Rewind_UINT32(wStream* _s)
|
|
{
|
|
Stream_Rewind(_s, sizeof(UINT32));
|
|
}
|
|
static inline void Stream_Rewind_UINT64(wStream* _s)
|
|
{
|
|
Stream_Rewind(_s, sizeof(UINT64));
|
|
}
|
|
|
|
static inline void Stream_Fill(wStream* _s, int _v, size_t _n)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_s) >= (_n));
|
|
memset(_s->pointer, _v, (_n));
|
|
Stream_Seek(_s, _n);
|
|
}
|
|
|
|
static inline void Stream_Zero(wStream* _s, size_t _n)
|
|
{
|
|
Stream_Fill(_s, '\0', _n);
|
|
}
|
|
|
|
static inline void Stream_Copy(wStream* _src, wStream* _dst, size_t _n)
|
|
{
|
|
WINPR_ASSERT(_src);
|
|
WINPR_ASSERT(_dst);
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_src) >= (_n));
|
|
WINPR_ASSERT(Stream_GetRemainingCapacity(_dst) >= (_n));
|
|
|
|
memcpy(_dst->pointer, _src->pointer, _n);
|
|
Stream_Seek(_dst, _n);
|
|
Stream_Seek(_src, _n);
|
|
}
|
|
|
|
/** @brief Convenience macro to get a pointer to the stream buffer casted to a specific type
|
|
*
|
|
* @since version 3.9.0
|
|
*/
|
|
#define Stream_BufferAs(s, type) WINPR_STREAM_CAST(type*, Stream_Buffer(s))
|
|
|
|
static inline BYTE* Stream_Buffer(wStream* _s)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
return _s->buffer;
|
|
}
|
|
|
|
/** @brief Convenience macro to get a const pointer to the stream buffer casted to a specific type
|
|
*
|
|
* @since version 3.9.0
|
|
*/
|
|
#define Stream_ConstBufferAs(s, type) WINPR_STREAM_CAST(type*, Stream_ConstBuffer(s))
|
|
static inline const BYTE* Stream_ConstBuffer(const wStream* _s)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
return _s->buffer;
|
|
}
|
|
|
|
#define Stream_GetBuffer(_s, _b) _b = Stream_Buffer(_s)
|
|
|
|
/** @brief Convenience macro to get a pointer to the stream buffer casted to a specific type
|
|
*
|
|
* @since version 3.9.0
|
|
*/
|
|
#define Stream_GetBufferAs(_s, _b) _b = Stream_BufferAs(_s, __typeof(_b))
|
|
|
|
#define Stream_PointerAs(s, type) WINPR_STREAM_CAST(type*, Stream_Pointer(s))
|
|
|
|
static inline void* Stream_Pointer(wStream* _s)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
return _s->pointer;
|
|
}
|
|
|
|
static inline const void* Stream_ConstPointer(const wStream* _s)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
return _s->pointer;
|
|
}
|
|
|
|
#define Stream_GetPointer(_s, _p) _p = Stream_Pointer(_s)
|
|
|
|
/** @brief Convenience macro to get a pointer to the stream pointer casted to a specific type
|
|
*
|
|
* @since version 3.9.0
|
|
*/
|
|
#define Stream_GetPointerAs(_s, _p) _p = Stream_PointerAs(_s, __typeof(_p))
|
|
|
|
#if defined(WITH_WINPR_DEPRECATED)
|
|
WINPR_DEPRECATED_VAR("Use Stream_SetPosition instead",
|
|
WINPR_API BOOL Stream_SetPointer(wStream* _s, BYTE* _p));
|
|
WINPR_DEPRECATED_VAR("Use Stream_New(buffer, capacity) instead",
|
|
WINPR_API BOOL Stream_SetBuffer(wStream* _s, BYTE* _b));
|
|
WINPR_DEPRECATED_VAR("Use Stream_New(buffer, capacity) instead",
|
|
WINPR_API void Stream_SetCapacity(wStream* _s, size_t capacity));
|
|
#endif
|
|
|
|
static inline size_t Stream_Length(const wStream* _s)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
return _s->length;
|
|
}
|
|
|
|
#define Stream_GetLength(_s, _l) _l = Stream_Length(_s)
|
|
WINPR_API BOOL Stream_SetLength(wStream* _s, size_t _l);
|
|
|
|
static inline size_t Stream_Capacity(const wStream* _s)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
return _s->capacity;
|
|
}
|
|
|
|
#define Stream_GetCapacity(_s, _c) _c = Stream_Capacity(_s);
|
|
|
|
static inline size_t Stream_GetPosition(const wStream* _s)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
WINPR_ASSERT(_s->buffer <= _s->pointer);
|
|
return WINPR_STREAM_CAST(size_t, (_s->pointer - _s->buffer));
|
|
}
|
|
|
|
/** @brief helper to reset stream read/write position to beginning of stream.
|
|
*
|
|
* Same as \ref Stream_SetPosition(s, 0) but does not need bounds checks.
|
|
*
|
|
* @param _s A stream to reset the position on. Must not be \b nullptr
|
|
*
|
|
* @since version 3.24.0
|
|
*/
|
|
static inline void Stream_ResetPosition(wStream* _s)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
_s->pointer = _s->buffer;
|
|
}
|
|
|
|
WINPR_API BOOL Stream_SetPosition(wStream* _s, size_t _p);
|
|
|
|
WINPR_API void Stream_SealLength(wStream* _s);
|
|
|
|
static inline void Stream_Clear(wStream* _s)
|
|
{
|
|
WINPR_ASSERT(_s);
|
|
memset(_s->buffer, 0, _s->capacity);
|
|
}
|
|
|
|
#define Stream_SafeSeek(s, size) Stream_SafeSeekEx(s, size, __FILE__, __LINE__, __func__)
|
|
WINPR_API BOOL Stream_SafeSeekEx(wStream* s, size_t size, const char* file, size_t line,
|
|
const char* fkt);
|
|
|
|
WINPR_API BOOL Stream_Read_UTF16_String(wStream* s, WCHAR* dst, size_t charLength);
|
|
WINPR_API BOOL Stream_Write_UTF16_String(wStream* s, const WCHAR* src, size_t charLength);
|
|
|
|
/** \brief Reads a WCHAR string from a stream and converts it to UTF-8 and returns a newly
|
|
* allocated string
|
|
*
|
|
* \param s The stream to read data from
|
|
* \param wcharLength The number of WCHAR characters to read (NOT the size in bytes!)
|
|
* \param pUtfCharLength Ignored if \b nullptr, otherwise will be set to the number of
|
|
* characters in the resulting UTF-8 string
|
|
* \return A '\0' terminated UTF-8 encoded string or nullptr for any failure.
|
|
*/
|
|
WINPR_API char* Stream_Read_UTF16_String_As_UTF8(wStream* s, size_t wcharLength,
|
|
size_t* pUtfCharLength);
|
|
|
|
/** \brief Reads a WCHAR string from a stream and converts it to UTF-8 and
|
|
* writes it to the supplied buffer
|
|
*
|
|
* \param s The stream to read data from
|
|
* \param wcharLength The number of WCHAR characters to read (NOT the size in bytes!)
|
|
* \param utfBuffer A pointer to a buffer holding the result string
|
|
* \param utfBufferCharLength The size of the result buffer
|
|
* \return The char length (strlen) of the result string or -1 for failure
|
|
*/
|
|
WINPR_API SSIZE_T Stream_Read_UTF16_String_As_UTF8_Buffer(wStream* s, size_t wcharLength,
|
|
char* utfBuffer,
|
|
size_t utfBufferCharLength);
|
|
|
|
/** \brief Writes a UTF-8 string UTF16 encoded to the stream. If the UTF-8
|
|
* string is short, the remaining characters are filled up with '\0'
|
|
*
|
|
* \param s The stream to write to
|
|
* \param wcharLength the length (in WCHAR characters) to write
|
|
* \param src The source data buffer with the UTF-8 data
|
|
* \param length The length in bytes of the UTF-8 buffer
|
|
* \param fill If \b TRUE fill the unused parts of the wcharLength with 0
|
|
*
|
|
* \b return number of used characters for success, /b -1 for failure
|
|
*/
|
|
WINPR_API SSIZE_T Stream_Write_UTF16_String_From_UTF8(wStream* s, size_t wcharLength,
|
|
const char* src, size_t length,
|
|
BOOL fill);
|
|
|
|
/* StreamPool */
|
|
|
|
WINPR_API void StreamPool_Return(wStreamPool* pool, wStream* s);
|
|
|
|
/** @brief increment reference count of stream
|
|
*
|
|
* @param s The stream to reference
|
|
* @bug versions < 3.13.0 did only handle streams returned by StreamPool_Take
|
|
*/
|
|
WINPR_API void Stream_AddRef(wStream* s);
|
|
|
|
/** @brief Release a reference to a stream.
|
|
* If the reference count reaches \b 0 it is returned to the StreamPool it was taken from or \b
|
|
* Stream_Free is called.
|
|
*
|
|
* @param s The stream to release
|
|
* @bug versions < 3.13.0 did only handle streams returned by StreamPool_Take
|
|
*/
|
|
WINPR_API void Stream_Release(wStream* s);
|
|
|
|
WINPR_ATTR_MALLOC(Stream_Release, 1)
|
|
WINPR_ATTR_NODISCARD
|
|
WINPR_API wStream* StreamPool_Take(wStreamPool* pool, size_t size);
|
|
|
|
WINPR_API wStream* StreamPool_Find(wStreamPool* pool, const BYTE* ptr);
|
|
|
|
/** Return the number of streams still not returned to the pool
|
|
*
|
|
* @param pool The pool to query, must not be \b nullptr
|
|
*
|
|
* @return the number of streams still in use
|
|
*
|
|
* @since version 3.10.0
|
|
*/
|
|
WINPR_API size_t StreamPool_UsedCount(wStreamPool* pool);
|
|
|
|
/** Wait up to \b timeoutMS milliseconds for streams to be returned to the pool.
|
|
* Use \b INFINITE for an infinite timeout
|
|
*
|
|
* @param pool The pool to query, must not be \b nullptr
|
|
* @param timeoutMS Milliseconds to wait at most, use \b INFINITE for no timeout.
|
|
*
|
|
* @return \b TRUE in case all streams were returned, \b FALSE otherwise.
|
|
*
|
|
* @since version 3.10.0
|
|
*/
|
|
WINPR_API BOOL StreamPool_WaitForReturn(wStreamPool* pool, UINT32 timeoutMS);
|
|
|
|
WINPR_API void StreamPool_Clear(wStreamPool* pool);
|
|
|
|
WINPR_API void StreamPool_Free(wStreamPool* pool);
|
|
|
|
WINPR_ATTR_MALLOC(StreamPool_Free, 1)
|
|
WINPR_ATTR_NODISCARD
|
|
WINPR_API wStreamPool* StreamPool_New(BOOL synchronized, size_t defaultSize);
|
|
|
|
WINPR_API char* StreamPool_GetStatistics(wStreamPool* pool, char* buffer, size_t size);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif /* WINPR_UTILS_STREAM_H */
|