NodeSpace.h
// [[[[1]]]] - nodal p2p wiki daemon // This article and all its includes are licenced under LGPL // GPL: [[[[2]]]] // SRC: [[[[3]]]] // included in [[[[4]]]][[[[5]]]]
// 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("\ *root\ *io;session;\ *io\ *server;streams;\ *stream\ *session\ *events;desktop;\ *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); nodeEVENTS = trieGetValue("events"); logAdd("nodeEVENTS = %d",nodeEVENTS); 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() { //logAdd("nodeReduce() : (%d<-%d->%d)",nodeGetValue(nodeRENDER,nodePREV),nodeRENDER,nodeGetValue(nodeRENDER,nodeNEXT)); 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 } }