/*\ module-type: utils title: $:/core/modules/utils/linkedlist.js type: application/javascript This is a doubly-linked indexed list intended for manipulation, particularly pushTop, which it does with significantly better performance than an array. \*/ (function(){ function LinkedList() { this.clear(); }; LinkedList.prototype.clear = function() { // LinkedList performs the duty of both the head and tail node this.next = new LLMap(); this.prev = new LLMap(); // Linked list head initially points to itself this.next.set(null, null); this.prev.set(null, null); this.length = 0; }; LinkedList.prototype.remove = function(value) { if($tw.utils.isArray(value)) { for(var t=0; t 1) { nextEntry.shift(); prevEntry.shift(); } else { list.next.set(value,undefined); list.prev.set(value,undefined); } list.length -= 1; }; // Sticks the given node onto the end of the list. function _linkToEnd(list,value) { var old = list.next.get(value); var last = list.prev.get(null); // Does it already exists? if(old !== undefined) { if(!Array.isArray(old)) { old = [old]; list.next.set(value,old); list.prev.set(value,[list.prev.get(value)]); } old.push(null); list.prev.get(value).push(last); } else { list.next.set(value,null); list.prev.set(value,last); } // Make the old last point to this new one. if(value !== last) { var array = list.next.get(last); if(Array.isArray(array)) { array[array.length-1] = value; } else { list.next.set(last,value); } list.prev.set(null,value); } else { // Edge case, the pushed value was already the last value. // The second-to-last nextPtr for that value must point to itself now. var array = list.next.get(last); array[array.length-2] = value; } list.length += 1; }; function _assertString(value) { if(typeof value !== "string") { throw "Linked List only accepts string values, not " + value; } }; var LLMap = function() { this.map = Object.create(null); }; // Just a wrapper so our object map can also accept null. LLMap.prototype = { set: function(key,val) { (key === null) ? (this.null = val) : (this.map[key] = val); }, get: function(key) { return (key === null) ? this.null : this.map[key]; } }; exports.LinkedList = LinkedList; })();