@x-oasis/integer-buffer-set 0.1.27 → 0.1.29
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/dist/index.d.ts +16 -5
- package/dist/integer-buffer-set.cjs.development.js +115 -39
- package/dist/integer-buffer-set.cjs.development.js.map +1 -1
- package/dist/integer-buffer-set.cjs.production.min.js +1 -1
- package/dist/integer-buffer-set.cjs.production.min.js.map +1 -1
- package/dist/integer-buffer-set.esm.js +115 -39
- package/dist/integer-buffer-set.esm.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +111 -65
package/src/index.ts
CHANGED
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
const defaultMetaExtractor = (value) => value;
|
|
17
17
|
export const defaultBufferSize = 10;
|
|
18
18
|
const thresholdNumber = Number.MAX_SAFE_INTEGER - 100000;
|
|
19
|
+
const assertThresholdNumber = (val: any) =>
|
|
20
|
+
typeof val === 'number' && val > thresholdNumber;
|
|
19
21
|
|
|
20
22
|
// !!!!! should do meta validation...meta should has an index...
|
|
21
23
|
// value: original data `index` value
|
|
@@ -98,11 +100,6 @@ class IntegerBufferSet<Meta = any> {
|
|
|
98
100
|
return this._bufferSize;
|
|
99
101
|
}
|
|
100
102
|
|
|
101
|
-
isThresholdMeta(meta) {
|
|
102
|
-
if (typeof meta === 'number' && meta > thresholdNumber) return true;
|
|
103
|
-
return false;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
103
|
setIsOnTheFlyFull(val: any) {
|
|
107
104
|
if (val != null) {
|
|
108
105
|
const data = this._onTheFlyIndices.filter((v) => v != null);
|
|
@@ -140,15 +137,23 @@ class IntegerBufferSet<Meta = any> {
|
|
|
140
137
|
}
|
|
141
138
|
|
|
142
139
|
getIndexMeta(index: number) {
|
|
143
|
-
|
|
144
|
-
|
|
140
|
+
try {
|
|
141
|
+
if (index == null || index < 0) return null;
|
|
142
|
+
return this._metaExtractor(index);
|
|
143
|
+
} catch (err) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
145
146
|
}
|
|
146
147
|
|
|
147
148
|
getMetaIndex(meta: Meta) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
149
|
+
try {
|
|
150
|
+
if (meta == null) return -1;
|
|
151
|
+
if (assertThresholdNumber(meta)) return -1;
|
|
152
|
+
if (this._indexExtractor) return this._indexExtractor(meta);
|
|
153
|
+
return this._metaToIndexMap.get(meta);
|
|
154
|
+
} catch (err) {
|
|
155
|
+
return -1;
|
|
156
|
+
}
|
|
152
157
|
}
|
|
153
158
|
|
|
154
159
|
setMetaIndex(meta: Meta, index: number) {
|
|
@@ -188,12 +193,63 @@ class IntegerBufferSet<Meta = any> {
|
|
|
188
193
|
return newPosition;
|
|
189
194
|
}
|
|
190
195
|
|
|
191
|
-
|
|
192
|
-
return
|
|
196
|
+
_peek(heap: Heap) {
|
|
197
|
+
return heap.peek();
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
_getMaxItem() {
|
|
201
|
+
return this._peek(this._largeValues);
|
|
193
202
|
}
|
|
194
203
|
|
|
204
|
+
_getMinItem() {
|
|
205
|
+
return this._peek(this._smallValues);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
_getMinValue() {
|
|
209
|
+
return this._peek(this._smallValues)?.value;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
_getMaxValue() {
|
|
213
|
+
return this._peek(this._largeValues)?.value;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// should omit thresholdNumber
|
|
195
217
|
getMaxValue() {
|
|
196
|
-
|
|
218
|
+
const stack = [];
|
|
219
|
+
let item;
|
|
220
|
+
|
|
221
|
+
while ((item = this._getMaxItem()) && assertThresholdNumber(item?.value)) {
|
|
222
|
+
stack.push(item);
|
|
223
|
+
this._largeValues.pop();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
let stackItem;
|
|
227
|
+
while ((stackItem = stack.pop())) {
|
|
228
|
+
this._largeValues.push(stackItem);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return item?.value;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
getMinValue() {
|
|
235
|
+
const stack = [];
|
|
236
|
+
let item;
|
|
237
|
+
|
|
238
|
+
while ((item = this._getMinItem()) && assertThresholdNumber(item?.value)) {
|
|
239
|
+
stack.push(item);
|
|
240
|
+
this._smallValues.pop();
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
let stackItem;
|
|
244
|
+
while ((stackItem = stack.pop())) {
|
|
245
|
+
this._smallValues.push(stackItem);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
return item?.value;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
_push(heap: Heap, item: HeapItem) {
|
|
252
|
+
heap.push(item);
|
|
197
253
|
}
|
|
198
254
|
|
|
199
255
|
getFliedPosition(newIndex: number, safeRange: SafeRange) {
|
|
@@ -268,7 +324,6 @@ class IntegerBufferSet<Meta = any> {
|
|
|
268
324
|
});
|
|
269
325
|
} else {
|
|
270
326
|
this._cleanHeaps();
|
|
271
|
-
// console.log('commeit ---')
|
|
272
327
|
position = this.commitPosition({
|
|
273
328
|
newIndex,
|
|
274
329
|
meta,
|
|
@@ -325,11 +380,10 @@ class IntegerBufferSet<Meta = any> {
|
|
|
325
380
|
|
|
326
381
|
let indexToReplace;
|
|
327
382
|
|
|
328
|
-
const minValue = this.
|
|
329
|
-
const maxValue = this.
|
|
383
|
+
const minValue = this._getMinValue();
|
|
384
|
+
const maxValue = this._getMaxValue();
|
|
330
385
|
|
|
331
|
-
|
|
332
|
-
if (maxValue > thresholdNumber) {
|
|
386
|
+
if (assertThresholdNumber(maxValue)) {
|
|
333
387
|
indexToReplace = maxValue;
|
|
334
388
|
this._largeValues.pop();
|
|
335
389
|
const replacedMeta = this._indexToMetaMap.get(indexToReplace);
|
|
@@ -390,7 +444,7 @@ class IntegerBufferSet<Meta = any> {
|
|
|
390
444
|
return position;
|
|
391
445
|
}
|
|
392
446
|
|
|
393
|
-
shuffle() {
|
|
447
|
+
shuffle(options: { retry: boolean; fallback: boolean }) {
|
|
394
448
|
const indices = new Array(this.bufferSize);
|
|
395
449
|
for (let idx = 0; idx < indices.length; idx++) {
|
|
396
450
|
const meta = this._onTheFlyIndices[idx] || this._positionToMetaList[idx];
|
|
@@ -448,33 +502,43 @@ class IntegerBufferSet<Meta = any> {
|
|
|
448
502
|
|
|
449
503
|
this._positionToMetaList = positionToMetaList;
|
|
450
504
|
|
|
451
|
-
return this.getIndices(
|
|
505
|
+
return this.getIndices({
|
|
506
|
+
...options,
|
|
507
|
+
retry: true,
|
|
508
|
+
});
|
|
452
509
|
}
|
|
453
510
|
|
|
454
511
|
// key point: `meta` should be preserved..
|
|
455
|
-
getIndices(
|
|
456
|
-
|
|
457
|
-
|
|
512
|
+
getIndices(
|
|
513
|
+
options = {
|
|
514
|
+
retry: false,
|
|
515
|
+
fallback: false,
|
|
516
|
+
}
|
|
517
|
+
) {
|
|
458
518
|
try {
|
|
519
|
+
const { retry, fallback } = options;
|
|
520
|
+
const { smallValues, largeValues } = this.initialize();
|
|
459
521
|
const indices = new Array(this._positionToMetaList.length);
|
|
460
522
|
const metaToPositionMap = new Map();
|
|
461
523
|
const indexToMetaMap = new Map();
|
|
462
524
|
const metaToIndexMap = new Map();
|
|
463
525
|
for (let idx = 0; idx < indices.length; idx++) {
|
|
464
|
-
const meta =
|
|
465
|
-
this._onTheFlyIndices[idx]
|
|
526
|
+
const meta = fallback
|
|
527
|
+
? this._onTheFlyIndices[idx]
|
|
528
|
+
: this._onTheFlyIndices[idx] || this._positionToMetaList[idx];
|
|
466
529
|
const targetIndex = this.getMetaIndex(meta);
|
|
467
|
-
// which means source data has changed. such as one
|
|
530
|
+
// which means source data has changed. such as one item has been deleted
|
|
468
531
|
if (
|
|
469
|
-
!
|
|
470
|
-
meta != this.getIndexMeta(targetIndex)
|
|
532
|
+
!assertThresholdNumber(meta) &&
|
|
533
|
+
meta != this.getIndexMeta(targetIndex) &&
|
|
534
|
+
!retry
|
|
471
535
|
) {
|
|
472
|
-
return this.shuffle();
|
|
536
|
+
return this.shuffle(options);
|
|
473
537
|
}
|
|
474
|
-
if (meta != null && !
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
538
|
+
if (meta != null && !assertThresholdNumber(meta)) {
|
|
539
|
+
const item = { position: idx, value: targetIndex };
|
|
540
|
+
this._push(smallValues, item);
|
|
541
|
+
this._push(largeValues, item);
|
|
478
542
|
metaToPositionMap.set(meta, idx);
|
|
479
543
|
indexToMetaMap.set(targetIndex, meta);
|
|
480
544
|
metaToIndexMap.set(meta, targetIndex);
|
|
@@ -496,7 +560,10 @@ class IntegerBufferSet<Meta = any> {
|
|
|
496
560
|
return indices;
|
|
497
561
|
} catch (err) {
|
|
498
562
|
console.log('err ', err);
|
|
499
|
-
return this.
|
|
563
|
+
return this.getIndices({
|
|
564
|
+
...options,
|
|
565
|
+
fallback: true,
|
|
566
|
+
});
|
|
500
567
|
} finally {
|
|
501
568
|
this.readyToStartNextLoop();
|
|
502
569
|
// clear on the fly indices after return indices.
|
|
@@ -504,10 +571,10 @@ class IntegerBufferSet<Meta = any> {
|
|
|
504
571
|
}
|
|
505
572
|
|
|
506
573
|
_pushToHeaps(position: number, value: number) {
|
|
507
|
-
const
|
|
574
|
+
const item = { position, value };
|
|
508
575
|
// We can reuse the same object in both heaps, because we don't mutate them
|
|
509
|
-
this._smallValues
|
|
510
|
-
this._largeValues
|
|
576
|
+
this._push(this._smallValues, item);
|
|
577
|
+
this._push(this._largeValues, item);
|
|
511
578
|
}
|
|
512
579
|
|
|
513
580
|
_setMetaPosition(meta: Meta, position: number) {
|
|
@@ -528,8 +595,6 @@ class IntegerBufferSet<Meta = any> {
|
|
|
528
595
|
const onTheFlyPositionMeta = this._onTheFlyIndices[position];
|
|
529
596
|
let positionToReplace = position;
|
|
530
597
|
|
|
531
|
-
// console.log('position ', newIndex, position);
|
|
532
|
-
|
|
533
598
|
if (onTheFlyPositionMeta) {
|
|
534
599
|
// such as place item 11 twice...
|
|
535
600
|
if (onTheFlyPositionMeta === meta) return position;
|
|
@@ -581,11 +646,6 @@ class IntegerBufferSet<Meta = any> {
|
|
|
581
646
|
}
|
|
582
647
|
|
|
583
648
|
_cleanHeaps() {
|
|
584
|
-
// We not usually only remove object from one heap while moving value.
|
|
585
|
-
// Here we make sure that there is no stale data on top of heaps.
|
|
586
|
-
// this._cleanHeap(this._smallValues);
|
|
587
|
-
// this._cleanHeap(this._largeValues);
|
|
588
|
-
|
|
589
649
|
for (let idx = 0; idx < this._positionToMetaList.length; idx++) {
|
|
590
650
|
if (this._positionToMetaList[idx] == null) {
|
|
591
651
|
this._recreateHeaps();
|
|
@@ -601,6 +661,8 @@ class IntegerBufferSet<Meta = any> {
|
|
|
601
661
|
this._smallValues.size(),
|
|
602
662
|
this._largeValues.size()
|
|
603
663
|
);
|
|
664
|
+
// We not usually only remove object from one heap while moving value.
|
|
665
|
+
// Here we make sure that there is no stale data on top of heaps.
|
|
604
666
|
if (maxHeapSize > 10 * minHeapSize) {
|
|
605
667
|
// There are many old values in one of heaps. We need to get rid of them
|
|
606
668
|
// to not use too avoid memory leaks
|
|
@@ -616,14 +678,13 @@ class IntegerBufferSet<Meta = any> {
|
|
|
616
678
|
) {
|
|
617
679
|
const meta = this._positionToMetaList[position];
|
|
618
680
|
let value = this.getMetaIndex(meta);
|
|
619
|
-
|
|
620
|
-
if (!meta || value === -1 || value == null) {
|
|
681
|
+
if (meta == null || value === -1 || value == null) {
|
|
621
682
|
value = Number.MAX_SAFE_INTEGER - position;
|
|
622
683
|
}
|
|
623
684
|
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
685
|
+
const item = { position, value };
|
|
686
|
+
this._push(smallValues, item);
|
|
687
|
+
this._push(largeValues, item);
|
|
627
688
|
if (value > thresholdNumber) {
|
|
628
689
|
// @ts-ignore
|
|
629
690
|
this._setMetaPosition(value, position);
|
|
@@ -631,25 +692,10 @@ class IntegerBufferSet<Meta = any> {
|
|
|
631
692
|
this._setMetaIndex(value, value);
|
|
632
693
|
}
|
|
633
694
|
}
|
|
634
|
-
|
|
635
|
-
// this._largeValues.peek().value;
|
|
636
|
-
|
|
637
695
|
this._smallValues = smallValues;
|
|
638
696
|
this._largeValues = largeValues;
|
|
639
697
|
}
|
|
640
698
|
|
|
641
|
-
// _cleanHeap(heap: Heap<HeapItem>) {
|
|
642
|
-
// while (
|
|
643
|
-
// !heap.empty() &&
|
|
644
|
-
// this._metaToPositionMap.get(
|
|
645
|
-
// this._indexToMetaMap.get(heap.peek()!.value)
|
|
646
|
-
// ) == null
|
|
647
|
-
// ) {
|
|
648
|
-
// console.log('pop ---', heap.peek()!.value);
|
|
649
|
-
// heap.pop();
|
|
650
|
-
// }
|
|
651
|
-
// }
|
|
652
|
-
|
|
653
699
|
_smallerComparator(lhs: HeapItem, rhs: HeapItem) {
|
|
654
700
|
return lhs.value < rhs.value;
|
|
655
701
|
}
|