20#include <freerdp/config.h>
22#include <freerdp/utils/ringbuffer.h>
26#include <winpr/assert.h>
29#include <freerdp/log.h>
31#ifdef WITH_DEBUG_RINGBUFFER
32#define TAG FREERDP_TAG("utils.ringbuffer")
34#define DEBUG_RINGBUFFER(...) WLog_DBG(TAG, __VA_ARGS__)
36#define DEBUG_RINGBUFFER(...) \
42BOOL ringbuffer_init(
RingBuffer* ringbuffer,
size_t initialSize)
44 WINPR_ASSERT(ringbuffer);
45 ringbuffer->buffer = malloc(initialSize);
47 if (!ringbuffer->buffer)
50 ringbuffer->readPtr = ringbuffer->writePtr = 0;
51 ringbuffer->initialSize = ringbuffer->size = ringbuffer->freeSize = initialSize;
52 DEBUG_RINGBUFFER(
"ringbuffer_init(%p)", (
void*)ringbuffer);
56size_t ringbuffer_used(
const RingBuffer* ringbuffer)
58 WINPR_ASSERT(ringbuffer);
59 return ringbuffer->size - ringbuffer->freeSize;
62size_t ringbuffer_capacity(
const RingBuffer* ringbuffer)
64 WINPR_ASSERT(ringbuffer);
65 return ringbuffer->size;
70 DEBUG_RINGBUFFER(
"ringbuffer_destroy(%p)", (
void*)ringbuffer);
74 free(ringbuffer->buffer);
75 ringbuffer->buffer =
nullptr;
78static BOOL ringbuffer_realloc(
RingBuffer* ringbuffer,
size_t targetSize)
80 WINPR_ASSERT(ringbuffer);
81 BYTE* newData =
nullptr;
82 DEBUG_RINGBUFFER(
"ringbuffer_realloc(%p): targetSize: %" PRIdz
"", (
void*)ringbuffer,
85 if (ringbuffer->writePtr == ringbuffer->readPtr)
90 newData = (BYTE*)realloc(ringbuffer->buffer, targetSize);
95 ringbuffer->readPtr = ringbuffer->writePtr = 0;
96 ringbuffer->buffer = newData;
98 else if ((ringbuffer->writePtr >= ringbuffer->readPtr) && (ringbuffer->writePtr < targetSize))
108 newData = (BYTE*)realloc(ringbuffer->buffer, targetSize);
113 ringbuffer->buffer = newData;
120 newData = (BYTE*)malloc(targetSize);
125 if (ringbuffer->readPtr < ringbuffer->writePtr)
132 memcpy(newData, ringbuffer->buffer + ringbuffer->readPtr, ringbuffer_used(ringbuffer));
142 memcpy(dst, ringbuffer->buffer + ringbuffer->readPtr,
143 ringbuffer->size - ringbuffer->readPtr);
144 dst += (ringbuffer->size - ringbuffer->readPtr);
146 if (ringbuffer->writePtr)
147 memcpy(dst, ringbuffer->buffer, ringbuffer->writePtr);
150 ringbuffer->writePtr = ringbuffer->size - ringbuffer->freeSize;
151 ringbuffer->readPtr = 0;
152 free(ringbuffer->buffer);
153 ringbuffer->buffer = newData;
156 ringbuffer->freeSize += (targetSize - ringbuffer->size);
157 ringbuffer->size = targetSize;
170BOOL ringbuffer_write(
RingBuffer* ringbuffer,
const BYTE* ptr,
size_t sz)
173 size_t remaining = 0;
175 WINPR_ASSERT(ringbuffer);
176 DEBUG_RINGBUFFER(
"ringbuffer_write(%p): sz: %" PRIdz
"", (
void*)ringbuffer, sz);
178 if ((ringbuffer->freeSize <= sz) && !ringbuffer_realloc(ringbuffer, ringbuffer->size + sz))
190 if (ringbuffer->size - ringbuffer->writePtr < sz)
191 toWrite = ringbuffer->size - ringbuffer->writePtr;
195 memcpy(ringbuffer->buffer + ringbuffer->writePtr, ptr, toWrite);
196 remaining -= toWrite;
201 memcpy(ringbuffer->buffer, ptr, remaining);
203 ringbuffer->writePtr = (ringbuffer->writePtr + sz) % ringbuffer->size;
204 ringbuffer->freeSize -= sz;
208BYTE* ringbuffer_ensure_linear_write(
RingBuffer* ringbuffer,
size_t sz)
210 DEBUG_RINGBUFFER(
"ringbuffer_ensure_linear_write(%p): sz: %" PRIdz
"", (
void*)ringbuffer, sz);
212 WINPR_ASSERT(ringbuffer);
213 if (ringbuffer->freeSize < sz)
215 if (!ringbuffer_realloc(ringbuffer, ringbuffer->size + sz - ringbuffer->freeSize + 32))
219 if (ringbuffer->writePtr == ringbuffer->readPtr)
221 ringbuffer->writePtr = ringbuffer->readPtr = 0;
224 if (ringbuffer->writePtr + sz < ringbuffer->size)
225 return ringbuffer->buffer + ringbuffer->writePtr;
234 memmove(ringbuffer->buffer, ringbuffer->buffer + ringbuffer->readPtr,
235 ringbuffer->writePtr - ringbuffer->readPtr);
236 ringbuffer->readPtr = 0;
237 ringbuffer->writePtr = ringbuffer->size - ringbuffer->freeSize;
238 return ringbuffer->buffer + ringbuffer->writePtr;
241BOOL ringbuffer_commit_written_bytes(
RingBuffer* ringbuffer,
size_t sz)
243 DEBUG_RINGBUFFER(
"ringbuffer_commit_written_bytes(%p): sz: %" PRIdz
"", (
void*)ringbuffer, sz);
245 WINPR_ASSERT(ringbuffer);
249 if (ringbuffer->writePtr + sz > ringbuffer->size)
252 ringbuffer->writePtr = (ringbuffer->writePtr + sz) % ringbuffer->size;
253 ringbuffer->freeSize -= sz;
259 size_t remaining = sz;
263 DEBUG_RINGBUFFER(
"ringbuffer_peek(%p): sz: %" PRIdz
"", (
const void*)ringbuffer, sz);
265 WINPR_ASSERT(ringbuffer);
269 if ((ringbuffer->size - ringbuffer->freeSize) < sz)
270 remaining = ringbuffer->size - ringbuffer->freeSize;
274 if ((ringbuffer->readPtr + remaining) > ringbuffer->size)
275 toRead = ringbuffer->size - ringbuffer->readPtr;
279 chunks[0].data = ringbuffer->buffer + ringbuffer->readPtr;
280 chunks[0].size = toRead;
288 chunks[chunkIndex].data = ringbuffer->buffer;
289 chunks[chunkIndex].size = remaining;
296void ringbuffer_commit_read_bytes(
RingBuffer* ringbuffer,
size_t sz)
298 DEBUG_RINGBUFFER(
"ringbuffer_commit_read_bytes(%p): sz: %" PRIdz
"", (
void*)ringbuffer, sz);
300 WINPR_ASSERT(ringbuffer);
304 WINPR_ASSERT(ringbuffer->size - ringbuffer->freeSize >= sz);
305 ringbuffer->readPtr = (ringbuffer->readPtr + sz) % ringbuffer->size;
306 ringbuffer->freeSize += sz;
309 if ((ringbuffer->size != ringbuffer->initialSize) &&
310 (ringbuffer_used(ringbuffer) < ringbuffer->initialSize / 2))
311 ringbuffer_realloc(ringbuffer, ringbuffer->initialSize);
a piece of data in the ring buffer, exactly like a glibc iovec