Difference between revisions of "Peerd.c"
(remove serialise test from here) |
(set the node constants from trieGetValue()) |
||
Line 1: | Line 1: | ||
// [[[[http://www.organicdesign.co.nz/peerd|peerd]]]] - nodal p2p wiki daemon | // [[[[http://www.organicdesign.co.nz/peerd|peerd]]]] - nodal p2p wiki daemon | ||
− | + | // This article and all its includes are licenced under LGPL | |
− | // This article and all its includes are licenced under [[[[http://www.gnu.org/copyleft/lesser.html | + | // 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]]]] | |
− | |||
− | int | + | typedef int node; // node: a type for referring to nodes |
− | + | typedef void (code)(); // code: a type for executing functions from pointer | |
− | + | // Reserved nodes used by nodal reduction process (tmp) | |
− | + | // - doesn't matter that these node indexes conflict with 128 ascii nodes | |
− | + | // because these will not currently need anything stored in them | |
− | + | #define nodeLOOP 1 | |
− | # | + | #define nodeTRUE 1 |
− | # | + | #define nodeNEXT 2 |
− | # | + | #define nodePREV 3 |
− | # | + | #define nodeCODE 4 |
− | # | ||
− | |||
− | // | + | // Runtime nodes |
− | + | node this; // this: the current node, like cwd | |
− | |||
− | |||
− | // | + | // stateless |
− | + | node nodeINTERFACE; | |
− | + | node nodeSTREAMS; | |
− | |||
− | |||
− | // | + | // function ref |
− | + | node nodeEVENTS; | |
− | + | node nodeIO; | |
− | + | node nodeSERVER; | |
− | + | node nodeDESKTOP; | |
− | |||
− | |||
− | |||
− | // | + | // pointer to struct |
− | + | node nodeSTREAM; | |
− | + | node nodeWINDOW; | |
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | // Prototypes | |
− | + | node nodeTraverse(node subject,node key); | |
− | + | 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); | ||
+ | void **nodeGetState(node subject,node key); | ||
+ | int nodeInit(); | ||
+ | void nodeExit(); | ||
+ | void nodeReduce(); | ||
− | |||
− | |||
− | |||
+ | // ----------------------------------------------------------------------------------------- // | ||
+ | // nodeSpace.c | ||
+ | |||
+ | // - use array-of-node path? | ||
+ | node nodeTraverse(node subject,node key) { | ||
+ | return listTraverse((item)subject,(item)key); | ||
+ | } | ||
+ | |||
+ | // set nodal value of node/path | ||
+ | // - allows null key | ||
+ | node nodeGetValue(node subject,node key) { | ||
+ | return listGetValue(key?listTraverse((item)subject,(item)key):(item)subject); | ||
+ | } | ||
+ | |||
+ | node nodeSetValue(node subject,node key,node value) { | ||
+ | // todo: onChange | ||
+ | return listSetValue(key?listTraverse((item)subject,(item)key):(item)subject, (item)value); | ||
+ | } | ||
+ | |||
+ | // Returns a newly created node | ||
+ | node nodeInsert() { | ||
+ | return (node)listInsert(); | ||
+ | } | ||
+ | |||
+ | // Returns newly created node | ||
+ | // - this is just traverse() but with an event raised | ||
+ | node nodeInsertKey(node subject,node key) { | ||
+ | // todo: onInstall | ||
+ | node i = nodeTraverse(subject,key); | ||
+ | return i; | ||
+ | } | ||
+ | |||
+ | // Returns the node that was removed | ||
+ | node nodeRemoveKey(node subject,node key) { | ||
+ | // todo: onRemove | ||
+ | node i = nodeTraverse(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) | ||
+ | node nodeLoopInsert(node subject,node insert) { | ||
+ | if (insert == 0) insert = nodeInsert(); | ||
+ | if (subject == 0) subject = insert; | ||
+ | node next = nodeGetValue(subject,nodeNEXT); | ||
+ | nodeSetValue(insert,nodeNEXT,next); | ||
+ | nodeSetValue(subject,nodeNEXT,insert); | ||
+ | nodeSetValue(insert,nodePREV,subject); | ||
+ | return nodeSetValue(next,nodePREV,insert); | ||
+ | } | ||
+ | |||
+ | // Returns the new loop pointer so nodeLOOP can be removed and updated | ||
+ | node nodeLoopRemove(node subject) { | ||
+ | node prev = nodeGetValue(subject,nodePREV); | ||
+ | node next = nodeGetValue(subject,nodeNEXT); | ||
+ | nodeSetValue(next,nodePREV,prev); | ||
+ | return nodeSetValue(prev,nodeNEXT,next); | ||
+ | } | ||
+ | |||
+ | void **nodeState(node subject,node key) { | ||
+ | return hash(itob(key?(int)listTraverse((item)subject,(item)key):(int)subject,nssBuf)); | ||
+ | } | ||
+ | |||
+ | // Clean up all the mess and 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]]]] | ||
+ | char *serialise(node); | ||
+ | void deserialise(char*); | ||
+ | int nodeInit() { | ||
+ | |||
+ | char *file = "*[[0|root]]\n*[[1000|io]];[[1001|interface]];\n*[[io]]\n*[[1002|server]];[[1003|streams]];\n*[[1004|stream]]\n*[[interface]]\n*[[1005|events]];[[1006|desktop]];\n*[[1007|window]]\n"; | ||
+ | |||
+ | /* nodeIO = nodeLoopInsert(0,0); | ||
+ | nodeINTERFACE = nodeLoopInsert(nodeIO,0); | ||
+ | nodeSERVER = nodeLoopInsert(0,0); | ||
+ | nodeSTREAMS = nodeLoopInsert(nodeSERVER,0); | ||
+ | nodeSTREAM = nodeInsert(); | ||
+ | nodeEVENTS = nodeLoopInsert(0,0); | ||
+ | nodeDESKTOP = nodeLoopInsert(nodeEVENTS,0); | ||
+ | nodeWINDOW = nodeInsert(); | ||
+ | nodeSetValue(0,nodeLOOP,nodeIO); | ||
+ | nodeSetValue(nodeIO,nodeLOOP,nodeSERVER); | ||
+ | nodeSetValue(nodeINTERFACE,nodeLOOP,nodeEVENTS); */ | ||
+ | |||
+ | deserialise(file); | ||
+ | |||
+ | nodeIO = trieGetValue("io"); logAdd("nodeIO = %d",nodeIO); | ||
+ | nodeINTERFACE = trieGetValue("interface"); logAdd("nodeINTERFACE = %d",nodeINTERFACE); | ||
+ | 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); | ||
+ | nodeWINDOW = trieGetValue("window"); logAdd("nodeWINDOW = %d",nodeWINDOW); | ||
+ | |||
+ | return EXIT_SUCCESS; | ||
+ | } | ||
+ | |||
+ | // Moves "this" to current loop item if exists then rotates loop and executes or reduces the item | ||
+ | // - THEN may not be needed since by default things should stay the same | ||
+ | // ie. a function would have to set THEN to change, so why not change loop directly itself? | ||
+ | void nodeReduce() { | ||
+ | if (this = nodeGetValue(loop = nodeTraverse(this,nodeLOOP),0)) { // this = current loop item | ||
+ | nodeSetValue(loop,0,nodeGetValue(this,nodeNEXT)); // Rotate loop | ||
+ | nodeGetValue(this,nodeCODE)?((code*)*nodeState(this,0))():nodeReduce(); // Exec or reduce item | ||
+ | } | ||
} | } |
Revision as of 23:50, 14 September 2006
// [[[[1]]]] - nodal p2p wiki daemon // This article and all its includes are licenced under LGPL // GPL: [[[[2]]]] // SRC: [[[[3]]]] // included in [[[[4]]]][[[[5]]]]
typedef int node; // node: a type for referring to nodes typedef void (code)(); // code: a type for executing functions from pointer
// Reserved nodes used by nodal reduction process (tmp) // - doesn't matter that these node indexes conflict with 128 ascii nodes // because these will not currently need anything stored in them
- define nodeLOOP 1
- define nodeTRUE 1
- define nodeNEXT 2
- define nodePREV 3
- define nodeCODE 4
// Runtime nodes node this; // this: the current node, like cwd
// stateless node nodeINTERFACE; node nodeSTREAMS;
// function ref node nodeEVENTS; node nodeIO; node nodeSERVER; node nodeDESKTOP;
// pointer to struct node nodeSTREAM; node nodeWINDOW;
// Prototypes
node nodeTraverse(node subject,node key);
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);
void **nodeGetState(node subject,node key);
int nodeInit();
void nodeExit();
void nodeReduce();
// ----------------------------------------------------------------------------------------- //
// nodeSpace.c
// - use array-of-node path? node nodeTraverse(node subject,node key) { return listTraverse((item)subject,(item)key); }
// set nodal value of node/path // - allows null key node nodeGetValue(node subject,node key) { return listGetValue(key?listTraverse((item)subject,(item)key):(item)subject); }
node nodeSetValue(node subject,node key,node value) { // todo: onChange return listSetValue(key?listTraverse((item)subject,(item)key):(item)subject, (item)value); }
// Returns a newly created node node nodeInsert() { return (node)listInsert(); }
// Returns newly created node // - this is just traverse() but with an event raised node nodeInsertKey(node subject,node key) { // todo: onInstall node i = nodeTraverse(subject,key); return i; }
// Returns the node that was removed node nodeRemoveKey(node subject,node key) { // todo: onRemove node i = nodeTraverse(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) node nodeLoopInsert(node subject,node insert) { if (insert == 0) insert = nodeInsert(); if (subject == 0) subject = insert; node next = nodeGetValue(subject,nodeNEXT); nodeSetValue(insert,nodeNEXT,next); nodeSetValue(subject,nodeNEXT,insert); nodeSetValue(insert,nodePREV,subject); return nodeSetValue(next,nodePREV,insert); }
// Returns the new loop pointer so nodeLOOP can be removed and updated node nodeLoopRemove(node subject) { node prev = nodeGetValue(subject,nodePREV); node next = nodeGetValue(subject,nodeNEXT); nodeSetValue(next,nodePREV,prev); return nodeSetValue(prev,nodeNEXT,next); }
void **nodeState(node subject,node key) { return hash(itob(key?(int)listTraverse((item)subject,(item)key):(int)subject,nssBuf)); }
// Clean up all the mess and 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]]
char *serialise(node);
void deserialise(char*);
int nodeInit() {
char *file = "*root\n*io;interface;\n*io\n*server;streams;\n*stream\n*interface\n*events;desktop;\n*window\n";
/* nodeIO = nodeLoopInsert(0,0); nodeINTERFACE = nodeLoopInsert(nodeIO,0); nodeSERVER = nodeLoopInsert(0,0); nodeSTREAMS = nodeLoopInsert(nodeSERVER,0); nodeSTREAM = nodeInsert(); nodeEVENTS = nodeLoopInsert(0,0); nodeDESKTOP = nodeLoopInsert(nodeEVENTS,0); nodeWINDOW = nodeInsert(); nodeSetValue(0,nodeLOOP,nodeIO); nodeSetValue(nodeIO,nodeLOOP,nodeSERVER); nodeSetValue(nodeINTERFACE,nodeLOOP,nodeEVENTS); */
deserialise(file);
nodeIO = trieGetValue("io"); logAdd("nodeIO = %d",nodeIO); nodeINTERFACE = trieGetValue("interface"); logAdd("nodeINTERFACE = %d",nodeINTERFACE); 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); nodeWINDOW = trieGetValue("window"); logAdd("nodeWINDOW = %d",nodeWINDOW);
return EXIT_SUCCESS; }
// Moves "this" to current loop item if exists then rotates loop and executes or reduces the item // - THEN may not be needed since by default things should stay the same // ie. a function would have to set THEN to change, so why not change loop directly itself? void nodeReduce() { if (this = nodeGetValue(loop = nodeTraverse(this,nodeLOOP),0)) { // this = current loop item nodeSetValue(loop,0,nodeGetValue(this,nodeNEXT)); // Rotate loop nodeGetValue(this,nodeCODE)?((code*)*nodeState(this,0))():nodeReduce(); // Exec or reduce item } }