forked from cory/tildefriends
Cory McWilliams
d293637741
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3530 ed5197a5-7fde-0310-b194-c3ffbd925b24
269 lines
7.5 KiB
JavaScript
269 lines
7.5 KiB
JavaScript
//! {"category": "libraries"}
|
|
|
|
class DatabaseList {
|
|
constructor(name) {
|
|
this._name = name;
|
|
}
|
|
|
|
_getList() {
|
|
let self = this;
|
|
return database.get(this._name).then(function(node) {
|
|
return JSON.parse(node);
|
|
}).catch(function(error) {
|
|
return self._emptyNode();
|
|
});
|
|
}
|
|
|
|
_randomKey() {
|
|
let kAlphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
let kBytes = 32;
|
|
let result = "";
|
|
for (let i = 0; i < kBytes; i++) {
|
|
result += kAlphabet.charAt(Math.floor(Math.random() * kAlphabet.length));
|
|
}
|
|
return this._name + "_" + result;
|
|
}
|
|
|
|
_emptyNode() {
|
|
return {next: null, previous: null};
|
|
}
|
|
|
|
_getNode() {
|
|
var self = this;
|
|
var key = self._randomKey();
|
|
return database.get(key).then(function(found) {
|
|
if (!found) {
|
|
return key;
|
|
} else {
|
|
return self._getNode();
|
|
}
|
|
});
|
|
}
|
|
|
|
_getRelative(node, next, count) {
|
|
}
|
|
|
|
_insertEnd(item, after) {
|
|
let self = this;
|
|
return this._getList().then(function(listNode) {
|
|
let readPromises = [self._getNode()];
|
|
readPromises.push(listNode.previous ? database.get(listNode.previous).then(JSON.parse) : null);
|
|
readPromises.push(listNode.next ? database.get(listNode.next).then(JSON.parse) : null);
|
|
return Promise.all(readPromises).then(function(results) {
|
|
let newNodeName = results[0];
|
|
let previousNode = results[1];
|
|
let nextNode = results[2];
|
|
let newNode = self._emptyNode();
|
|
let oldPrevious = listNode.previous;
|
|
let oldNext = listNode.next;
|
|
newNode.value = item;
|
|
newNode.previous = listNode.previous || newNodeName;
|
|
newNode.next = listNode.next || newNodeName;
|
|
if (after) {
|
|
listNode.previous = newNodeName;
|
|
listNode.next = listNode.next || newNodeName;
|
|
} else {
|
|
listNode.next = newNodeName;
|
|
listNode.previous = listNode.previous || newNodeName;
|
|
}
|
|
let writePromises = [
|
|
database.set(self._name, JSON.stringify(listNode)),
|
|
database.set(newNodeName, JSON.stringify(newNode)),
|
|
];
|
|
if (oldPrevious && oldPrevious == oldNext) {
|
|
previousNode.next = newNodeName;
|
|
previousNode.previous = newNodeName;
|
|
writePromises.push(database.set(oldPrevious, JSON.stringify(previousNode)));
|
|
} else {
|
|
if (previousNode) {
|
|
previousNode.next = newNodeName;
|
|
writePromises.push(database.set(oldPrevious, JSON.stringify(previousNode)));
|
|
}
|
|
if (nextNode) {
|
|
nextNode.previous = newNodeName;
|
|
writePromises.push(database.set(oldNext, JSON.stringify(nextNode)));
|
|
}
|
|
}
|
|
return Promise.all(writePromises);
|
|
});
|
|
});
|
|
}
|
|
|
|
_removeEnd(after) {
|
|
let self = this;
|
|
return this._getList().then(function(listNode) {
|
|
if (listNode.next) {
|
|
if (listNode.next == listNode.previous) {
|
|
return database.get(listNode.next).then(JSON.parse).then(function(removedNode) {
|
|
let removedName = listNode.next;
|
|
listNode.next = null;
|
|
listNode.previous = null;
|
|
return Promise.all([
|
|
database.remove(removedName),
|
|
database.set(self._name, JSON.stringify(listNode)),
|
|
]).then(function() {
|
|
return removedNode.value;
|
|
});
|
|
});
|
|
} else {
|
|
let name1 = listNode.previous;
|
|
let name2 = listNode.next;
|
|
return Promise.all([
|
|
database.get(listNode.previous),
|
|
database.get(listNode.next),
|
|
]).then(function(nodes) {
|
|
var node1 = JSON.parse(nodes[0]);
|
|
var node2 = JSON.parse(nodes[1]);
|
|
if (after) {
|
|
let name0 = node1.previous;
|
|
return database.get(name0).then(JSON.parse).then(function(node0) {
|
|
node0.next = name2;
|
|
node2.previous = name0;
|
|
listNode.previous = name0;
|
|
return Promise.all([
|
|
database.set(name0, JSON.stringify(node0)),
|
|
database.remove(name1),
|
|
database.set(name2, JSON.stringify(node2)),
|
|
database.set(self._name, JSON.stringify(listNode)),
|
|
])
|
|
}).then(function() {
|
|
return node1.value;
|
|
});
|
|
} else {
|
|
let name3 = node2.next;
|
|
return database.get(name3).then(JSON.parse).then(function(node3) {
|
|
node1.next = name3;
|
|
node3.previous = name1;
|
|
listNode.next = name3;
|
|
terminal.print(name1, " ", name2, " ", name3, " ", self._name);
|
|
terminal.print(JSON.stringify(listNode));
|
|
return Promise.all([
|
|
database.set(name1, JSON.stringify(node1)),
|
|
database.remove(name2),
|
|
database.set(name3, JSON.stringify(node3)),
|
|
database.set(self._name, JSON.stringify(listNode)),
|
|
])
|
|
}).then(function() {
|
|
return node2.value;
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
push(item) {
|
|
return this._insertEnd(item, true);
|
|
}
|
|
|
|
pop() {
|
|
return this._removeEnd(true);
|
|
}
|
|
|
|
shift() {
|
|
return this._removeEnd(false);
|
|
}
|
|
|
|
unshift(item) {
|
|
return this._insertEnd(item, false);
|
|
}
|
|
|
|
_sliceInternal(head, count, next, end, result) {
|
|
let self = this;
|
|
if (head[next] == end && count > 0) {
|
|
result.push(head.value);
|
|
return new Promise(function(resolve, reject) { resolve(result); });
|
|
} else {
|
|
if (count > 0) {
|
|
return database.get(head[next]).then(JSON.parse).then(function(retrieved) {
|
|
return self._sliceInternal(retrieved, count - 1, next, end, result).then(function(result) {
|
|
result.push(head.value);
|
|
return result;
|
|
});
|
|
});
|
|
} else {
|
|
return new Promise(function(resolve, reject) { resolve(result); });
|
|
}
|
|
}
|
|
}
|
|
|
|
get(count) {
|
|
let self = this;
|
|
return self._getList().then(function(listNode) {
|
|
if (listNode.next) {
|
|
return database.get(count > 0 ? listNode.next : listNode.previous).then(JSON.parse).then(function(head) {
|
|
if (head) {
|
|
return self._sliceInternal(
|
|
head,
|
|
Math.abs(count),
|
|
count > 0 ? "next" : "previous",
|
|
count > 0 ? listNode.next : listNode.previous,
|
|
[]).then(function(result) {
|
|
result.reverse();
|
|
return result;
|
|
});
|
|
} else {
|
|
return null;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function wipeDatabase() {
|
|
let promises = [];
|
|
return database.getAll().then(function(list) {
|
|
for (let i = 0; i < list.length; i++) {
|
|
promises.push(database.remove(list[i]));
|
|
}
|
|
});
|
|
return Promise.all(promises);
|
|
}
|
|
|
|
function dumpDatabase() {
|
|
return database.getAll().then(function(list) {
|
|
let promises = [];
|
|
for (let i = 0; i < list.length; i++) {
|
|
promises.push(database.get(list[i]));
|
|
}
|
|
return Promise.all(promises).then(function(values) {
|
|
for (let i = 0; i < list.length; i++) {
|
|
terminal.print(list[i], " ", values[i]);
|
|
}
|
|
});
|
|
}).catch(function(error) {
|
|
terminal.print(error);
|
|
});
|
|
}
|
|
|
|
if (imports.terminal) {
|
|
x = new DatabaseList("list");
|
|
core.register("onInput", function(input) {
|
|
if (input == "clear") {
|
|
wipeDatabase().then(function() {
|
|
terminal.print("Database is now empty.");
|
|
});
|
|
} else if (input.substring(0, "push ".length) == "push ") {
|
|
x.push(input.substring("push ".length)).then(dumpDatabase).catch(terminal.print);
|
|
} else if (input.substring(0, "unshift ".length) == "unshift ") {
|
|
x.unshift(input.substring("unshift ".length)).then(dumpDatabase).catch(terminal.print);
|
|
} else if (input == "pop") {
|
|
x.pop().then(function(out) {
|
|
terminal.print("POPPED: ", out);
|
|
}).then(dumpDatabase).catch(terminal.print);
|
|
} else if (input == "shift") {
|
|
x.shift().then(function(out) {
|
|
terminal.print("SHIFTED: ", out);
|
|
}).then(dumpDatabase).catch(terminal.print);
|
|
} else if (input.substring(0, "get ".length) == "get ") {
|
|
let parts = input.split(" ");
|
|
x.get(parseInt(parts[1])).then(function(result) {
|
|
terminal.print(JSON.stringify(result))
|
|
}).catch(terminal.print);
|
|
} else {
|
|
dumpDatabase();
|
|
}
|
|
});
|
|
} |