20 #include <freerdp/config.h>
22 #include <freerdp/utils/ringbuffer.h>
26 #include <winpr/assert.h>
28 #include <winpr/crt.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(...) \
42 BOOL ringbuffer_init(
RingBuffer* rb,
size_t initialSize)
44 rb->buffer = malloc(initialSize);
49 rb->readPtr = rb->writePtr = 0;
50 rb->initialSize = rb->size = rb->freeSize = initialSize;
51 DEBUG_RINGBUFFER(
"ringbuffer_init(%p)", (
void*)rb);
57 return rb->size - rb->freeSize;
60 size_t ringbuffer_capacity(
const RingBuffer* rb)
67 DEBUG_RINGBUFFER(
"ringbuffer_destroy(%p)", (
void*)rb);
72 static BOOL ringbuffer_realloc(
RingBuffer* rb,
size_t targetSize)
75 DEBUG_RINGBUFFER(
"ringbuffer_realloc(%p): targetSize: %" PRIdz
"", (
void*)rb, targetSize);
77 if (rb->writePtr == rb->readPtr)
82 newData = (BYTE*)realloc(rb->buffer, targetSize);
87 rb->readPtr = rb->writePtr = 0;
90 else if ((rb->writePtr >= rb->readPtr) && (rb->writePtr < targetSize))
100 newData = (BYTE*)realloc(rb->buffer, targetSize);
105 rb->buffer = newData;
112 newData = (BYTE*)malloc(targetSize);
117 if (rb->readPtr < rb->writePtr)
124 memcpy(newData, rb->buffer + rb->readPtr, ringbuffer_used(rb));
134 memcpy(dst, rb->buffer + rb->readPtr, rb->size - rb->readPtr);
135 dst += (rb->size - rb->readPtr);
138 memcpy(dst, rb->buffer, rb->writePtr);
141 rb->writePtr = rb->size - rb->freeSize;
144 rb->buffer = newData;
147 rb->freeSize += (targetSize - rb->size);
148 rb->size = targetSize;
161 BOOL ringbuffer_write(
RingBuffer* rb,
const BYTE* ptr,
size_t sz)
164 size_t remaining = 0;
165 DEBUG_RINGBUFFER(
"ringbuffer_write(%p): sz: %" PRIdz
"", (
void*)rb, sz);
167 if ((rb->freeSize <= sz) && !ringbuffer_realloc(rb, rb->size + sz))
179 if (rb->size - rb->writePtr < sz)
180 toWrite = rb->size - rb->writePtr;
184 memcpy(rb->buffer + rb->writePtr, ptr, toWrite);
185 remaining -= toWrite;
190 memcpy(rb->buffer, ptr, remaining);
192 rb->writePtr = (rb->writePtr + sz) % rb->size;
197 BYTE* ringbuffer_ensure_linear_write(
RingBuffer* rb,
size_t sz)
199 DEBUG_RINGBUFFER(
"ringbuffer_ensure_linear_write(%p): sz: %" PRIdz
"", (
void*)rb, sz);
201 if (rb->freeSize < sz)
203 if (!ringbuffer_realloc(rb, rb->size + sz - rb->freeSize + 32))
207 if (rb->writePtr == rb->readPtr)
209 rb->writePtr = rb->readPtr = 0;
212 if (rb->writePtr + sz < rb->size)
213 return rb->buffer + rb->writePtr;
222 memmove(rb->buffer, rb->buffer + rb->readPtr, rb->writePtr - rb->readPtr);
224 rb->writePtr = rb->size - rb->freeSize;
225 return rb->buffer + rb->writePtr;
228 BOOL ringbuffer_commit_written_bytes(
RingBuffer* rb,
size_t sz)
230 DEBUG_RINGBUFFER(
"ringbuffer_commit_written_bytes(%p): sz: %" PRIdz
"", (
void*)rb, sz);
235 if (rb->writePtr + sz > rb->size)
238 rb->writePtr = (rb->writePtr + sz) % rb->size;
245 size_t remaining = sz;
249 DEBUG_RINGBUFFER(
"ringbuffer_peek(%p): sz: %" PRIdz
"", (
const void*)rb, sz);
254 if ((rb->size - rb->freeSize) < sz)
255 remaining = rb->size - rb->freeSize;
259 if ((rb->readPtr + remaining) > rb->size)
260 toRead = rb->size - rb->readPtr;
264 chunks[0].data = rb->buffer + rb->readPtr;
265 chunks[0].size = toRead;
273 chunks[chunkIndex].data = rb->buffer;
274 chunks[chunkIndex].size = remaining;
281 void ringbuffer_commit_read_bytes(
RingBuffer* rb,
size_t sz)
283 DEBUG_RINGBUFFER(
"ringbuffer_commit_read_bytes(%p): sz: %" PRIdz
"", (
void*)rb, sz);
288 WINPR_ASSERT(rb->size - rb->freeSize >= sz);
289 rb->readPtr = (rb->readPtr + sz) % rb->size;
293 if ((rb->size != rb->initialSize) && (ringbuffer_used(rb) < rb->initialSize / 2))
294 ringbuffer_realloc(rb, rb->initialSize);
a piece of data in the ring buffer, exactly like a glibc iovec