forked from cory/tildefriends
All of the changes that have been sitting on tildepi for ages. For posterity.
git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3530 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
269
packages/cory/db/db.js
Normal file
269
packages/cory/db/db.js
Normal file
@ -0,0 +1,269 @@
|
||||
//! {"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();
|
||||
}
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user