mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
115 lines
2.2 KiB
Plaintext
115 lines
2.2 KiB
Plaintext
<*
|
|
@require Type.kindof == ARRAY : "Required an array type"
|
|
*>
|
|
module std::collections::ringbuffer <Type>;
|
|
import std::io;
|
|
|
|
alias Element = $typeof((Type){}[0]);
|
|
|
|
struct RingBuffer (Printable)
|
|
{
|
|
Type buf;
|
|
usz written;
|
|
usz head;
|
|
}
|
|
|
|
fn void RingBuffer.init(&self) @inline
|
|
{
|
|
*self = {};
|
|
}
|
|
|
|
fn void RingBuffer.push(&self, Element c)
|
|
{
|
|
if (self.written < self.buf.len)
|
|
{
|
|
self.buf[self.written] = c;
|
|
self.written++;
|
|
}
|
|
else
|
|
{
|
|
self.buf[self.head] = c;
|
|
self.head = (self.head + 1) % self.buf.len;
|
|
}
|
|
}
|
|
|
|
fn Element RingBuffer.get(&self, usz index) @operator([])
|
|
{
|
|
index %= self.buf.len;
|
|
usz avail = self.buf.len - self.head;
|
|
if (index < avail)
|
|
{
|
|
return self.buf[self.head + index];
|
|
}
|
|
return self.buf[index - avail];
|
|
}
|
|
|
|
fn Element? RingBuffer.pop(&self)
|
|
{
|
|
switch
|
|
{
|
|
case self.written == 0:
|
|
return NO_MORE_ELEMENT?;
|
|
case self.written < self.buf.len:
|
|
self.written--;
|
|
return self.buf[self.written];
|
|
default:
|
|
self.head = (self.head - 1) % self.buf.len;
|
|
return self.buf[self.head];
|
|
}
|
|
}
|
|
|
|
fn usz? RingBuffer.to_format(&self, Formatter* format) @dynamic
|
|
{
|
|
// Improve this?
|
|
return format.printf("%s", self.buf);
|
|
}
|
|
|
|
fn usz RingBuffer.read(&self, usz index, Element[] buffer)
|
|
{
|
|
index %= self.buf.len;
|
|
if (self.written < self.buf.len)
|
|
{
|
|
if (index >= self.written) return 0;
|
|
usz end = self.written - index;
|
|
usz n = min(end, buffer.len);
|
|
buffer[:n] = self.buf[index:n];
|
|
return n;
|
|
}
|
|
usz end = self.buf.len - self.head;
|
|
if (index >= end)
|
|
{
|
|
index -= end;
|
|
if (index >= self.head) return 0;
|
|
usz n = min(self.head - index, buffer.len);
|
|
buffer[:n] = self.buf[index:n];
|
|
return n;
|
|
}
|
|
if (buffer.len <= self.buf.len - index)
|
|
{
|
|
usz n = buffer.len;
|
|
buffer[:n] = self.buf[self.head + index:n];
|
|
return n;
|
|
}
|
|
usz n1 = self.buf.len - index;
|
|
buffer[:n1] = self.buf[self.head + index:n1];
|
|
buffer = buffer[n1..];
|
|
index -= n1;
|
|
usz n2 = min(self.head - index, buffer.len);
|
|
buffer[:n2] = self.buf[index:n2];
|
|
return n1 + n2;
|
|
}
|
|
|
|
fn void RingBuffer.write(&self, Element[] buffer)
|
|
{
|
|
usz i;
|
|
while (self.written < self.buf.len && i < buffer.len)
|
|
{
|
|
self.buf[self.written] = buffer[i++];
|
|
self.written++;
|
|
}
|
|
foreach (c : buffer[i..])
|
|
{
|
|
self.buf[self.head] = c;
|
|
self.head = (self.head + 1) % self.buf.len;
|
|
}
|
|
} |