-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathbootstrapTransform.js
78 lines (68 loc) · 2.61 KB
/
bootstrapTransform.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
// These methods let you build a transform function from a transformComponent
// function for OT types like JSON0 in which operations are lists of components
// and transforming them requires N^2 work. I find it kind of nasty that I need
// this, but I'm not really sure what a better solution is. Maybe I should do
// this automatically to types that don't have a compose function defined.
// Add transform and transformX functions for an OT type which has
// transformComponent defined. transformComponent(destination array,
// component, other component, side)
module.exports = bootstrapTransform
function bootstrapTransform(type, transformComponent, checkValidOp, append) {
var transformComponentX = function(left, right, destLeft, destRight) {
transformComponent(destLeft, left, right, 'left');
transformComponent(destRight, right, left, 'right');
};
var transformX = type.transformX = function(leftOp, rightOp) {
checkValidOp(leftOp);
checkValidOp(rightOp);
var newRightOp = [];
for (var i = 0; i < rightOp.length; i++) {
var rightComponent = rightOp[i];
// Generate newLeftOp by composing leftOp by rightComponent
var newLeftOp = [];
var k = 0;
while (k < leftOp.length) {
var nextC = [];
transformComponentX(leftOp[k], rightComponent, newLeftOp, nextC);
k++;
if (nextC.length === 1) {
rightComponent = nextC[0];
} else if (nextC.length === 0) {
for (var j = k; j < leftOp.length; j++) {
append(newLeftOp, leftOp[j]);
}
rightComponent = null;
break;
} else {
// Recurse.
var pair = transformX(leftOp.slice(k), nextC);
for (var l = 0; l < pair[0].length; l++) {
append(newLeftOp, pair[0][l]);
}
for (var r = 0; r < pair[1].length; r++) {
append(newRightOp, pair[1][r]);
}
rightComponent = null;
break;
}
}
if (rightComponent != null) {
append(newRightOp, rightComponent);
}
leftOp = newLeftOp;
}
return [leftOp, newRightOp];
};
// Transforms op with specified type ('left' or 'right') by otherOp.
type.transform = function(op, otherOp, type) {
if (!(type === 'left' || type === 'right'))
throw new Error("type must be 'left' or 'right'");
if (otherOp.length === 0) return op;
if (op.length === 1 && otherOp.length === 1)
return transformComponent([], op[0], otherOp[0], type);
if (type === 'left')
return transformX(op, otherOp)[0];
else
return transformX(otherOp, op)[1];
};
};