Difference between revisions of "NodeSpace.h"

From Organic Design wiki
m
m
 
(151 intermediate revisions by the same user not shown)
Line 1: Line 1:
 +
{{legacy}}
 +
<source lang="c">
 +
// [[[[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 LGPL
// GPL: http://www.gnu.org/copyleft/lesser.html
+
// GPL: [[[[http://www.gnu.org/copyleft/lesser.html]]]]
// SRC: http://www.organicdesign.co.nz/nodeSpace.c
+
// 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]]]]
  
// Reserved nodes (tmp)
+
// node: a type for referring to nodes
#define nodeROOT 0
+
typedef int node;
#define nodeFALSE 0
 
#define nodeCURRENT 1
 
#define nodeTRUE 1
 
#define nodeNEXT 2
 
#define nodeCODE 3
 
#define nodeTHEN 4
 
  
// these will have content, so must start after 128 ascii-list-items
+
// code is a variable of type pointer-to-function
#define nodeNETWORK 128
+
typedef void (codeType)();
#define nodeDESKTOP 129
+
codeType *code;
#define nodeSTREAMINFO 130
 
  
typedef int node;      // node: a type for referring to nodes
+
// constants defined in [[[[peerd.c]]]]
typedef void (*code)(); // code: a type for referring to functions
+
// - nodal constants
node this;              // this: the current node, like cwd
+
// - this and parent
  
// - path is array-of-node
+
// stateless
node nodeTraverse(node subject,node key) {
+
node nodeSESSION;
// select node wco selNode
+
node nodeSTREAMS;
return subject;
+
 
}
+
// 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
 
// set nodal value of node/path
// - allows null key
 
 
node nodeGetValue(node subject,node key) {
 
node nodeGetValue(node subject,node key) {
return listGetValue(key?listTraverse((item)subject,(item)key):(item)subject);
+
// todo: if subject/nodeGETVAL...
 +
return listGetValue(listTraverse(subject,key));
 
}
 
}
  
 
node nodeSetValue(node subject,node key,node value) {
 
node nodeSetValue(node subject,node key,node value) {
 
// todo: onChange
 
// todo: onChange
return listSetValue(key?listTraverse((item)subject,(item)key):(item)subject, (item)value);
+
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) {
 
node nodeInsertKey(node subject,node key) {
// todo: onInstall
+
// todo: hook in nodeSTART
node instance;
+
return listTraverse(subject,key);
return instance;
 
 
}
 
}
  
void nodeRemoveKey(node subject,node key) {
+
// Returns the node that was removed
// todo: onRemove
+
node nodeRemoveKey(node subject,node key) {
 +
// todo: hook in nodeSTOP
 +
node i = listTraverse(subject,key);
 +
// todo: delete
 +
return i;
 
}
 
}
  
void nodeLoopInsert(node subject,node loop) {
+
// Returns the inserted node as the new loop pointer
// add object to the passed loop (do error if not a loop)
+
// - 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;
 
}
 
}
  
void nodeLoopRemove(node subject) {
+
// Removes a node from the subject's [[[[loop]]]]
// remove subject from loop if its currently in one
+
// - 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;
 
}
 
}
  
// State is a pointer to a locally meaningful item which is associated with a node
+
// Rotates the subject node's [[[[loop]]]] and returning the last [[[[focus]]]]
// - doesn't need separate get/set since pointer-based, but keeps it more lang-independent
+
node nodeLoopRotate(node subject) {
void *nodeGetState(node subject,node key) {
+
node focus = nodeGetValue(subject,0);
itob(key?(int)listTraverse((item)subject,(item)key):(int)subject,nssBuf);
+
if (focus) nodeSetValue(subject,0,nodeGetValue(focus,nodeNEXT));
return *hash(nssBuf);
+
return focus;
 
}
 
}
  
void *nodeSetState(node subject,node key,void *state) {
+
// not used yet - use array-of-node path?
itob(key?(int)listTraverse((item)subject,(item)key):(int)subject,nssBuf);
+
node nodeTraverse(node subject,node *path) {
return *hash(nssBuf) = state;
+
}
 +
 
 +
// 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);
 +
 
 
}
 
}
  
// - Consumes quanta of execution
+
// Moves "this" to node's [[[[focus]]]] if exists then rotates [[[[loop]]]] and executes/reduces the focus item
// - Creates History from change events
+
void nodeReduce() {
// - Builds, declares and executes functionality
+
grandpa = parent;
// - Should reduction handle cyles (current-cycle etc), or a separate root-thread
+
if (this = nodeLoopRotate(parent = this)) {      // Move "this" to the [[[[focus]]]] in the node's loop and rotate
// - returns false if no more to reduce
+
nodeSetValue(this,nodePARENT,parent);         // Update the [[[[parent]]]] association
int nodeReduce(node subject) {
+
if (code = *nodeState(this,nodeCODE)) code(); // [[[[nodeCODE]]]] value is a pointer-index, execute as function-reference if non-zero
node cur;
+
}
if ((cur = nodeGetValue(subject, nodeCURRENT)) == nodeFALSE) return 0; // return if no CURRENT node
 
nodeSetValue(subject, nodeCURRENT, nodeGetValue(cur, nodeNEXT)); // test NEXT first?
 
if (nodeGetValue(cur, nodeCODE) == nodeTRUE) {
 
((code)nodeGetState(cur,nodeROOT))(); // execute code-ref returned in state
 
// Later this must declare and build if no function-reference
 
// replace self in loop with n.THEN if non-zero
 
} else nodeReduce(cur);
 
return 1;
 
 
}
 
}
 +
</source>

Latest revision as of 15:20, 17 August 2022

Legacy.svg Legacy: This article describes a concept that has been superseded in the course of ongoing development on the Organic Design wiki. Please do not develop this any further or base work on this concept, now this page is for historic record only.
// [[[[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
		}
	}