-
-
Notifications
You must be signed in to change notification settings - Fork 92
/
circular-buffer.js
140 lines (108 loc) · 3.05 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
132
133
134
135
136
137
138
139
140
/**
* 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;
if (index >= this.capacity)
index -= this.capacity;
this.items[index] = item;
// Overwriting?
if (this.size === this.capacity) {
index++;
// Wrapping around?
if (index >= this.capacity) {
this.start = 0;
}
else {
this.start = index;
}
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;