fastds 0.0.1-rc.0 → 0.0.1
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/build/__bench__/index.d.ts +1 -0
- package/build/binary-search.cjs +13 -7
- package/build/binary-search.cjs.map +1 -1
- package/build/binary-search.js +13 -7
- package/build/binary-search.js.map +1 -1
- package/build/index.cjs.map +1 -1
- package/build/index.js.map +1 -1
- package/build/ring-buffer.cjs +131 -75
- package/build/ring-buffer.cjs.map +1 -1
- package/build/ring-buffer.d.ts +7 -6
- package/build/ring-buffer.js +131 -75
- package/build/ring-buffer.js.map +1 -1
- package/package.json +9 -9
- package/src/index.ts +0 -1
- package/src/ring-buffer.ts +151 -94
package/src/ring-buffer.ts
CHANGED
@@ -13,7 +13,7 @@ export class RingBuffer<T> {
|
|
13
13
|
|
14
14
|
static from<T>(values: T[]): RingBuffer<T> {
|
15
15
|
const n = values.length;
|
16
|
-
const ring = new RingBuffer<T>(n);
|
16
|
+
const ring = new RingBuffer<T>(n + 1);
|
17
17
|
for (let i = 0; i < n; i++) {
|
18
18
|
ring.#buffer[i] = values[i];
|
19
19
|
}
|
@@ -27,12 +27,11 @@ export class RingBuffer<T> {
|
|
27
27
|
readonly [Symbol.toStringTag] = 'RingBuffer';
|
28
28
|
|
29
29
|
constructor(capacity: number = DEFAULT_CAPACITY) {
|
30
|
-
const size = Math.max(1 << (32 - Math.clz32(capacity)), DEFAULT_CAPACITY);
|
30
|
+
const size = Math.max(1 << (32 - Math.clz32(capacity - 1)), DEFAULT_CAPACITY);
|
31
31
|
this.#buffer = new Array<T>(size);
|
32
32
|
this.#mask = size - 1;
|
33
33
|
}
|
34
34
|
|
35
|
-
|
36
35
|
get capacity() {
|
37
36
|
return this.#mask + 1;
|
38
37
|
}
|
@@ -57,6 +56,41 @@ export class RingBuffer<T> {
|
|
57
56
|
return (this.#tail + index) & this.#mask;
|
58
57
|
}
|
59
58
|
|
59
|
+
resize(capacity: number): boolean {
|
60
|
+
const buffer = this.#buffer;
|
61
|
+
const bufferLength = buffer.length;
|
62
|
+
if (bufferLength > capacity && bufferLength >> 1 < capacity) {
|
63
|
+
return false;
|
64
|
+
}
|
65
|
+
const size = Math.max(1 << (32 - Math.clz32(capacity - 1)), DEFAULT_CAPACITY);
|
66
|
+
const length = this.#length;
|
67
|
+
if (size < length) {
|
68
|
+
return false;
|
69
|
+
}
|
70
|
+
const head = this.#head;
|
71
|
+
const prevMask = this.#mask;
|
72
|
+
const prevTail = this.#tail;
|
73
|
+
|
74
|
+
const nextMask = size - 1;
|
75
|
+
const nextTail = (head + length) & nextMask;
|
76
|
+
|
77
|
+
const wrapIndex = size > bufferLength ? (prevTail < head ? bufferLength - head : length) : nextTail < head ? size - head : length;
|
78
|
+
|
79
|
+
for (let i = length - 1; i >= wrapIndex; i--) {
|
80
|
+
const read = (head + i) & prevMask;
|
81
|
+
const write = (head + i) & nextMask;
|
82
|
+
buffer[write] = buffer[read];
|
83
|
+
if (read !== write) {
|
84
|
+
buffer[read] = undefined;
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
this.#buffer.length = size;
|
89
|
+
this.#tail = nextTail;
|
90
|
+
this.#mask = nextMask;
|
91
|
+
return true;
|
92
|
+
}
|
93
|
+
|
60
94
|
grow(capacity: number = this.#mask + 1): void {
|
61
95
|
const buffer = this.#buffer;
|
62
96
|
const bufferLength = buffer.length;
|
@@ -68,7 +102,6 @@ export class RingBuffer<T> {
|
|
68
102
|
|
69
103
|
const oldTail = this.#tail;
|
70
104
|
if (oldTail < this.#head) {
|
71
|
-
const buffer = this.#buffer;
|
72
105
|
for (let i = 0; i < oldTail; i++) {
|
73
106
|
buffer[bufferLength + i] = buffer[i];
|
74
107
|
}
|
@@ -80,10 +113,13 @@ export class RingBuffer<T> {
|
|
80
113
|
|
81
114
|
allocate(index: number, count: number): boolean {
|
82
115
|
const prevLength = this.#length;
|
83
|
-
if (index < 0 ||
|
116
|
+
if (index < 0 || count <= 0) {
|
84
117
|
return false;
|
85
118
|
}
|
86
119
|
|
120
|
+
// Clamp index to valid range, like Array.splice()
|
121
|
+
index = Math.min(index, prevLength);
|
122
|
+
|
87
123
|
const buffer = this.#buffer;
|
88
124
|
const head = this.#head;
|
89
125
|
const tail = this.#tail;
|
@@ -321,6 +357,116 @@ export class RingBuffer<T> {
|
|
321
357
|
return true;
|
322
358
|
}
|
323
359
|
|
360
|
+
set(index: number, values: T[], insert = false) {
|
361
|
+
const length = this.#length;
|
362
|
+
if (index < 0 || index > length) {
|
363
|
+
return false;
|
364
|
+
}
|
365
|
+
const count = values.length;
|
366
|
+
if (insert) {
|
367
|
+
this.allocate(index, count);
|
368
|
+
} else {
|
369
|
+
const extra = Math.max(index + values.length - length, 0);
|
370
|
+
if (extra > 0) {
|
371
|
+
this.allocate(length, extra);
|
372
|
+
}
|
373
|
+
}
|
374
|
+
const buffer = this.#buffer;
|
375
|
+
const mask = this.#mask;
|
376
|
+
const baseWrite = this.#head + index;
|
377
|
+
for (let i = 0; i < count; i++) {
|
378
|
+
buffer[(baseWrite + i) & mask] = values[i];
|
379
|
+
}
|
380
|
+
return true;
|
381
|
+
}
|
382
|
+
|
383
|
+
setOne(index: number, value: T, insert = false) {
|
384
|
+
const length = this.#length;
|
385
|
+
if (index < 0 || index > length) {
|
386
|
+
return false;
|
387
|
+
}
|
388
|
+
if (insert) {
|
389
|
+
this.allocate(index, 1);
|
390
|
+
} else {
|
391
|
+
const extra = Math.max(index + 1 - length, 0);
|
392
|
+
if (extra > 0) {
|
393
|
+
this.allocate(length, extra);
|
394
|
+
}
|
395
|
+
}
|
396
|
+
const buffer = this.#buffer;
|
397
|
+
const mask = this.#mask;
|
398
|
+
buffer[(this.#head + index) & mask] = value;
|
399
|
+
|
400
|
+
return true;
|
401
|
+
}
|
402
|
+
|
403
|
+
slice(start: number = 0, end: number = this.#length): T[] {
|
404
|
+
const length = this.#length;
|
405
|
+
const buffer = this.#buffer;
|
406
|
+
const head = this.#head;
|
407
|
+
const tail = this.#tail;
|
408
|
+
const mask = this.#mask;
|
409
|
+
|
410
|
+
const actualStart = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
|
411
|
+
const actualEnd = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
|
412
|
+
|
413
|
+
if (head <= tail) {
|
414
|
+
return this.#buffer.slice((head + actualStart) & mask, (head + actualEnd) & mask) as T[];
|
415
|
+
}
|
416
|
+
|
417
|
+
const size = Math.max(actualEnd - actualStart, 0);
|
418
|
+
const result = new Array<T>(size);
|
419
|
+
for (let i = 0; i < size; i++) {
|
420
|
+
result[i] = buffer[(head + actualStart + i) & mask]!;
|
421
|
+
}
|
422
|
+
return result;
|
423
|
+
}
|
424
|
+
|
425
|
+
removeOne(index: number): number {
|
426
|
+
const length = this.#length;
|
427
|
+
if (index < 0 || index >= length) {
|
428
|
+
return -1;
|
429
|
+
}
|
430
|
+
const buffer = this.#buffer;
|
431
|
+
const mask = this.#mask;
|
432
|
+
const head = this.#head;
|
433
|
+
|
434
|
+
const leftMoveCount = index;
|
435
|
+
const rightMoveCount = length - index;
|
436
|
+
|
437
|
+
if (leftMoveCount < rightMoveCount) {
|
438
|
+
for (let i = index; i > 0; i--) {
|
439
|
+
buffer[(head + i) & mask] = buffer[(head + i - 1) & mask];
|
440
|
+
}
|
441
|
+
buffer[head] = undefined;
|
442
|
+
this.#head = (head + 1) & mask;
|
443
|
+
} else {
|
444
|
+
for (let i = index; i < length - 1; i++) {
|
445
|
+
buffer[(head + i) & mask] = buffer[(head + i + 1) & mask];
|
446
|
+
}
|
447
|
+
const tail = (head + length - 1) & mask;
|
448
|
+
buffer[tail] = undefined;
|
449
|
+
this.#tail = tail;
|
450
|
+
}
|
451
|
+
this.#length = length - 1;
|
452
|
+
|
453
|
+
return index;
|
454
|
+
}
|
455
|
+
|
456
|
+
removeFirst(value: T, index: number = 0): number {
|
457
|
+
const foundIndex = this.indexOf(value, index);
|
458
|
+
if (foundIndex === -1) {
|
459
|
+
return -1;
|
460
|
+
}
|
461
|
+
return this.removeOne(foundIndex);
|
462
|
+
}
|
463
|
+
|
464
|
+
remove(index: number, count: number): T[] {
|
465
|
+
const result = this.slice(index, index + count);
|
466
|
+
this.deallocate(index, count);
|
467
|
+
return result;
|
468
|
+
}
|
469
|
+
|
324
470
|
push(value: T) {
|
325
471
|
const tail = this.getTailOffset(1);
|
326
472
|
if (tail === this.#head) {
|
@@ -386,68 +532,6 @@ export class RingBuffer<T> {
|
|
386
532
|
return this.indexOf(value) !== -1;
|
387
533
|
}
|
388
534
|
|
389
|
-
insertOne(index: number, value: T): number {
|
390
|
-
this.allocate(index, 1);
|
391
|
-
this.#buffer[(this.#head + index) & this.#mask] = value;
|
392
|
-
return index;
|
393
|
-
}
|
394
|
-
|
395
|
-
insert(index: number, values: T[]): number {
|
396
|
-
const length = values.length;
|
397
|
-
const writeBase = this.#head + index;
|
398
|
-
this.allocate(index, length);
|
399
|
-
for (let i = 0; i < length; i++) {
|
400
|
-
this.#buffer[(writeBase + i) & this.#mask] = values[i];
|
401
|
-
}
|
402
|
-
|
403
|
-
return index;
|
404
|
-
}
|
405
|
-
|
406
|
-
removeOne(index: number): number {
|
407
|
-
const length = this.#length;
|
408
|
-
if (index < 0 || index >= length) {
|
409
|
-
return -1;
|
410
|
-
}
|
411
|
-
const buffer = this.#buffer;
|
412
|
-
const mask = this.#mask;
|
413
|
-
const head = this.#head;
|
414
|
-
|
415
|
-
const leftMoveCount = index;
|
416
|
-
const rightMoveCount = length - index;
|
417
|
-
|
418
|
-
if (leftMoveCount < rightMoveCount) {
|
419
|
-
for (let i = index; i > 0; i--) {
|
420
|
-
buffer[(head + i) & mask] = buffer[(head + i - 1) & mask];
|
421
|
-
}
|
422
|
-
buffer[head] = undefined;
|
423
|
-
this.#head = (head + 1) & mask;
|
424
|
-
} else {
|
425
|
-
for (let i = index; i < length - 1; i++) {
|
426
|
-
buffer[(head + i) & mask] = buffer[(head + i + 1) & mask];
|
427
|
-
}
|
428
|
-
const tail = (head + length - 1) & mask;
|
429
|
-
buffer[tail] = undefined;
|
430
|
-
this.#tail = tail;
|
431
|
-
}
|
432
|
-
this.#length = length - 1;
|
433
|
-
|
434
|
-
return index;
|
435
|
-
}
|
436
|
-
|
437
|
-
removeFirst(value: T, index: number = 0): number {
|
438
|
-
const foundIndex = this.indexOf(value, index);
|
439
|
-
if (foundIndex === -1) {
|
440
|
-
return -1;
|
441
|
-
}
|
442
|
-
return this.removeOne(foundIndex);
|
443
|
-
}
|
444
|
-
|
445
|
-
remove(index: number, count: number): T[] {
|
446
|
-
const result = this.slice(index, count);
|
447
|
-
this.deallocate(index, count);
|
448
|
-
return result;
|
449
|
-
}
|
450
|
-
|
451
535
|
clear(): this {
|
452
536
|
this.#buffer.length = 0;
|
453
537
|
this.#buffer.length = DEFAULT_CAPACITY;
|
@@ -458,31 +542,6 @@ export class RingBuffer<T> {
|
|
458
542
|
return this;
|
459
543
|
}
|
460
544
|
|
461
|
-
slice(start: number = 0, end: number = this.#length): T[] {
|
462
|
-
const length = this.#length;
|
463
|
-
const buffer = this.#buffer;
|
464
|
-
const head = this.#head;
|
465
|
-
const tail = this.#tail;
|
466
|
-
const mask = this.#mask;
|
467
|
-
|
468
|
-
const actualStart = start < 0 ? Math.max(length + start, 0) : Math.min(start, length);
|
469
|
-
const actualEnd = end < 0 ? Math.max(length + end, 0) : Math.min(end, length);
|
470
|
-
|
471
|
-
if (head <= tail) {
|
472
|
-
return this.#buffer.slice(
|
473
|
-
(head + actualStart) & mask,
|
474
|
-
(head + actualEnd) & mask,
|
475
|
-
) as T[];
|
476
|
-
}
|
477
|
-
|
478
|
-
const size = Math.max(actualEnd - actualStart, 0);
|
479
|
-
const result = new Array<T>(size);
|
480
|
-
for (let i = 0; i < size; i++) {
|
481
|
-
result[i] = buffer[(head + actualStart + i) & mask]!;
|
482
|
-
}
|
483
|
-
return result;
|
484
|
-
}
|
485
|
-
|
486
545
|
toArray(): T[] {
|
487
546
|
return this.slice();
|
488
547
|
}
|
@@ -522,5 +581,3 @@ export class RingBuffer<T> {
|
|
522
581
|
};
|
523
582
|
}
|
524
583
|
}
|
525
|
-
|
526
|
-
|