Files
MQTT-Explorer/backend/src/Model/RingBuffer.ts
T
2019-01-21 15:07:53 +01:00

71 lines
1.6 KiB
TypeScript

interface Lengthwise {
length: number
}
export class RingBuffer<T extends Lengthwise> {
private capacity: number
private maxItems: number
private usage: number = 0
private items: (any)[] = []
private start: number = 0
private end: number = 0
constructor(capacity: number, maxItems = Infinity, ringBuffer?: RingBuffer<T>) {
this.capacity = capacity
this.maxItems = maxItems
if (ringBuffer) {
this.items = ringBuffer.toArray()
this.end = this.items.length
this.usage = this.items.length
}
}
public clone(): RingBuffer<T> {
return new RingBuffer(this.capacity, this.maxItems, this)
}
public toArray() {
return this.items.slice(this.start, this.end)
}
public add(item: T) {
const size = item.length
this.enforceCapacityConstraints(size)
this.usage += size
this.items[this.end] = item
this.end += 1
}
private enforceCapacityConstraints(addedItemSize: number) {
const remainingSize = this.capacity - (this.usage + addedItemSize)
if (remainingSize < 0) {
this.freeSomeSpace(Math.abs(remainingSize))
}
while ((this.end - this.start) >= this.maxItems) {
this.dropFirst()
}
}
private freeSpace(): number {
return this.capacity - this.usage
}
private isEmpty(): boolean {
return this.usage === 0
}
private freeSomeSpace(requiredSpace: number) {
while (this.freeSpace() < requiredSpace && !this.isEmpty()) {
this.dropFirst()
}
}
private dropFirst() {
const freedSpace = this.items[this.start].length
this.usage -= freedSpace
delete this.items[this.start]
this.start += 1
}
}