rafa
Version:
Rafa.js is a Javascript framework for building concurrent applications.
118 lines (103 loc) • 3.37 kB
JavaScript
function RingBuffer(capacity = 100, overwrite = true) {
const size = Math.max(capacity, 0) || 100;
this.buffer = new Array(size);
this.capacity = size;
this.length = 0;
this.overwrite = overwrite;
this.start = 0;
}
inherit(RingBuffer, Rafa, {
// # configure(capacity: Int, overwrite: Bool)
// Reconfigure the buffer.
// Copy items into new array, if capacity is bigger or capacity is smaller
// and greater than length.
// Throw an error if capacity is less than length.
configure(capacity, overwrite) {
let { length, buffer, start } = this;
const oldcapacity = this.capacity;
if (capacity < length)
throw new Error("Cannot shrink buffer to a capacity less than the current length");
if (capacity && length) {
const buff = new Array(capacity);
for (let i = 0; i < length; i++) {
buff[i] = buffer[start++];
if (start === oldcapacity) start = 0;
}
this.buffer = buff;
}
else this.buffer = null;
this.start = 0;
this.length = length;
this.capacity = capacity;
if (overwrite !== undefined) this.overwrite = overwrite;
return this;
},
// # end(): Int
// Return an integer representing the last element in the buffer.
end() {
const capacity = this.capacity;
let idx = this.start + this.length - 1;
if (idx >= capacity) idx -= capacity;
return idx;
},
// # head(): A
// Return the oldest value stored in the buffer or undefined of there are
// no values in the buffer.
head() {
if (this.length) return this.buffer[this.start];
},
// # pop(): A
// Remove and return the newest value stored in the buffer. Returns undefined
// if there are no values in the buffer.
pop() {
const { buffer, length } = this;
if (length) {
const idx = this.end();
const tail = buffer[idx];
buffer[idx] = null;
this.length--;
return tail;
}
},
// # push(value: A): Int
// Push a value into the buffer. If the buffer length is less than capacity
// then add the value in the next available slot. If the buffer is full and
// overwrite is true then add the value in the slot of the oldest value.
// Return `0` if the value was not stored, `1` if it was stored normally,
// and `2` if it was stored by overwriting an old value.
push(value) {
let { buffer, capacity, start, length } = this;
let result = 1;
let idx = start + length;
if (length === capacity) {
if (!this.overwrite) return 0;
result++;
start++;
if (start >= capacity) start -= capacity;
this.start = start;
}
else this.length = ++length;
if (idx >= capacity) idx -= capacity;
buffer[idx] = value;
return result;
},
// # shift(): A
// Remove and return the oldest value stored in the buffer. Returns undefined
// if there are no values in the buffer.
shift() {
let { buffer, capacity, start, length } = this;
if (length) {
const head = buffer[start];
buffer[start] = null;
if (--length) this.start = ++start === capacity ? 0 : start;
this.length = length;
return head;
}
},
// # tail(): A
// Return the newest value stored in the buffer or undefined of there are
// no values in the buffer.
tail() {
if (this.length) return this.buffer[this.end()];
}
});