1
0
Fork 0
mirror of https://github.com/YunoHost-Apps/rocketchat_ynh.git synced 2024-09-03 20:16:25 +02:00
rocketchat_ynh/sources/programs/server/packages/ordered-dict.js
2016-04-29 16:32:48 +02:00

241 lines
19 KiB
JavaScript

(function () {
/* Imports */
var Meteor = Package.meteor.Meteor;
var _ = Package.underscore._;
/* Package-scope variables */
var OrderedDict;
(function(){
///////////////////////////////////////////////////////////////////////////////////
// //
// packages/ordered-dict/ordered_dict.js //
// //
///////////////////////////////////////////////////////////////////////////////////
//
// This file defines an ordered dictionary abstraction that is useful for // 1
// maintaining a dataset backed by observeChanges. It supports ordering items // 2
// by specifying the item they now come before. // 3
// 4
// The implementation is a dictionary that contains nodes of a doubly-linked // 5
// list as its values. // 6
// 7
// constructs a new element struct // 8
// next and prev are whole elements, not keys. // 9
var element = function (key, value, next, prev) { // 10
return { // 11
key: key, // 12
value: value, // 13
next: next, // 14
prev: prev // 15
}; // 16
}; // 17
OrderedDict = function (/* ... */) { // 18
var self = this; // 19
self._dict = {}; // 20
self._first = null; // 21
self._last = null; // 22
self._size = 0; // 23
var args = _.toArray(arguments); // 24
self._stringify = function (x) { return x; }; // 25
if (typeof args[0] === 'function') // 26
self._stringify = args.shift(); // 27
_.each(args, function (kv) { // 28
self.putBefore(kv[0], kv[1], null); // 29
}); // 30
}; // 31
// 32
_.extend(OrderedDict.prototype, { // 33
// the "prefix keys with a space" thing comes from here // 34
// https://github.com/documentcloud/underscore/issues/376#issuecomment-2815649
_k: function (key) { return " " + this._stringify(key); }, // 36
// 37
empty: function () { // 38
var self = this; // 39
return !self._first; // 40
}, // 41
size: function () { // 42
var self = this; // 43
return self._size; // 44
}, // 45
_linkEltIn: function (elt) { // 46
var self = this; // 47
if (!elt.next) { // 48
elt.prev = self._last; // 49
if (self._last) // 50
self._last.next = elt; // 51
self._last = elt; // 52
} else { // 53
elt.prev = elt.next.prev; // 54
elt.next.prev = elt; // 55
if (elt.prev) // 56
elt.prev.next = elt; // 57
} // 58
if (self._first === null || self._first === elt.next) // 59
self._first = elt; // 60
}, // 61
_linkEltOut: function (elt) { // 62
var self = this; // 63
if (elt.next) // 64
elt.next.prev = elt.prev; // 65
if (elt.prev) // 66
elt.prev.next = elt.next; // 67
if (elt === self._last) // 68
self._last = elt.prev; // 69
if (elt === self._first) // 70
self._first = elt.next; // 71
}, // 72
putBefore: function (key, item, before) { // 73
var self = this; // 74
if (self._dict[self._k(key)]) // 75
throw new Error("Item " + key + " already present in OrderedDict"); // 76
var elt = before ? // 77
element(key, item, self._dict[self._k(before)]) : // 78
element(key, item, null); // 79
if (elt.next === undefined) // 80
throw new Error("could not find item to put this one before"); // 81
self._linkEltIn(elt); // 82
self._dict[self._k(key)] = elt; // 83
self._size++; // 84
}, // 85
append: function (key, item) { // 86
var self = this; // 87
self.putBefore(key, item, null); // 88
}, // 89
remove: function (key) { // 90
var self = this; // 91
var elt = self._dict[self._k(key)]; // 92
if (elt === undefined) // 93
throw new Error("Item " + key + " not present in OrderedDict"); // 94
self._linkEltOut(elt); // 95
self._size--; // 96
delete self._dict[self._k(key)]; // 97
return elt.value; // 98
}, // 99
get: function (key) { // 100
var self = this; // 101
if (self.has(key)) // 102
return self._dict[self._k(key)].value; // 103
return undefined; // 104
}, // 105
has: function (key) { // 106
var self = this; // 107
return _.has(self._dict, self._k(key)); // 108
}, // 109
// Iterate through the items in this dictionary in order, calling // 110
// iter(value, key, index) on each one. // 111
// 112
// Stops whenever iter returns OrderedDict.BREAK, or after the last element. // 113
forEach: function (iter) { // 114
var self = this; // 115
var i = 0; // 116
var elt = self._first; // 117
while (elt !== null) { // 118
var b = iter(elt.value, elt.key, i); // 119
if (b === OrderedDict.BREAK) // 120
return; // 121
elt = elt.next; // 122
i++; // 123
} // 124
}, // 125
first: function () { // 126
var self = this; // 127
if (self.empty()) // 128
return undefined; // 129
return self._first.key; // 130
}, // 131
firstValue: function () { // 132
var self = this; // 133
if (self.empty()) // 134
return undefined; // 135
return self._first.value; // 136
}, // 137
last: function () { // 138
var self = this; // 139
if (self.empty()) // 140
return undefined; // 141
return self._last.key; // 142
}, // 143
lastValue: function () { // 144
var self = this; // 145
if (self.empty()) // 146
return undefined; // 147
return self._last.value; // 148
}, // 149
prev: function (key) { // 150
var self = this; // 151
if (self.has(key)) { // 152
var elt = self._dict[self._k(key)]; // 153
if (elt.prev) // 154
return elt.prev.key; // 155
} // 156
return null; // 157
}, // 158
next: function (key) { // 159
var self = this; // 160
if (self.has(key)) { // 161
var elt = self._dict[self._k(key)]; // 162
if (elt.next) // 163
return elt.next.key; // 164
} // 165
return null; // 166
}, // 167
moveBefore: function (key, before) { // 168
var self = this; // 169
var elt = self._dict[self._k(key)]; // 170
var eltBefore = before ? self._dict[self._k(before)] : null; // 171
if (elt === undefined) // 172
throw new Error("Item to move is not present"); // 173
if (eltBefore === undefined) { // 174
throw new Error("Could not find element to move this one before"); // 175
} // 176
if (eltBefore === elt.next) // no moving necessary // 177
return; // 178
// remove from its old place // 179
self._linkEltOut(elt); // 180
// patch into its new place // 181
elt.next = eltBefore; // 182
self._linkEltIn(elt); // 183
}, // 184
// Linear, sadly. // 185
indexOf: function (key) { // 186
var self = this; // 187
var ret = null; // 188
self.forEach(function (v, k, i) { // 189
if (self._k(k) === self._k(key)) { // 190
ret = i; // 191
return OrderedDict.BREAK; // 192
} // 193
return undefined; // 194
}); // 195
return ret; // 196
}, // 197
_checkRep: function () { // 198
var self = this; // 199
_.each(self._dict, function (k, v) { // 200
if (v.next === v) // 201
throw new Error("Next is a loop"); // 202
if (v.prev === v) // 203
throw new Error("Prev is a loop"); // 204
}); // 205
} // 206
// 207
}); // 208
OrderedDict.BREAK = {"break": true}; // 209
// 210
///////////////////////////////////////////////////////////////////////////////////
}).call(this);
/* Exports */
if (typeof Package === 'undefined') Package = {};
Package['ordered-dict'] = {
OrderedDict: OrderedDict
};
})();
//# sourceMappingURL=ordered-dict.js.map