-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathindex.js
151 lines (133 loc) · 3.17 KB
/
index.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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/**
* Expose `RingBuffer`.
*/
module.exports = RingBuffer;
/**
* Initializes a new empty `RingBuffer` with the given `capacity`, when no
* value is provided uses the default capacity (50).
*
* If provided, `evictedCb` gets run with any evicted elements.
*
* @param {Number}
* @param {Function}
* @return {RingBuffer}
* @api public
*/
function RingBuffer(capacity, evictedCb) {
this._elements = new Array(capacity || 50);
this._first = 0;
this._last = 0;
this._size = 0;
this._evictedCb = evictedCb;
}
/**
* Returns the capacity of the ring buffer.
*
* @return {Number}
* @api public
*/
RingBuffer.prototype.capacity = function() {
return this._elements.length;
};
/**
* Returns whether the ring buffer is empty or not.
*
* @return {Boolean}
* @api public
*/
RingBuffer.prototype.isEmpty = function() {
return this.size() === 0;
};
/**
* Returns whether the ring buffer is full or not.
*
* @return {Boolean}
* @api public
*/
RingBuffer.prototype.isFull = function() {
return this.size() === this.capacity();
};
/**
* Peeks at the top element of the queue.
*
* @return {Object}
* @throws {Error} when the ring buffer is empty.
* @api public
*/
RingBuffer.prototype.peek = function() {
if (this.isEmpty()) throw new Error('RingBuffer is empty');
return this._elements[this._first];
};
/**
* Peeks at multiple elements in the queue.
*
* @return {Array}
* @throws {Error} when there are not enough elements in the buffer.
* @api public
*/
RingBuffer.prototype.peekN = function(count) {
if (count > this._size) throw new Error('Not enough elements in RingBuffer');
var end = Math.min(this._first + count, this.capacity());
var firstHalf = this._elements.slice(this._first, end);
if (end < this.capacity()) {
return firstHalf;
}
var secondHalf = this._elements.slice(0, count - firstHalf.length);
return firstHalf.concat(secondHalf);
};
/**
* Dequeues the top element of the queue.
*
* @return {Object}
* @throws {Error} when the ring buffer is empty.
* @api public
*/
RingBuffer.prototype.deq = function() {
var element = this.peek();
this._size--;
this._first = (this._first + 1) % this.capacity();
return element;
};
/**
* Dequeues multiple elements of the queue.
*
* @return {Array}
* @throws {Error} when there are not enough elements in the buffer.
* @api public
*/
RingBuffer.prototype.deqN = function(count) {
var elements = this.peekN(count);
this._size -= count;
this._first = (this._first + count) % this.capacity();
return elements;
};
/**
* Enqueues the `element` at the end of the ring buffer and returns its new size.
*
* @param {Object} element
* @return {Number}
* @api public
*/
RingBuffer.prototype.enq = function(element) {
this._end = (this._first + this.size()) % this.capacity();
var full = this.isFull()
if (full && this._evictedCb) {
this._evictedCb(this._elements[this._end]);
}
this._elements[this._end] = element;
if (full) {
this._first = (this._first + 1) % this.capacity();
} else {
this._size++;
}
return this.size();
};
/**
* Returns the size of the queue.
*
* @return {Number}
* @api public
*/
RingBuffer.prototype.size = function() {
return this._size;
};