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*)rb);
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*)rb, targetSize);
84 if (ringbuffer->writePtr == ringbuffer->readPtr)
89 newData = (BYTE*)realloc(ringbuffer->buffer, targetSize);
94 ringbuffer->readPtr = ringbuffer->writePtr = 0;
95 ringbuffer->buffer = newData;
97 else if ((ringbuffer->writePtr >= ringbuffer->readPtr) && (ringbuffer->writePtr < targetSize))
107 newData = (BYTE*)realloc(ringbuffer->buffer, targetSize);
112 ringbuffer->buffer = newData;
119 newData = (BYTE*)malloc(targetSize);
124 if (ringbuffer->readPtr < ringbuffer->writePtr)
131 memcpy(newData, ringbuffer->buffer + ringbuffer->readPtr, ringbuffer_used(ringbuffer));
141 memcpy(dst, ringbuffer->buffer + ringbuffer->readPtr,
142 ringbuffer->size - ringbuffer->readPtr);
143 dst += (ringbuffer->size - ringbuffer->readPtr);
145 if (ringbuffer->writePtr)
146 memcpy(dst, ringbuffer->buffer, ringbuffer->writePtr);
149 ringbuffer->writePtr = ringbuffer->size - ringbuffer->freeSize;
150 ringbuffer->readPtr = 0;
151 free(ringbuffer->buffer);
152 ringbuffer->buffer = newData;
155 ringbuffer->freeSize += (targetSize - ringbuffer->size);
156 ringbuffer->size = targetSize;
169BOOL ringbuffer_write(
RingBuffer* ringbuffer,
const BYTE* ptr,
size_t sz)
172 size_t remaining = 0;
174 WINPR_ASSERT(ringbuffer);
175 DEBUG_RINGBUFFER(
"ringbuffer_write(%p): sz: %" PRIdz
"", (
void*)rb, sz);
177 if ((ringbuffer->freeSize <= sz) && !ringbuffer_realloc(ringbuffer, ringbuffer->size + sz))
189 if (ringbuffer->size - ringbuffer->writePtr < sz)
190 toWrite = ringbuffer->size - ringbuffer->writePtr;
194 memcpy(ringbuffer->buffer + ringbuffer->writePtr, ptr, toWrite);
195 remaining -= toWrite;
200 memcpy(ringbuffer->buffer, ptr, remaining);
202 ringbuffer->writePtr = (ringbuffer->writePtr + sz) % ringbuffer->size;
203 ringbuffer->freeSize -= sz;
207BYTE* ringbuffer_ensure_linear_write(
RingBuffer* ringbuffer,
size_t sz)
209 DEBUG_RINGBUFFER(
"ringbuffer_ensure_linear_write(%p): sz: %" PRIdz
"", (
void*)rb, sz);
211 WINPR_ASSERT(ringbuffer);
212 if (ringbuffer->freeSize < sz)
214 if (!ringbuffer_realloc(ringbuffer, ringbuffer->size + sz - ringbuffer->freeSize + 32))
218 if (ringbuffer->writePtr == ringbuffer->readPtr)
220 ringbuffer->writePtr = ringbuffer->readPtr = 0;
223 if (ringbuffer->writePtr + sz < ringbuffer->size)
224 return ringbuffer->buffer + ringbuffer->writePtr;
233 memmove(ringbuffer->buffer, ringbuffer->buffer + ringbuffer->readPtr,
234 ringbuffer->writePtr - ringbuffer->readPtr);
235 ringbuffer->readPtr = 0;
236 ringbuffer->writePtr = ringbuffer->size - ringbuffer->freeSize;
237 return ringbuffer->buffer + ringbuffer->writePtr;
240BOOL ringbuffer_commit_written_bytes(
RingBuffer* ringbuffer,
size_t sz)
242 DEBUG_RINGBUFFER(
"ringbuffer_commit_written_bytes(%p): sz: %" PRIdz
"", (
void*)rb, sz);
244 WINPR_ASSERT(ringbuffer);
248 if (ringbuffer->writePtr + sz > ringbuffer->size)
251 ringbuffer->writePtr = (ringbuffer->writePtr + sz) % ringbuffer->size;
252 ringbuffer->freeSize -= sz;
258 size_t remaining = sz;
262 DEBUG_RINGBUFFER(
"ringbuffer_peek(%p): sz: %" PRIdz
"", (
const void*)rb, sz);
264 WINPR_ASSERT(ringbuffer);
268 if ((ringbuffer->size - ringbuffer->freeSize) < sz)
269 remaining = ringbuffer->size - ringbuffer->freeSize;
273 if ((ringbuffer->readPtr + remaining) > ringbuffer->size)
274 toRead = ringbuffer->size - ringbuffer->readPtr;
278 chunks[0].data = ringbuffer->buffer + ringbuffer->readPtr;
279 chunks[0].size = toRead;
287 chunks[chunkIndex].data = ringbuffer->buffer;
288 chunks[chunkIndex].size = remaining;
295void ringbuffer_commit_read_bytes(
RingBuffer* ringbuffer,
size_t sz)
297 DEBUG_RINGBUFFER(
"ringbuffer_commit_read_bytes(%p): sz: %" PRIdz
"", (
void*)ringbuffer, sz);
299 WINPR_ASSERT(ringbuffer);
303 WINPR_ASSERT(ringbuffer->size - ringbuffer->freeSize >= sz);
304 ringbuffer->readPtr = (ringbuffer->readPtr + sz) % ringbuffer->size;
305 ringbuffer->freeSize += sz;
308 if ((ringbuffer->size != ringbuffer->initialSize) &&
309 (ringbuffer_used(ringbuffer) < ringbuffer->initialSize / 2))
310 ringbuffer_realloc(ringbuffer, ringbuffer->initialSize);
a piece of data in the ring buffer, exactly like a glibc iovec