@fluidframework/merge-tree 0.51.0 → 0.52.0
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/collections.d.ts +41 -92
- package/dist/collections.d.ts.map +1 -1
- package/dist/collections.js +4 -334
- package/dist/collections.js.map +1 -1
- package/dist/index.d.ts +10 -11
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -12
- package/dist/index.js.map +1 -1
- package/dist/localReference.d.ts +2 -2
- package/dist/localReference.d.ts.map +1 -1
- package/dist/localReference.js +0 -1
- package/dist/localReference.js.map +1 -1
- package/dist/snapshotV1.d.ts +1 -1
- package/dist/snapshotV1.d.ts.map +1 -1
- package/dist/snapshotV1.js.map +1 -1
- package/dist/snapshotlegacy.d.ts +7 -28
- package/dist/snapshotlegacy.d.ts.map +1 -1
- package/dist/snapshotlegacy.js.map +1 -1
- package/lib/collections.d.ts +41 -92
- package/lib/collections.d.ts.map +1 -1
- package/lib/collections.js +5 -326
- package/lib/collections.js.map +1 -1
- package/lib/index.d.ts +10 -11
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +10 -11
- package/lib/index.js.map +1 -1
- package/lib/localReference.d.ts +2 -2
- package/lib/localReference.d.ts.map +1 -1
- package/lib/localReference.js +0 -1
- package/lib/localReference.js.map +1 -1
- package/lib/snapshotV1.d.ts +1 -1
- package/lib/snapshotV1.d.ts.map +1 -1
- package/lib/snapshotV1.js.map +1 -1
- package/lib/snapshotlegacy.d.ts +7 -28
- package/lib/snapshotlegacy.d.ts.map +1 -1
- package/lib/snapshotlegacy.js.map +1 -1
- package/package.json +9 -8
- package/src/collections.ts +109 -470
- package/src/index.ts +10 -11
- package/src/localReference.ts +3 -4
- package/src/snapshotV1.ts +1 -1
- package/src/snapshotlegacy.ts +9 -22
package/lib/collections.js
CHANGED
|
@@ -2,11 +2,6 @@
|
|
|
2
2
|
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
|
-
/* eslint-disable @typescript-eslint/consistent-type-assertions, eqeqeq, object-shorthand */
|
|
6
|
-
/* eslint-disable no-bitwise */
|
|
7
|
-
/* Remove once strictNullCheck is enabled */
|
|
8
|
-
import { Trace } from "@fluidframework/common-utils";
|
|
9
|
-
import { internedSpaces } from "./mergeTree";
|
|
10
5
|
export class Stack {
|
|
11
6
|
constructor() {
|
|
12
7
|
this.items = [];
|
|
@@ -24,7 +19,7 @@ export class Stack {
|
|
|
24
19
|
return this.items.pop();
|
|
25
20
|
}
|
|
26
21
|
}
|
|
27
|
-
|
|
22
|
+
function ListRemoveEntry(entry) {
|
|
28
23
|
if (entry === undefined) {
|
|
29
24
|
return undefined;
|
|
30
25
|
}
|
|
@@ -37,7 +32,7 @@ export function ListRemoveEntry(entry) {
|
|
|
37
32
|
}
|
|
38
33
|
return (entry);
|
|
39
34
|
}
|
|
40
|
-
|
|
35
|
+
function ListMakeEntry(data) {
|
|
41
36
|
return new List(false, data);
|
|
42
37
|
}
|
|
43
38
|
export function ListMakeHead() {
|
|
@@ -120,13 +115,6 @@ export class List {
|
|
|
120
115
|
empty() {
|
|
121
116
|
return (this.next === this);
|
|
122
117
|
}
|
|
123
|
-
pushEntry(entry) {
|
|
124
|
-
entry.isHead = false;
|
|
125
|
-
entry.next = this.next;
|
|
126
|
-
entry.prev = this;
|
|
127
|
-
this.next = entry;
|
|
128
|
-
entry.next.prev = entry;
|
|
129
|
-
}
|
|
130
118
|
push(data) {
|
|
131
119
|
const entry = ListMakeEntry(data);
|
|
132
120
|
entry.data = data;
|
|
@@ -136,46 +124,7 @@ export class List {
|
|
|
136
124
|
this.next = entry;
|
|
137
125
|
entry.next.prev = entry;
|
|
138
126
|
}
|
|
139
|
-
popEntry(head) {
|
|
140
|
-
if (this.next.isHead) {
|
|
141
|
-
return undefined;
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
return ListRemoveEntry(this.next);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
insertEntry(entry) {
|
|
148
|
-
entry.isHead = false;
|
|
149
|
-
this.prev.next = entry;
|
|
150
|
-
entry.next = this;
|
|
151
|
-
entry.prev = this.prev;
|
|
152
|
-
this.prev = entry;
|
|
153
|
-
return entry;
|
|
154
|
-
}
|
|
155
|
-
insertAfter(data) {
|
|
156
|
-
const entry = ListMakeEntry(data);
|
|
157
|
-
entry.next = this.next;
|
|
158
|
-
entry.prev = this;
|
|
159
|
-
this.next = entry;
|
|
160
|
-
entry.next.prev = entry;
|
|
161
|
-
return (entry);
|
|
162
|
-
}
|
|
163
|
-
insertBefore(data) {
|
|
164
|
-
const entry = ListMakeEntry(data);
|
|
165
|
-
return this.insertEntryBefore(entry);
|
|
166
|
-
}
|
|
167
|
-
insertEntryBefore(entry) {
|
|
168
|
-
this.prev.next = entry;
|
|
169
|
-
entry.next = this;
|
|
170
|
-
entry.prev = this.prev;
|
|
171
|
-
this.prev = entry;
|
|
172
|
-
return (entry);
|
|
173
|
-
}
|
|
174
127
|
}
|
|
175
|
-
export const numberComparer = {
|
|
176
|
-
min: Number.MIN_VALUE,
|
|
177
|
-
compare: (a, b) => a - b,
|
|
178
|
-
};
|
|
179
128
|
export class Heap {
|
|
180
129
|
constructor(a, comp) {
|
|
181
130
|
this.comp = comp;
|
|
@@ -227,93 +176,6 @@ export class Heap {
|
|
|
227
176
|
}
|
|
228
177
|
}
|
|
229
178
|
}
|
|
230
|
-
// For testing
|
|
231
|
-
export function LinearDictionary(compareKeys) {
|
|
232
|
-
const props = [];
|
|
233
|
-
const compareProps = (a, b) => compareKeys(a.key, b.key);
|
|
234
|
-
function diag() {
|
|
235
|
-
console.log(`size is ${props.length}`);
|
|
236
|
-
}
|
|
237
|
-
function mapRange(action, accum, start, end) {
|
|
238
|
-
let _start = start;
|
|
239
|
-
let _end = end;
|
|
240
|
-
if (props.length !== 0) {
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
if (_start === undefined) {
|
|
244
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
245
|
-
_start = min().key;
|
|
246
|
-
}
|
|
247
|
-
if (_end === undefined) {
|
|
248
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
249
|
-
_end = max().key;
|
|
250
|
-
}
|
|
251
|
-
for (let i = 0, len = props.length; i < len; i++) {
|
|
252
|
-
if (compareKeys(_start, props[i].key) <= 0) {
|
|
253
|
-
const ecmp = compareKeys(_end, props[i].key);
|
|
254
|
-
if (ecmp < 0) {
|
|
255
|
-
break;
|
|
256
|
-
}
|
|
257
|
-
if (!action(props[i], accum)) {
|
|
258
|
-
break;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
function map(action, accum) {
|
|
264
|
-
mapRange(action, accum);
|
|
265
|
-
}
|
|
266
|
-
function min() {
|
|
267
|
-
if (props.length > 0) {
|
|
268
|
-
return props[0];
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
function max() {
|
|
272
|
-
if (props.length > 0) {
|
|
273
|
-
return props[props.length - 1];
|
|
274
|
-
}
|
|
275
|
-
}
|
|
276
|
-
function get(key) {
|
|
277
|
-
for (let i = 0, len = props.length; i < len; i++) {
|
|
278
|
-
if (props[i].key == key) {
|
|
279
|
-
return props[i];
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
}
|
|
283
|
-
function put(key, data) {
|
|
284
|
-
if (key !== undefined) {
|
|
285
|
-
if (data === undefined) {
|
|
286
|
-
remove(key);
|
|
287
|
-
}
|
|
288
|
-
else {
|
|
289
|
-
props.push({ key, data });
|
|
290
|
-
props.sort(compareProps); // Go to insertion sort if too slow
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
function remove(key) {
|
|
295
|
-
if (key !== undefined) {
|
|
296
|
-
for (let i = 0, len = props.length; i < len; i++) {
|
|
297
|
-
if (props[i].key == key) {
|
|
298
|
-
props[i] = props[len - 1];
|
|
299
|
-
props.length--;
|
|
300
|
-
props.sort(compareProps);
|
|
301
|
-
break;
|
|
302
|
-
}
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
return {
|
|
307
|
-
min: min,
|
|
308
|
-
max: max,
|
|
309
|
-
map: map,
|
|
310
|
-
mapRange: mapRange,
|
|
311
|
-
remove: remove,
|
|
312
|
-
get: get,
|
|
313
|
-
put: put,
|
|
314
|
-
diag: diag,
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
179
|
export var RBColor;
|
|
318
180
|
(function (RBColor) {
|
|
319
181
|
RBColor[RBColor["RED"] = 0] = "RED";
|
|
@@ -489,18 +351,6 @@ export class RedBlackTree {
|
|
|
489
351
|
this.aug.update(node);
|
|
490
352
|
}
|
|
491
353
|
}
|
|
492
|
-
removeMin() {
|
|
493
|
-
if (this.root) {
|
|
494
|
-
if ((!this.isRed(this.root.left)) && (!this.isRed(this.root.right))) {
|
|
495
|
-
this.root.color = 0 /* RED */;
|
|
496
|
-
}
|
|
497
|
-
this.root = this.nodeRemoveMin(this.root);
|
|
498
|
-
if (this.root) {
|
|
499
|
-
this.root.color = 1 /* BLACK */;
|
|
500
|
-
}
|
|
501
|
-
}
|
|
502
|
-
// TODO: error on empty
|
|
503
|
-
}
|
|
504
354
|
nodeRemoveMin(node) {
|
|
505
355
|
let _node = node;
|
|
506
356
|
if (_node.left) {
|
|
@@ -512,33 +362,6 @@ export class RedBlackTree {
|
|
|
512
362
|
return this.balance(_node);
|
|
513
363
|
}
|
|
514
364
|
}
|
|
515
|
-
removeMax() {
|
|
516
|
-
if (this.root) {
|
|
517
|
-
if ((!this.isRed(this.root.left)) && (!this.isRed(this.root.right))) {
|
|
518
|
-
this.root.color = 0 /* RED */;
|
|
519
|
-
}
|
|
520
|
-
this.root = this.nodeRemoveMax(this.root);
|
|
521
|
-
if (this.root) {
|
|
522
|
-
this.root.color = 1 /* BLACK */;
|
|
523
|
-
}
|
|
524
|
-
}
|
|
525
|
-
// TODO: error on empty
|
|
526
|
-
}
|
|
527
|
-
nodeRemoveMax(node) {
|
|
528
|
-
let _node = node;
|
|
529
|
-
if (this.isRed(_node.left)) {
|
|
530
|
-
_node = this.rotateRight(_node);
|
|
531
|
-
}
|
|
532
|
-
if (!_node.right) {
|
|
533
|
-
return undefined;
|
|
534
|
-
}
|
|
535
|
-
if ((!this.isRed(_node.right)) && (!this.isRed(_node.right.left))) {
|
|
536
|
-
_node = this.moveRedRight(_node);
|
|
537
|
-
}
|
|
538
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
539
|
-
_node.right = this.nodeRemoveMax(_node.right);
|
|
540
|
-
return this.balance(_node);
|
|
541
|
-
}
|
|
542
365
|
remove(key) {
|
|
543
366
|
if (key !== undefined) {
|
|
544
367
|
if (!this.contains(key)) {
|
|
@@ -875,115 +698,11 @@ export class RedBlackTree {
|
|
|
875
698
|
console.log(`Height is ${this.height()}`);
|
|
876
699
|
}
|
|
877
700
|
}
|
|
878
|
-
/**
|
|
879
|
-
* Union of two ranges; assumes for both ranges start \<= end.
|
|
880
|
-
* @param a - A range
|
|
881
|
-
* @param b - A range
|
|
882
|
-
*/
|
|
883
|
-
export function integerRangeUnion(a, b) {
|
|
884
|
-
return {
|
|
885
|
-
start: Math.min(a.start, b.start),
|
|
886
|
-
end: Math.max(a.end, b.end),
|
|
887
|
-
};
|
|
888
|
-
}
|
|
889
|
-
export function integerRangeOverlaps(a, b) {
|
|
890
|
-
return (a.start < b.end) && (a.end > b.start);
|
|
891
|
-
}
|
|
892
|
-
export function integerRangeComparer(a, b) {
|
|
893
|
-
if (a.start === b.start) {
|
|
894
|
-
return a.end - b.end;
|
|
895
|
-
}
|
|
896
|
-
else {
|
|
897
|
-
return a.start - b.start;
|
|
898
|
-
}
|
|
899
|
-
}
|
|
900
|
-
export const integerRangeCopy = (r) => ({ start: r.start, end: r.end });
|
|
901
701
|
export const integerRangeToString = (range) => `[${range.start},${range.end})`;
|
|
902
|
-
|
|
903
|
-
export class IntegerRangeTree {
|
|
904
|
-
constructor() {
|
|
905
|
-
this.ranges = new RedBlackTree(integerRangeComparer, this);
|
|
906
|
-
this.diag = false;
|
|
907
|
-
}
|
|
908
|
-
remove(r) {
|
|
909
|
-
this.ranges.remove(r);
|
|
910
|
-
}
|
|
911
|
-
put(r) {
|
|
912
|
-
this.ranges.put(r, { minmax: integerRangeCopy(r) });
|
|
913
|
-
}
|
|
914
|
-
toString() {
|
|
915
|
-
return this.nodeToString(this.ranges.root);
|
|
916
|
-
}
|
|
917
|
-
nodeToString(node) {
|
|
918
|
-
let buf = "";
|
|
919
|
-
let indentAmt = 0;
|
|
920
|
-
const actions = {
|
|
921
|
-
pre: (n) => {
|
|
922
|
-
let red = "";
|
|
923
|
-
if (n.color === 0 /* RED */) {
|
|
924
|
-
red = "R ";
|
|
925
|
-
}
|
|
926
|
-
buf += internedSpaces(indentAmt);
|
|
927
|
-
buf += `${red}key: ${integerRangeToString(n.key)} minmax: ${integerRangeToString(n.data.minmax)}\n`;
|
|
928
|
-
indentAmt += 2;
|
|
929
|
-
return true;
|
|
930
|
-
},
|
|
931
|
-
post: (n) => {
|
|
932
|
-
indentAmt -= 2;
|
|
933
|
-
return true;
|
|
934
|
-
},
|
|
935
|
-
showStructure: true,
|
|
936
|
-
};
|
|
937
|
-
this.ranges.nodeWalk(node, actions);
|
|
938
|
-
return buf;
|
|
939
|
-
}
|
|
940
|
-
matchPos(pos) {
|
|
941
|
-
return this.match({ start: pos, end: pos + 1 });
|
|
942
|
-
}
|
|
943
|
-
match(r) {
|
|
944
|
-
return this.ranges.gather(r, this);
|
|
945
|
-
}
|
|
946
|
-
matchNode(node, key) {
|
|
947
|
-
return !!node && integerRangeOverlaps(node.key, key);
|
|
948
|
-
}
|
|
949
|
-
continueSubtree(node, key) {
|
|
950
|
-
const cont = !!node && integerRangeOverlaps(node.data.minmax, key);
|
|
951
|
-
if (this.diag && (!cont)) {
|
|
952
|
-
if (node) {
|
|
953
|
-
console.log(`skipping subtree of size ${node.size} key ${integerRangeToString(key)}`);
|
|
954
|
-
console.log(this.nodeToString(node));
|
|
955
|
-
}
|
|
956
|
-
}
|
|
957
|
-
return cont;
|
|
958
|
-
}
|
|
959
|
-
update(node) {
|
|
960
|
-
if (node.left && node.right) {
|
|
961
|
-
node.data.minmax = integerRangeUnion(node.key, integerRangeUnion(node.left.data.minmax, node.right.data.minmax));
|
|
962
|
-
}
|
|
963
|
-
else {
|
|
964
|
-
if (node.left) {
|
|
965
|
-
node.data.minmax = integerRangeUnion(node.key, node.left.data.minmax);
|
|
966
|
-
}
|
|
967
|
-
else if (node.right) {
|
|
968
|
-
node.data.minmax = integerRangeUnion(node.key, node.right.data.minmax);
|
|
969
|
-
}
|
|
970
|
-
else {
|
|
971
|
-
node.data.minmax = integerRangeCopy(node.key);
|
|
972
|
-
}
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
export const intervalComparer = (a, b) => a.compare(b);
|
|
702
|
+
const intervalComparer = (a, b) => a.compare(b);
|
|
977
703
|
export class IntervalTree {
|
|
978
704
|
constructor() {
|
|
979
705
|
this.intervals = new RedBlackTree(intervalComparer, this);
|
|
980
|
-
this.diag = false;
|
|
981
|
-
this.timePut = false;
|
|
982
|
-
this.putTime = 0;
|
|
983
|
-
this.putCount = 0;
|
|
984
|
-
}
|
|
985
|
-
printTiming() {
|
|
986
|
-
console.log(`put total = ${this.putTime} avg=${(this.putTime / this.putCount).toFixed(2)}`);
|
|
987
706
|
}
|
|
988
707
|
remove(x) {
|
|
989
708
|
this.intervals.remove(x);
|
|
@@ -1001,15 +720,7 @@ export class IntervalTree {
|
|
|
1001
720
|
};
|
|
1002
721
|
};
|
|
1003
722
|
}
|
|
1004
|
-
|
|
1005
|
-
const trace = Trace.start();
|
|
1006
|
-
this.intervals.put(x, { minmax: x.clone() }, rbConflict);
|
|
1007
|
-
this.putTime += trace.trace().duration * 1000;
|
|
1008
|
-
this.putCount++;
|
|
1009
|
-
}
|
|
1010
|
-
else {
|
|
1011
|
-
this.intervals.put(x, { minmax: x.clone() }, rbConflict);
|
|
1012
|
-
}
|
|
723
|
+
this.intervals.put(x, { minmax: x.clone() }, rbConflict);
|
|
1013
724
|
}
|
|
1014
725
|
map(fn) {
|
|
1015
726
|
const actions = {
|
|
@@ -1048,14 +759,7 @@ export class IntervalTree {
|
|
|
1048
759
|
return !!node && node.key.overlaps(key);
|
|
1049
760
|
}
|
|
1050
761
|
continueSubtree(node, key) {
|
|
1051
|
-
|
|
1052
|
-
if (this.diag && (!cont)) {
|
|
1053
|
-
if (node) {
|
|
1054
|
-
console.log(`skipping subtree of size ${node.size} key ${key.toString()}`);
|
|
1055
|
-
// console.log(this.nodeToString(node));
|
|
1056
|
-
}
|
|
1057
|
-
}
|
|
1058
|
-
return cont;
|
|
762
|
+
return !!node && node.data.minmax.overlaps(key);
|
|
1059
763
|
}
|
|
1060
764
|
update(node) {
|
|
1061
765
|
if (node.left && node.right) {
|
|
@@ -1203,26 +907,6 @@ export class TST {
|
|
|
1203
907
|
this.collectPairs(x.mid, { text: prefix.text + x.c }, q);
|
|
1204
908
|
this.collectPairs(x.right, prefix, q);
|
|
1205
909
|
}
|
|
1206
|
-
patternCollect(x, prefix, d, pattern, q) {
|
|
1207
|
-
if (x === undefined) {
|
|
1208
|
-
return;
|
|
1209
|
-
}
|
|
1210
|
-
const c = pattern.charAt(d);
|
|
1211
|
-
if ((c === ".") || (c < x.c)) {
|
|
1212
|
-
this.patternCollect(x.left, prefix, d, pattern, q);
|
|
1213
|
-
}
|
|
1214
|
-
else if ((c === ".") || (c === x.c)) {
|
|
1215
|
-
if ((d === (pattern.length - 1)) && (x.val !== undefined)) {
|
|
1216
|
-
q.push(prefix.text + x.c);
|
|
1217
|
-
}
|
|
1218
|
-
else if (d < (pattern.length - 1)) {
|
|
1219
|
-
this.patternCollect(x.mid, { text: prefix.text + x.c }, d + 1, pattern, q);
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
|
-
if ((c === ".") || (c > x.c)) {
|
|
1223
|
-
this.patternCollect(x.right, prefix, d, pattern, q);
|
|
1224
|
-
}
|
|
1225
|
-
}
|
|
1226
910
|
nodeProximity(x, prefix, d, pattern, distance, q) {
|
|
1227
911
|
if ((x === undefined) || (distance < 0)) {
|
|
1228
912
|
return;
|
|
@@ -1252,10 +936,5 @@ export class TST {
|
|
|
1252
936
|
this.nodeProximity(x.right, prefix, d, pattern, distance, q);
|
|
1253
937
|
}
|
|
1254
938
|
}
|
|
1255
|
-
match(pattern) {
|
|
1256
|
-
const q = [];
|
|
1257
|
-
this.patternCollect(this.root, { text: "" }, 0, pattern, q);
|
|
1258
|
-
return q;
|
|
1259
|
-
}
|
|
1260
939
|
}
|
|
1261
940
|
//# sourceMappingURL=collections.js.map
|