forked from Yomguithereal/mnemonist
-
Notifications
You must be signed in to change notification settings - Fork 0
/
circular-buffer.js
131 lines (100 loc) · 2.97 KB
/
circular-buffer.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
/**
* Mnemonist CircularBuffer
* =========================
*
* Circular buffer implementation fit to use as a finite deque.
*/
var iterables = require('./utils/iterables.js'),
FixedDeque = require('./fixed-deque');
/**
* CircularBuffer.
*
* @constructor
*/
function CircularBuffer(ArrayClass, capacity) {
if (arguments.length < 2)
throw new Error('mnemonist/circular-buffer: expecting an Array class and a capacity.');
if (typeof capacity !== 'number' || capacity <= 0)
throw new Error('mnemonist/circular-buffer: `capacity` should be a positive number.');
this.ArrayClass = ArrayClass;
this.capacity = capacity;
this.items = new ArrayClass(this.capacity);
this.clear();
}
/**
* Pasting most of the prototype from FixedDeque.
*/
function paste(name) {
CircularBuffer.prototype[name] = FixedDeque.prototype[name];
}
Object.keys(FixedDeque.prototype).forEach(paste);
if (typeof Symbol !== 'undefined')
Object.getOwnPropertySymbols(FixedDeque.prototype).forEach(paste);
/**
* Method used to append a value to the buffer.
*
* @param {any} item - Item to append.
* @return {number} - Returns the new size of the buffer.
*/
CircularBuffer.prototype.push = function(item) {
var index = (this.start + this.size) % this.capacity;
this.items[index] = item;
// Overwriting?
if (this.size === this.capacity) {
// If start is at the end, we wrap around the buffer
this.start = (index + 1) % this.capacity;
return this.size;
}
return ++this.size;
};
/**
* Method used to prepend a value to the buffer.
*
* @param {any} item - Item to prepend.
* @return {number} - Returns the new size of the buffer.
*/
CircularBuffer.prototype.unshift = function(item) {
var index = this.start - 1;
if (this.start === 0)
index = this.capacity - 1;
this.items[index] = item;
// Overwriting
if (this.size === this.capacity) {
this.start = index;
return this.size;
}
this.start = index;
return ++this.size;
};
/**
* Static @.from function taking an arbitrary iterable & converting it into
* a circular buffer.
*
* @param {Iterable} iterable - Target iterable.
* @param {function} ArrayClass - Array class to use.
* @param {number} capacity - Desired capacity.
* @return {FiniteStack}
*/
CircularBuffer.from = function(iterable, ArrayClass, capacity) {
if (arguments.length < 3) {
capacity = iterables.guessLength(iterable);
if (typeof capacity !== 'number')
throw new Error('mnemonist/circular-buffer.from: could not guess iterable length. Please provide desired capacity as last argument.');
}
var buffer = new CircularBuffer(ArrayClass, capacity);
if (iterables.isArrayLike(iterable)) {
var i, l;
for (i = 0, l = iterable.length; i < l; i++)
buffer.items[i] = iterable[i];
buffer.size = l;
return buffer;
}
iterables.forEach(iterable, function(value) {
buffer.push(value);
});
return buffer;
};
/**
* Exporting.
*/
module.exports = CircularBuffer;