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.
@@ -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 || index > prevLength || count <= 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
-