NodeSpace.h
From Organic Design wiki
// [[[[http://www.organicdesign.co.nz/peerd|peerd]]]] - nodal p2p wiki daemon
// This article and all its includes are licenced under LGPL
// GPL: [[[[http://www.gnu.org/copyleft/lesser.html]]]]
// SRC: [[[[http://www.organicdesign.co.nz/nodeSpace.c]]]]
// included in [[[[http://www.organicdesign.co.nz/category:peerd/files/C|peerd]]]][[[[http://www.organicdesign.co.nz/peerd.c|/peerd.c]]]]
// node: a type for referring to nodes
typedef int node;
// code is a variable of type pointer-to-function
typedef void (codeType)();
codeType *code;
// constants defined in [[[[peerd.c]]]]
// - nodal constants
// - this and parent
// stateless
node nodeSESSION;
node nodeSTREAMS;
// function ref
node nodeEVENTS;
node nodeIO;
node nodeSERVER;
node nodeDESKTOP;
node nodeRENDER;
// pointer to struct
node nodeSTREAM;
node nodeSPRITE;
node nodeEVENT;
// Prototypes
node nodeGetValue(node subject,node key);
node nodeSetValue(node subject,node key,node value);
node nodeInsertKey(node subject,node key);
node nodeRemoveKey(node subject,node key);
node nodeLoopInsert(node subject,node insert);
node nodeLoopRemove(node subject,node remove);
node nodeLoopRotate(node subject);
node nodeTraverse(node subject,node *path);
void **nodeState(node subject,node key);
void nodeInit();
void nodeExit();
void ifExit();
void nodeReduce();
// ----------------------------------------------------------------------------------------- //
// nodeSpace.c
// set nodal value of node/path
node nodeGetValue(node subject,node key) {
// todo: if subject/nodeGETVAL...
return listGetValue(listTraverse(subject,key));
}
node nodeSetValue(node subject,node key,node value) {
// todo: onChange
return listSetValue(listTraverse(subject,key),value);
}
// Returns a newly created node
node nodeInsert() {
return listInsert();
}
// Returns newly created node
// - this is just traverse() but with an event raised
node nodeInsertKey(node subject,node key) {
// todo: hook in nodeSTART
return listTraverse(subject,key);
}
// Returns the node that was removed
node nodeRemoveKey(node subject,node key) {
// todo: hook in nodeSTOP
node i = listTraverse(subject,key);
// todo: delete
return i;
}
// Returns the inserted node as the new loop pointer
// - this allows it to act as a stack if nodeLOOP (current-loop-node) is updated with returned node
// - either can be 0 on entry (for new loop and/or new node)
// todo: update nodePARENT of inserted node
node nodeLoopInsert(node subject,node insert) {
node focus = nodeGetValue(subject,0);
if (insert == 0) insert = nodeInsert();
if (focus) {
// Insert into existing [[[[loop]]]] ([[[[focus]]]] remains unchanged)
node next = nodeGetValue(focus,nodeNEXT);
nodeSetValue(insert,nodeNEXT,next);
nodeSetValue(insert,nodePREV,focus);
nodeSetValue(next,nodePREV,insert);
nodeSetValue(focus,nodeNEXT,insert);
}
else {
// No existing [[[[loop]]]], make new node into a single item loop
nodeSetValue(subject,0,insert);
nodeSetValue(insert,nodeNEXT,insert);
nodeSetValue(insert,nodePREV,insert);
}
nodeSetValue(insert,nodePARENT,subject);
return insert;
}
// Removes a node from the subject's [[[[loop]]]]
// - if remove parameter is 0, the [[[[focus]]]] node is removed and next becomes the new focus
// - the removed item is returned not the focus
// - the removed node's parent is set to 0
node nodeLoopRemove(node subject,node remove) {
node n = remove;
node focus = nodeGetValue(subject,0);
if (focus) {
if (remove == 0) remove = focus;
node prev = nodeGetValue(remove,nodePREV);
node next = nodeGetValue(remove,nodeNEXT);
nodeSetValue(next,nodePREV,prev);
nodeSetValue(prev,nodeNEXT,next);
if (next == remove) next = 0;
if (remove == focus) focus = nodeSetValue(subject,0,next);
nodeSetValue(remove,nodePARENT,0);
}
return remove;
}
// Rotates the subject node's [[[[loop]]]] and returning the last [[[[focus]]]]
node nodeLoopRotate(node subject) {
node focus = nodeGetValue(subject,0);
if (focus) nodeSetValue(subject,0,nodeGetValue(focus,nodeNEXT));
return focus;
}
// not used yet - use array-of-node path?
node nodeTraverse(node subject,node *path) {
}
// Treat an association value as a pointer index
void **nodeState(node subject,node key) {
int index = nodeGetValue(subject,key);
if (index == 0) nodeSetValue(subject,key,index = insertPointer(NULL));
return pointer(index);
}
// Clean up all the mess and exit
// - add exit functions here for any includes requiring cleanup before exit
void nodeExit() {
logAdd("Gracefully exiting.");
ifExit();
ioExit();
listExit();
exit(EXIT_SUCCESS);
}
// Set up initial nodal structure
// - todo: this structure should be read from [[[[nodeSpace.txt]]]]
// - use [[[[io.c]]]] for reading content from wiki if url/file
char *serialise(node);
void deserialise(char*);
void nodeInit() {
if (file) {
// todo: load from file and deserialise
}
else {
// no file specified in command-line args, use default inline text
deserialise("\
*[[0|root]]\
*[[1000|io]];[[1001|session]];\
*[[io]]\
*[[1002|server]];[[1003|streams]];\
*[[1004|stream]]\
*[[session]]\
*[[1006|desktop]];\
*[[1007|sprite]]\
*[[render]]\
");
}
nodeIO = trieGetValue("io"); logAdd("nodeIO = %d",nodeIO);
nodeSESSION = trieGetValue("session"); logAdd("nodeSESSION = %d",nodeSESSION);
nodeSERVER = trieGetValue("server"); logAdd("nodeSERVER = %d",nodeSERVER);
nodeSTREAMS = trieGetValue("streams"); logAdd("nodeSTREAMS = %d",nodeSTREAMS);
nodeSTREAM = trieGetValue("stream"); logAdd("nodeSTREAM = %d",nodeSTREAM);
nodeDESKTOP = trieGetValue("desktop"); logAdd("nodeDESKTOP = %d",nodeDESKTOP);
nodeSPRITE = trieGetValue("sprite"); logAdd("nodeSPRITE = %d",nodeSPRITE);
nodeRENDER = trieGetValue("render"); logAdd("nodeRENDER = %d",nodeRENDER);
}
// Moves "this" to node's [[[[focus]]]] if exists then rotates [[[[loop]]]] and executes/reduces the focus item
void nodeReduce() {
grandpa = parent;
if (this = nodeLoopRotate(parent = this)) { // Move "this" to the [[[[focus]]]] in the node's loop and rotate
nodeSetValue(this,nodePARENT,parent); // Update the [[[[parent]]]] association
if (code = *nodeState(this,nodeCODE)) code(); // [[[[nodeCODE]]]] value is a pointer-index, execute as function-reference if non-zero
}
}