-
Notifications
You must be signed in to change notification settings - Fork 0
/
ringbuffer.js
111 lines (89 loc) · 3.72 KB
/
ringbuffer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
/* ISC License
*
* Copyright (c) 2016-2020, Erayd LTD
*
* Permission to use, copy, modify, and/or distribute this software for any purpose
* with or without fee is hereby granted, provided that the above copyright notice
* and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
"use strict";
const events = require("events");
module.exports = class Ringbuffer extends events.EventEmitter {
constructor(size) {
super();
var head = 0;
var items = 0;
var buffer = new Array(size);
// basic properties
Object.defineProperties(this, {
// get the size of the buffer
size: { value: size, writable: false, enumerable: true },
// get the current number of items in the buffer
length: { get: () => items, enumerable: true },
// get the current number of free slots in the buffer
free: { get: () => size - items, enumerable: true },
// methods
push: { value: push, writable: false },
unshift: { value: unshift, writable: false },
pop: { value: pop, writable: false },
shift: { value: shift, writable: false },
peek: { value: peek, writable: false },
peekStart: { value: peekStart, writable: false }
});
// push item onto the end of the buffer
function push(value) {
if (items === size) throw new Error("Buffer is full");
var pos = (head + items++) % size;
buffer[pos] = value;
if (items === 1) this.emit("data", this);
if (items === size) this.emit("full", this);
}
// push item onto the start of the buffer
function unshift(value) {
if (items === size) throw new Error("Buffer is full");
var pos = head ? --head : (head = size - 1);
buffer[pos] = value;
items++;
if (items === 1) this.emit("data", this);
if (items === size) this.emit("full", this);
}
// pop an item off the end of the buffer
function pop() {
if (!items) throw new Error("No items in buffer");
var pos = (head + --items) % size;
var value = buffer[pos];
buffer[pos] = undefined;
if (!items) this.emit("empty", this);
if (items < size) this.emit("free", this);
return value;
}
// pop an item off the start of the buffer
function shift() {
if (!items) throw new Error("No items in buffer");
var value = buffer[head];
buffer[head] = undefined;
if (++head == size) head = 0;
items--;
if (!items) this.emit("empty", this);
if (items < size) this.emit("free", this);
return value;
}
// peek at the end of the buffer
function peek() {
if (!items) throw new Error("No items in buffer");
return buffer[(head + (items - 1)) % size];
}
// peek at the start of the buffer
function peekStart() {
if (!items) throw new Error("No items in buffer");
return buffer[head];
}
}
};