@theia/process 1.48.1 → 1.48.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -30
- package/lib/common/process-common-module.d.ts +3 -3
- package/lib/common/process-common-module.js +22 -22
- package/lib/common/process-manager-types.d.ts +35 -35
- package/lib/common/process-manager-types.js +23 -23
- package/lib/common/shell-command-builder.d.ts +49 -49
- package/lib/common/shell-command-builder.js +169 -169
- package/lib/common/shell-command-builder.slow-spec.d.ts +9 -9
- package/lib/common/shell-command-builder.slow-spec.js +404 -404
- package/lib/common/shell-quoting.d.ts +91 -91
- package/lib/common/shell-quoting.js +145 -145
- package/lib/common/shell-quoting.spec.d.ts +1 -1
- package/lib/common/shell-quoting.spec.js +170 -170
- package/lib/node/dev-null-stream.d.ts +17 -17
- package/lib/node/dev-null-stream.js +41 -41
- package/lib/node/index.d.ts +6 -6
- package/lib/node/index.js +24 -24
- package/lib/node/multi-ring-buffer.d.ts +68 -68
- package/lib/node/multi-ring-buffer.js +299 -299
- package/lib/node/multi-ring-buffer.spec.d.ts +1 -1
- package/lib/node/multi-ring-buffer.spec.js +422 -422
- package/lib/node/process-backend-module.d.ts +3 -3
- package/lib/node/process-backend-module.js +56 -56
- package/lib/node/process-manager.d.ts +33 -33
- package/lib/node/process-manager.js +102 -102
- package/lib/node/process.d.ts +95 -95
- package/lib/node/process.js +142 -142
- package/lib/node/pseudo-pty.d.ts +22 -22
- package/lib/node/pseudo-pty.js +38 -38
- package/lib/node/raw-process.d.ts +45 -45
- package/lib/node/raw-process.js +104 -104
- package/lib/node/raw-process.spec.d.ts +1 -1
- package/lib/node/raw-process.spec.js +164 -164
- package/lib/node/task-terminal-process.d.ts +10 -10
- package/lib/node/task-terminal-process.js +42 -42
- package/lib/node/terminal-process.d.ts +60 -60
- package/lib/node/terminal-process.js +248 -248
- package/lib/node/terminal-process.spec.d.ts +1 -1
- package/lib/node/terminal-process.spec.js +103 -103
- package/lib/node/test/process-test-container.d.ts +2 -2
- package/lib/node/test/process-test-container.js +28 -28
- package/lib/node/utils.d.ts +16 -16
- package/lib/node/utils.js +77 -77
- package/package.json +4 -4
- package/src/common/process-common-module.ts +22 -22
- package/src/common/process-manager-types.ts +58 -58
- package/src/common/shell-command-builder.slow-spec.ts +486 -486
- package/src/common/shell-command-builder.ts +187 -187
- package/src/common/shell-quoting.spec.ts +176 -176
- package/src/common/shell-quoting.ts +236 -236
- package/src/common/tests/$weird(),file=name.js +1 -1
- package/src/common/tests/white space.js +1 -1
- package/src/node/dev-null-stream.ts +47 -47
- package/src/node/index.ts +22 -22
- package/src/node/multi-ring-buffer.spec.ts +486 -486
- package/src/node/multi-ring-buffer.ts +348 -348
- package/src/node/process-backend-module.ts +67 -67
- package/src/node/process-manager.ts +107 -107
- package/src/node/process.ts +207 -207
- package/src/node/pseudo-pty.ts +54 -54
- package/src/node/raw-process.spec.ts +199 -199
- package/src/node/raw-process.ts +156 -156
- package/src/node/string-argv.d.ts +21 -21
- package/src/node/task-terminal-process.ts +41 -41
- package/src/node/terminal-process.spec.ts +121 -121
- package/src/node/terminal-process.ts +290 -290
- package/src/node/test/process-fork-test.js +22 -22
- package/src/node/test/process-test-container.ts +27 -27
- package/src/node/utils.ts +79 -79
|
@@ -1,300 +1,300 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// *****************************************************************************
|
|
3
|
-
// Copyright (C) 2017 Ericsson and others.
|
|
4
|
-
//
|
|
5
|
-
// This program and the accompanying materials are made available under the
|
|
6
|
-
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
-
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
-
//
|
|
9
|
-
// This Source Code may also be made available under the following Secondary
|
|
10
|
-
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
-
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
-
// with the GNU Classpath Exception which is available at
|
|
13
|
-
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
-
//
|
|
15
|
-
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
-
// *****************************************************************************
|
|
17
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.MultiRingBuffer = exports.MultiRingBufferOptions = exports.MultiRingBufferReadableStream = void 0;
|
|
19
|
-
const tslib_1 = require("tslib");
|
|
20
|
-
const stream = require("stream");
|
|
21
|
-
const inversify_1 = require("@theia/core/shared/inversify");
|
|
22
|
-
/**
|
|
23
|
-
* The MultiRingBuffer is a ring buffer implementation that allows
|
|
24
|
-
* multiple independent readers.
|
|
25
|
-
*
|
|
26
|
-
* These readers are created using the getReader or getStream functions
|
|
27
|
-
* to create a reader that can be read using deq() or one that is a readable stream.
|
|
28
|
-
*/
|
|
29
|
-
class MultiRingBufferReadableStream extends stream.Readable {
|
|
30
|
-
constructor(ringBuffer, reader, encoding = 'utf8') {
|
|
31
|
-
super();
|
|
32
|
-
this.ringBuffer = ringBuffer;
|
|
33
|
-
this.reader = reader;
|
|
34
|
-
this.encoding = encoding;
|
|
35
|
-
this.more = false;
|
|
36
|
-
this.disposed = false;
|
|
37
|
-
this.setEncoding(encoding);
|
|
38
|
-
}
|
|
39
|
-
_read(size) {
|
|
40
|
-
this.more = true;
|
|
41
|
-
this.deq(size);
|
|
42
|
-
}
|
|
43
|
-
_destroy(err, callback) {
|
|
44
|
-
this.ringBuffer.closeStream(this);
|
|
45
|
-
this.ringBuffer.closeReader(this.reader);
|
|
46
|
-
this.disposed = true;
|
|
47
|
-
this.removeAllListeners();
|
|
48
|
-
callback(err);
|
|
49
|
-
}
|
|
50
|
-
onData() {
|
|
51
|
-
if (this.more === true) {
|
|
52
|
-
this.deq(-1);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
deq(size) {
|
|
56
|
-
if (this.disposed === true) {
|
|
57
|
-
return;
|
|
58
|
-
}
|
|
59
|
-
let buffer = undefined;
|
|
60
|
-
do {
|
|
61
|
-
buffer = this.ringBuffer.deq(this.reader, size, this.encoding);
|
|
62
|
-
if (buffer !== undefined) {
|
|
63
|
-
this.more = this.push(buffer, this.encoding);
|
|
64
|
-
}
|
|
65
|
-
} while (buffer !== undefined && this.more === true && this.disposed === false);
|
|
66
|
-
}
|
|
67
|
-
dispose() {
|
|
68
|
-
this.destroy();
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
exports.MultiRingBufferReadableStream = MultiRingBufferReadableStream;
|
|
72
|
-
exports.MultiRingBufferOptions = Symbol('MultiRingBufferOptions');
|
|
73
|
-
let MultiRingBuffer = class MultiRingBuffer {
|
|
74
|
-
constructor(options) {
|
|
75
|
-
this.options = options;
|
|
76
|
-
this.head = -1;
|
|
77
|
-
this.tail = -1;
|
|
78
|
-
this.readerId = 0;
|
|
79
|
-
this.maxSize = options.size;
|
|
80
|
-
if (options.encoding !== undefined) {
|
|
81
|
-
this.encoding = options.encoding;
|
|
82
|
-
}
|
|
83
|
-
else {
|
|
84
|
-
this.encoding = 'utf8';
|
|
85
|
-
}
|
|
86
|
-
this.buffer = Buffer.alloc(this.maxSize);
|
|
87
|
-
this.readers = new Map();
|
|
88
|
-
this.streams = new Map();
|
|
89
|
-
}
|
|
90
|
-
enq(str, encoding = 'utf8') {
|
|
91
|
-
let buffer = Buffer.from(str, encoding);
|
|
92
|
-
// Take the last elements of string if it's too big, drop the rest
|
|
93
|
-
if (buffer.length > this.maxSize) {
|
|
94
|
-
buffer = buffer.slice(buffer.length - this.maxSize);
|
|
95
|
-
}
|
|
96
|
-
if (buffer.length === 0) {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
// empty
|
|
100
|
-
if (this.head === -1 && this.tail === -1) {
|
|
101
|
-
this.head = 0;
|
|
102
|
-
this.tail = 0;
|
|
103
|
-
buffer.copy(this.buffer, this.head, 0, buffer.length);
|
|
104
|
-
this.head = buffer.length - 1;
|
|
105
|
-
this.onData(0);
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
const startHead = this.inc(this.head, 1).newPos;
|
|
109
|
-
if (this.inc(startHead, buffer.length).wrap === true) {
|
|
110
|
-
buffer.copy(this.buffer, startHead, 0, this.maxSize - startHead);
|
|
111
|
-
buffer.copy(this.buffer, 0, this.maxSize - startHead);
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
buffer.copy(this.buffer, startHead);
|
|
115
|
-
}
|
|
116
|
-
this.incTails(buffer.length);
|
|
117
|
-
this.head = this.inc(this.head, buffer.length).newPos;
|
|
118
|
-
this.onData(startHead);
|
|
119
|
-
}
|
|
120
|
-
getReader() {
|
|
121
|
-
this.readers.set(this.readerId, this.tail);
|
|
122
|
-
return this.readerId++;
|
|
123
|
-
}
|
|
124
|
-
closeReader(id) {
|
|
125
|
-
this.readers.delete(id);
|
|
126
|
-
}
|
|
127
|
-
getStream(encoding) {
|
|
128
|
-
const reader = this.getReader();
|
|
129
|
-
const readableStream = new MultiRingBufferReadableStream(this, reader, encoding);
|
|
130
|
-
this.streams.set(readableStream, reader);
|
|
131
|
-
return readableStream;
|
|
132
|
-
}
|
|
133
|
-
closeStream(readableStream) {
|
|
134
|
-
this.streams.delete(readableStream);
|
|
135
|
-
}
|
|
136
|
-
onData(start) {
|
|
137
|
-
/* Any stream that has read everything already
|
|
138
|
-
* Should go back to the last buffer in start offset */
|
|
139
|
-
for (const [id, pos] of this.readers) {
|
|
140
|
-
if (pos === -1) {
|
|
141
|
-
this.readers.set(id, start);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
/* Notify the streams there's new data. */
|
|
145
|
-
for (const [readableStream] of this.streams) {
|
|
146
|
-
readableStream.onData();
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
deq(id, size = -1, encoding = 'utf8') {
|
|
150
|
-
const pos = this.readers.get(id);
|
|
151
|
-
if (pos === undefined || pos === -1) {
|
|
152
|
-
return undefined;
|
|
153
|
-
}
|
|
154
|
-
if (size === 0) {
|
|
155
|
-
return undefined;
|
|
156
|
-
}
|
|
157
|
-
let buffer = '';
|
|
158
|
-
const maxDeqSize = this.sizeForReader(id);
|
|
159
|
-
const wrapped = this.isWrapped(pos, this.head);
|
|
160
|
-
let deqSize;
|
|
161
|
-
if (size === -1) {
|
|
162
|
-
deqSize = maxDeqSize;
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
deqSize = Math.min(size, maxDeqSize);
|
|
166
|
-
}
|
|
167
|
-
if (wrapped === false) { // no wrap
|
|
168
|
-
buffer = this.buffer.toString(encoding, pos, pos + deqSize);
|
|
169
|
-
}
|
|
170
|
-
else { // wrap
|
|
171
|
-
buffer = buffer.concat(this.buffer.toString(encoding, pos, this.maxSize), this.buffer.toString(encoding, 0, deqSize - (this.maxSize - pos)));
|
|
172
|
-
}
|
|
173
|
-
const lastIndex = this.inc(pos, deqSize - 1).newPos;
|
|
174
|
-
// everything is read
|
|
175
|
-
if (lastIndex === this.head) {
|
|
176
|
-
this.readers.set(id, -1);
|
|
177
|
-
}
|
|
178
|
-
else {
|
|
179
|
-
this.readers.set(id, this.inc(pos, deqSize).newPos);
|
|
180
|
-
}
|
|
181
|
-
return buffer;
|
|
182
|
-
}
|
|
183
|
-
sizeForReader(id) {
|
|
184
|
-
const pos = this.readers.get(id);
|
|
185
|
-
if (pos === undefined) {
|
|
186
|
-
return 0;
|
|
187
|
-
}
|
|
188
|
-
return this.sizeFrom(pos, this.head, this.isWrapped(pos, this.head));
|
|
189
|
-
}
|
|
190
|
-
size() {
|
|
191
|
-
return this.sizeFrom(this.tail, this.head, this.isWrapped(this.tail, this.head));
|
|
192
|
-
}
|
|
193
|
-
isWrapped(from, to) {
|
|
194
|
-
if (to < from) {
|
|
195
|
-
return true;
|
|
196
|
-
}
|
|
197
|
-
else {
|
|
198
|
-
return false;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
sizeFrom(from, to, wrap) {
|
|
202
|
-
if (from === -1 || to === -1) {
|
|
203
|
-
return 0;
|
|
204
|
-
}
|
|
205
|
-
else {
|
|
206
|
-
if (wrap === false) {
|
|
207
|
-
return to - from + 1;
|
|
208
|
-
}
|
|
209
|
-
else {
|
|
210
|
-
return to + 1 + this.maxSize - from;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
emptyForReader(id) {
|
|
215
|
-
const pos = this.readers.get(id);
|
|
216
|
-
if (pos === undefined || pos === -1) {
|
|
217
|
-
return true;
|
|
218
|
-
}
|
|
219
|
-
else {
|
|
220
|
-
return false;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
empty() {
|
|
224
|
-
if (this.head === -1 && this.tail === -1) {
|
|
225
|
-
return true;
|
|
226
|
-
}
|
|
227
|
-
else {
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
streamsSize() {
|
|
232
|
-
return this.streams.size;
|
|
233
|
-
}
|
|
234
|
-
readersSize() {
|
|
235
|
-
return this.readers.size;
|
|
236
|
-
}
|
|
237
|
-
/**
|
|
238
|
-
* Dispose all the attached readers/streams.
|
|
239
|
-
*/
|
|
240
|
-
dispose() {
|
|
241
|
-
for (const readableStream of this.streams.keys()) {
|
|
242
|
-
readableStream.dispose();
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
/* Position should be incremented if it goes pass end. */
|
|
246
|
-
shouldIncPos(pos, end, size) {
|
|
247
|
-
const { newPos: newHead, wrap } = this.inc(end, size);
|
|
248
|
-
/* Tail Head */
|
|
249
|
-
if (this.isWrapped(pos, end) === false) {
|
|
250
|
-
// Head needs to wrap to push the tail
|
|
251
|
-
if (wrap === true && newHead >= pos) {
|
|
252
|
-
return true;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
else { /* Head Tail */
|
|
256
|
-
// If we wrap head is pushing tail, or if it goes over pos
|
|
257
|
-
if (wrap === true || newHead >= pos) {
|
|
258
|
-
return true;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
return false;
|
|
262
|
-
}
|
|
263
|
-
incTailSize(pos, head, size) {
|
|
264
|
-
const { newPos: newHead } = this.inc(head, size);
|
|
265
|
-
/* New tail is 1 past newHead. */
|
|
266
|
-
return this.inc(newHead, 1);
|
|
267
|
-
}
|
|
268
|
-
incTail(pos, size) {
|
|
269
|
-
if (this.shouldIncPos(pos, this.head, size) === false) {
|
|
270
|
-
return { newPos: pos, wrap: false };
|
|
271
|
-
}
|
|
272
|
-
return this.incTailSize(pos, this.head, size);
|
|
273
|
-
}
|
|
274
|
-
/* Increment the main tail and all the reader positions. */
|
|
275
|
-
incTails(size) {
|
|
276
|
-
this.tail = this.incTail(this.tail, size).newPos;
|
|
277
|
-
for (const [id, pos] of this.readers) {
|
|
278
|
-
if (pos !== -1) {
|
|
279
|
-
if (this.shouldIncPos(pos, this.tail, size) === true) {
|
|
280
|
-
this.readers.set(id, this.tail);
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
inc(pos, size) {
|
|
286
|
-
if (size === 0) {
|
|
287
|
-
return { newPos: pos, wrap: false };
|
|
288
|
-
}
|
|
289
|
-
const newPos = (pos + size) % this.maxSize;
|
|
290
|
-
const wrap = newPos <= pos;
|
|
291
|
-
return { newPos, wrap };
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
MultiRingBuffer = (0, tslib_1.__decorate)([
|
|
295
|
-
(0, inversify_1.injectable)(),
|
|
296
|
-
(0, tslib_1.__param)(0, (0, inversify_1.inject)(exports.MultiRingBufferOptions)),
|
|
297
|
-
(0, tslib_1.__metadata)("design:paramtypes", [Object])
|
|
298
|
-
], MultiRingBuffer);
|
|
299
|
-
exports.MultiRingBuffer = MultiRingBuffer;
|
|
1
|
+
"use strict";
|
|
2
|
+
// *****************************************************************************
|
|
3
|
+
// Copyright (C) 2017 Ericsson and others.
|
|
4
|
+
//
|
|
5
|
+
// This program and the accompanying materials are made available under the
|
|
6
|
+
// terms of the Eclipse Public License v. 2.0 which is available at
|
|
7
|
+
// http://www.eclipse.org/legal/epl-2.0.
|
|
8
|
+
//
|
|
9
|
+
// This Source Code may also be made available under the following Secondary
|
|
10
|
+
// Licenses when the conditions for such availability set forth in the Eclipse
|
|
11
|
+
// Public License v. 2.0 are satisfied: GNU General Public License, version 2
|
|
12
|
+
// with the GNU Classpath Exception which is available at
|
|
13
|
+
// https://www.gnu.org/software/classpath/license.html.
|
|
14
|
+
//
|
|
15
|
+
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
16
|
+
// *****************************************************************************
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.MultiRingBuffer = exports.MultiRingBufferOptions = exports.MultiRingBufferReadableStream = void 0;
|
|
19
|
+
const tslib_1 = require("tslib");
|
|
20
|
+
const stream = require("stream");
|
|
21
|
+
const inversify_1 = require("@theia/core/shared/inversify");
|
|
22
|
+
/**
|
|
23
|
+
* The MultiRingBuffer is a ring buffer implementation that allows
|
|
24
|
+
* multiple independent readers.
|
|
25
|
+
*
|
|
26
|
+
* These readers are created using the getReader or getStream functions
|
|
27
|
+
* to create a reader that can be read using deq() or one that is a readable stream.
|
|
28
|
+
*/
|
|
29
|
+
class MultiRingBufferReadableStream extends stream.Readable {
|
|
30
|
+
constructor(ringBuffer, reader, encoding = 'utf8') {
|
|
31
|
+
super();
|
|
32
|
+
this.ringBuffer = ringBuffer;
|
|
33
|
+
this.reader = reader;
|
|
34
|
+
this.encoding = encoding;
|
|
35
|
+
this.more = false;
|
|
36
|
+
this.disposed = false;
|
|
37
|
+
this.setEncoding(encoding);
|
|
38
|
+
}
|
|
39
|
+
_read(size) {
|
|
40
|
+
this.more = true;
|
|
41
|
+
this.deq(size);
|
|
42
|
+
}
|
|
43
|
+
_destroy(err, callback) {
|
|
44
|
+
this.ringBuffer.closeStream(this);
|
|
45
|
+
this.ringBuffer.closeReader(this.reader);
|
|
46
|
+
this.disposed = true;
|
|
47
|
+
this.removeAllListeners();
|
|
48
|
+
callback(err);
|
|
49
|
+
}
|
|
50
|
+
onData() {
|
|
51
|
+
if (this.more === true) {
|
|
52
|
+
this.deq(-1);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
deq(size) {
|
|
56
|
+
if (this.disposed === true) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
let buffer = undefined;
|
|
60
|
+
do {
|
|
61
|
+
buffer = this.ringBuffer.deq(this.reader, size, this.encoding);
|
|
62
|
+
if (buffer !== undefined) {
|
|
63
|
+
this.more = this.push(buffer, this.encoding);
|
|
64
|
+
}
|
|
65
|
+
} while (buffer !== undefined && this.more === true && this.disposed === false);
|
|
66
|
+
}
|
|
67
|
+
dispose() {
|
|
68
|
+
this.destroy();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.MultiRingBufferReadableStream = MultiRingBufferReadableStream;
|
|
72
|
+
exports.MultiRingBufferOptions = Symbol('MultiRingBufferOptions');
|
|
73
|
+
let MultiRingBuffer = class MultiRingBuffer {
|
|
74
|
+
constructor(options) {
|
|
75
|
+
this.options = options;
|
|
76
|
+
this.head = -1;
|
|
77
|
+
this.tail = -1;
|
|
78
|
+
this.readerId = 0;
|
|
79
|
+
this.maxSize = options.size;
|
|
80
|
+
if (options.encoding !== undefined) {
|
|
81
|
+
this.encoding = options.encoding;
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
this.encoding = 'utf8';
|
|
85
|
+
}
|
|
86
|
+
this.buffer = Buffer.alloc(this.maxSize);
|
|
87
|
+
this.readers = new Map();
|
|
88
|
+
this.streams = new Map();
|
|
89
|
+
}
|
|
90
|
+
enq(str, encoding = 'utf8') {
|
|
91
|
+
let buffer = Buffer.from(str, encoding);
|
|
92
|
+
// Take the last elements of string if it's too big, drop the rest
|
|
93
|
+
if (buffer.length > this.maxSize) {
|
|
94
|
+
buffer = buffer.slice(buffer.length - this.maxSize);
|
|
95
|
+
}
|
|
96
|
+
if (buffer.length === 0) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// empty
|
|
100
|
+
if (this.head === -1 && this.tail === -1) {
|
|
101
|
+
this.head = 0;
|
|
102
|
+
this.tail = 0;
|
|
103
|
+
buffer.copy(this.buffer, this.head, 0, buffer.length);
|
|
104
|
+
this.head = buffer.length - 1;
|
|
105
|
+
this.onData(0);
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const startHead = this.inc(this.head, 1).newPos;
|
|
109
|
+
if (this.inc(startHead, buffer.length).wrap === true) {
|
|
110
|
+
buffer.copy(this.buffer, startHead, 0, this.maxSize - startHead);
|
|
111
|
+
buffer.copy(this.buffer, 0, this.maxSize - startHead);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
buffer.copy(this.buffer, startHead);
|
|
115
|
+
}
|
|
116
|
+
this.incTails(buffer.length);
|
|
117
|
+
this.head = this.inc(this.head, buffer.length).newPos;
|
|
118
|
+
this.onData(startHead);
|
|
119
|
+
}
|
|
120
|
+
getReader() {
|
|
121
|
+
this.readers.set(this.readerId, this.tail);
|
|
122
|
+
return this.readerId++;
|
|
123
|
+
}
|
|
124
|
+
closeReader(id) {
|
|
125
|
+
this.readers.delete(id);
|
|
126
|
+
}
|
|
127
|
+
getStream(encoding) {
|
|
128
|
+
const reader = this.getReader();
|
|
129
|
+
const readableStream = new MultiRingBufferReadableStream(this, reader, encoding);
|
|
130
|
+
this.streams.set(readableStream, reader);
|
|
131
|
+
return readableStream;
|
|
132
|
+
}
|
|
133
|
+
closeStream(readableStream) {
|
|
134
|
+
this.streams.delete(readableStream);
|
|
135
|
+
}
|
|
136
|
+
onData(start) {
|
|
137
|
+
/* Any stream that has read everything already
|
|
138
|
+
* Should go back to the last buffer in start offset */
|
|
139
|
+
for (const [id, pos] of this.readers) {
|
|
140
|
+
if (pos === -1) {
|
|
141
|
+
this.readers.set(id, start);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/* Notify the streams there's new data. */
|
|
145
|
+
for (const [readableStream] of this.streams) {
|
|
146
|
+
readableStream.onData();
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
deq(id, size = -1, encoding = 'utf8') {
|
|
150
|
+
const pos = this.readers.get(id);
|
|
151
|
+
if (pos === undefined || pos === -1) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
if (size === 0) {
|
|
155
|
+
return undefined;
|
|
156
|
+
}
|
|
157
|
+
let buffer = '';
|
|
158
|
+
const maxDeqSize = this.sizeForReader(id);
|
|
159
|
+
const wrapped = this.isWrapped(pos, this.head);
|
|
160
|
+
let deqSize;
|
|
161
|
+
if (size === -1) {
|
|
162
|
+
deqSize = maxDeqSize;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
deqSize = Math.min(size, maxDeqSize);
|
|
166
|
+
}
|
|
167
|
+
if (wrapped === false) { // no wrap
|
|
168
|
+
buffer = this.buffer.toString(encoding, pos, pos + deqSize);
|
|
169
|
+
}
|
|
170
|
+
else { // wrap
|
|
171
|
+
buffer = buffer.concat(this.buffer.toString(encoding, pos, this.maxSize), this.buffer.toString(encoding, 0, deqSize - (this.maxSize - pos)));
|
|
172
|
+
}
|
|
173
|
+
const lastIndex = this.inc(pos, deqSize - 1).newPos;
|
|
174
|
+
// everything is read
|
|
175
|
+
if (lastIndex === this.head) {
|
|
176
|
+
this.readers.set(id, -1);
|
|
177
|
+
}
|
|
178
|
+
else {
|
|
179
|
+
this.readers.set(id, this.inc(pos, deqSize).newPos);
|
|
180
|
+
}
|
|
181
|
+
return buffer;
|
|
182
|
+
}
|
|
183
|
+
sizeForReader(id) {
|
|
184
|
+
const pos = this.readers.get(id);
|
|
185
|
+
if (pos === undefined) {
|
|
186
|
+
return 0;
|
|
187
|
+
}
|
|
188
|
+
return this.sizeFrom(pos, this.head, this.isWrapped(pos, this.head));
|
|
189
|
+
}
|
|
190
|
+
size() {
|
|
191
|
+
return this.sizeFrom(this.tail, this.head, this.isWrapped(this.tail, this.head));
|
|
192
|
+
}
|
|
193
|
+
isWrapped(from, to) {
|
|
194
|
+
if (to < from) {
|
|
195
|
+
return true;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
return false;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
sizeFrom(from, to, wrap) {
|
|
202
|
+
if (from === -1 || to === -1) {
|
|
203
|
+
return 0;
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
if (wrap === false) {
|
|
207
|
+
return to - from + 1;
|
|
208
|
+
}
|
|
209
|
+
else {
|
|
210
|
+
return to + 1 + this.maxSize - from;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
emptyForReader(id) {
|
|
215
|
+
const pos = this.readers.get(id);
|
|
216
|
+
if (pos === undefined || pos === -1) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
else {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
empty() {
|
|
224
|
+
if (this.head === -1 && this.tail === -1) {
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
return false;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
streamsSize() {
|
|
232
|
+
return this.streams.size;
|
|
233
|
+
}
|
|
234
|
+
readersSize() {
|
|
235
|
+
return this.readers.size;
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Dispose all the attached readers/streams.
|
|
239
|
+
*/
|
|
240
|
+
dispose() {
|
|
241
|
+
for (const readableStream of this.streams.keys()) {
|
|
242
|
+
readableStream.dispose();
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
/* Position should be incremented if it goes pass end. */
|
|
246
|
+
shouldIncPos(pos, end, size) {
|
|
247
|
+
const { newPos: newHead, wrap } = this.inc(end, size);
|
|
248
|
+
/* Tail Head */
|
|
249
|
+
if (this.isWrapped(pos, end) === false) {
|
|
250
|
+
// Head needs to wrap to push the tail
|
|
251
|
+
if (wrap === true && newHead >= pos) {
|
|
252
|
+
return true;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
else { /* Head Tail */
|
|
256
|
+
// If we wrap head is pushing tail, or if it goes over pos
|
|
257
|
+
if (wrap === true || newHead >= pos) {
|
|
258
|
+
return true;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return false;
|
|
262
|
+
}
|
|
263
|
+
incTailSize(pos, head, size) {
|
|
264
|
+
const { newPos: newHead } = this.inc(head, size);
|
|
265
|
+
/* New tail is 1 past newHead. */
|
|
266
|
+
return this.inc(newHead, 1);
|
|
267
|
+
}
|
|
268
|
+
incTail(pos, size) {
|
|
269
|
+
if (this.shouldIncPos(pos, this.head, size) === false) {
|
|
270
|
+
return { newPos: pos, wrap: false };
|
|
271
|
+
}
|
|
272
|
+
return this.incTailSize(pos, this.head, size);
|
|
273
|
+
}
|
|
274
|
+
/* Increment the main tail and all the reader positions. */
|
|
275
|
+
incTails(size) {
|
|
276
|
+
this.tail = this.incTail(this.tail, size).newPos;
|
|
277
|
+
for (const [id, pos] of this.readers) {
|
|
278
|
+
if (pos !== -1) {
|
|
279
|
+
if (this.shouldIncPos(pos, this.tail, size) === true) {
|
|
280
|
+
this.readers.set(id, this.tail);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
inc(pos, size) {
|
|
286
|
+
if (size === 0) {
|
|
287
|
+
return { newPos: pos, wrap: false };
|
|
288
|
+
}
|
|
289
|
+
const newPos = (pos + size) % this.maxSize;
|
|
290
|
+
const wrap = newPos <= pos;
|
|
291
|
+
return { newPos, wrap };
|
|
292
|
+
}
|
|
293
|
+
};
|
|
294
|
+
MultiRingBuffer = (0, tslib_1.__decorate)([
|
|
295
|
+
(0, inversify_1.injectable)(),
|
|
296
|
+
(0, tslib_1.__param)(0, (0, inversify_1.inject)(exports.MultiRingBufferOptions)),
|
|
297
|
+
(0, tslib_1.__metadata)("design:paramtypes", [Object])
|
|
298
|
+
], MultiRingBuffer);
|
|
299
|
+
exports.MultiRingBuffer = MultiRingBuffer;
|
|
300
300
|
//# sourceMappingURL=multi-ring-buffer.js.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export {};
|
|
1
|
+
export {};
|
|
2
2
|
//# sourceMappingURL=multi-ring-buffer.spec.d.ts.map
|