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)
45 rb->buffer = malloc(initialSize);
50 rb->readPtr = rb->writePtr = 0;
51 rb->initialSize = rb->size = rb->freeSize = initialSize;
52 DEBUG_RINGBUFFER(
"ringbuffer_init(%p)", (
void*)rb);
59 return rb->size - rb->freeSize;
62 size_t ringbuffer_capacity(
const RingBuffer* rb)
70 DEBUG_RINGBUFFER(
"ringbuffer_destroy(%p)", (
void*)rb);
78 static BOOL ringbuffer_realloc(
RingBuffer* rb,
size_t targetSize)
82 DEBUG_RINGBUFFER(
"ringbuffer_realloc(%p): targetSize: %" PRIdz
"", (
void*)rb, targetSize);
84 if (rb->writePtr == rb->readPtr)
89 newData = (BYTE*)realloc(rb->buffer, targetSize);
94 rb->readPtr = rb->writePtr = 0;
97 else if ((rb->writePtr >= rb->readPtr) && (rb->writePtr < targetSize))
107 newData = (BYTE*)realloc(rb->buffer, targetSize);
112 rb->buffer = newData;
119 newData = (BYTE*)malloc(targetSize);
124 if (rb->readPtr < rb->writePtr)
131 memcpy(newData, rb->buffer + rb->readPtr, ringbuffer_used(rb));
141 memcpy(dst, rb->buffer + rb->readPtr, rb->size - rb->readPtr);
142 dst += (rb->size - rb->readPtr);
145 memcpy(dst, rb->buffer, rb->writePtr);
148 rb->writePtr = rb->size - rb->freeSize;
151 rb->buffer = newData;
154 rb->freeSize += (targetSize - rb->size);
155 rb->size = targetSize;
168 BOOL ringbuffer_write(
RingBuffer* rb,
const BYTE* ptr,
size_t sz)
171 size_t remaining = 0;
174 DEBUG_RINGBUFFER(
"ringbuffer_write(%p): sz: %" PRIdz
"", (
void*)rb, sz);
176 if ((rb->freeSize <= sz) && !ringbuffer_realloc(rb, rb->size + sz))
188 if (rb->size - rb->writePtr < sz)
189 toWrite = rb->size - rb->writePtr;
193 memcpy(rb->buffer + rb->writePtr, ptr, toWrite);
194 remaining -= toWrite;
199 memcpy(rb->buffer, ptr, remaining);
201 rb->writePtr = (rb->writePtr + sz) % rb->size;
206 BYTE* ringbuffer_ensure_linear_write(
RingBuffer* rb,
size_t sz)
208 DEBUG_RINGBUFFER(
"ringbuffer_ensure_linear_write(%p): sz: %" PRIdz
"", (
void*)rb, sz);
211 if (rb->freeSize < sz)
213 if (!ringbuffer_realloc(rb, rb->size + sz - rb->freeSize + 32))
217 if (rb->writePtr == rb->readPtr)
219 rb->writePtr = rb->readPtr = 0;
222 if (rb->writePtr + sz < rb->size)
223 return rb->buffer + rb->writePtr;
232 memmove(rb->buffer, rb->buffer + rb->readPtr, rb->writePtr - rb->readPtr);
234 rb->writePtr = rb->size - rb->freeSize;
235 return rb->buffer + rb->writePtr;
238 BOOL ringbuffer_commit_written_bytes(
RingBuffer* rb,
size_t sz)
240 DEBUG_RINGBUFFER(
"ringbuffer_commit_written_bytes(%p): sz: %" PRIdz
"", (
void*)rb, sz);
246 if (rb->writePtr + sz > rb->size)
249 rb->writePtr = (rb->writePtr + sz) % rb->size;
256 size_t remaining = sz;
260 DEBUG_RINGBUFFER(
"ringbuffer_peek(%p): sz: %" PRIdz
"", (
const void*)rb, sz);
266 if ((rb->size - rb->freeSize) < sz)
267 remaining = rb->size - rb->freeSize;
271 if ((rb->readPtr + remaining) > rb->size)
272 toRead = rb->size - rb->readPtr;
276 chunks[0].data = rb->buffer + rb->readPtr;
277 chunks[0].size = toRead;
285 chunks[chunkIndex].data = rb->buffer;
286 chunks[chunkIndex].size = remaining;
293 void ringbuffer_commit_read_bytes(
RingBuffer* rb,
size_t sz)
295 DEBUG_RINGBUFFER(
"ringbuffer_commit_read_bytes(%p): sz: %" PRIdz
"", (
void*)rb, sz);
301 WINPR_ASSERT(rb->size - rb->freeSize >= sz);
302 rb->readPtr = (rb->readPtr + sz) % rb->size;
306 if ((rb->size != rb->initialSize) && (ringbuffer_used(rb) < rb->initialSize / 2))
307 ringbuffer_realloc(rb, rb->initialSize);
a piece of data in the ring buffer, exactly like a glibc iovec