262 lines · 4.3 KB · C
RawDownload
#include <u.h>#include <libc.h> #include "bt.h"#include "impl.h" static voidbtinitnode(BehaviorNode *node, short type, char *name){	assert(type >= 0 || type < BT_MAXTYPE);	memset(node, 0, sizeof(BehaviorNode));	node->type = type;	snprint(node->name, sizeof(node->name), "%s", name);} BehaviorNode*btleaf(char *name, BehaviorAction action, void *ctx){	BehaviorLeaf *leaf; 	assert(action != nil); 	leaf = mallocz(sizeof(BehaviorLeaf), 1);	if(leaf == nil)		return nil; 	setmalloctag(leaf, getcallerpc(&name)); 	btinitnode(&leaf->node, BT_LEAF, name); 	leaf->action = action;	leaf->ctx = ctx;	return (BehaviorNode*)leaf;} static intbtaddchild(BehaviorBranch *node, BehaviorNode *child){	BehaviorNode **kids; 	kids = realloc(node->children, sizeof(BehaviorNode*) * (node->childcount + 1));	if(kids == nil)		return -1; 	child->ref++; 	node->children = kids;	node->children[node->childcount++] = child;	return 0;} intbtaddbranch(BehaviorNode *node, BehaviorNode *child){	assert(node->type == BT_SEQUENCE ||			node->type == BT_PRIORITY ||			node->type == BT_PARALLEL ||			node->type == BT_DYNGUARD); 	return btaddchild((BehaviorBranch*)node, child);} static intbtbranch(BehaviorBranch *node, va_list ap){	BehaviorNode *child; 	while((child = va_arg(ap, BehaviorNode*)) != nil){		if(btaddchild(node, child) < 0)			goto fail;	} 	return 0; fail:	free(node->children);	return -1;} BehaviorNode*btsequence(char *name, ...){	va_list ap;	BehaviorBranch *branch; 	branch = mallocz(sizeof(BehaviorBranch), 1);	if(branch == nil)		return nil; 	setmalloctag(branch, getcallerpc(&name)); 	btinitnode(&branch->node, BT_SEQUENCE, name); 	va_start(ap, name); 	if(btbranch(branch, ap) < 0){		free(branch);		branch = nil;	} 	va_end(ap);	return (BehaviorNode*)branch;} BehaviorNode*btpriority(char *name, ...){	va_list ap;	BehaviorBranch *priority; 	priority = mallocz(sizeof(BehaviorBranch), 1);	if(priority == nil)		return nil; 	setmalloctag(priority, getcallerpc(&name)); 	btinitnode(&priority->node, BT_PRIORITY, name); 	va_start(ap, name); 	if(btbranch(priority, ap) < 0){		free(priority);		priority = nil;	} 	va_end(ap);	return (BehaviorNode*)priority;} BehaviorNode*btparallel(char *name, int S, int F, ...){	va_list ap;	BehaviorParallel *parallel; 	parallel = mallocz(sizeof(BehaviorParallel), 1);	if(parallel == nil)		return nil; 	setmalloctag(parallel, getcallerpc(&name)); 	btinitnode(&parallel->branch.node, BT_PARALLEL, name); 	parallel->S = S;	parallel->F = F; 	va_start(ap, F); 	if(btbranch(&parallel->branch, ap) < 0){		free(parallel);		parallel = nil;	} 	va_end(ap);	return (BehaviorNode*)parallel;} BehaviorNode*btdynguard(char *name, ...){	va_list ap;	BehaviorBranch *dynguard; 	dynguard = mallocz(sizeof(BehaviorBranch), 1);	if(dynguard == nil)		return nil; 	setmalloctag(dynguard, getcallerpc(&name)); 	btinitnode(&dynguard->node, BT_DYNGUARD, name); 	// XXX: might not work without this	// dynguard->childcurrent = -1; 	va_start(ap, name); 	if(btbranch(dynguard, ap) < 0){		free(dynguard);		dynguard = nil;	} 	va_end(ap);	return (BehaviorNode*)dynguard;	} BehaviorNode*btinvert(char *name, BehaviorNode *child){	BehaviorBranch *invert; 	invert = mallocz(sizeof(BehaviorBranch), 1);	if(invert == nil)		return nil; 	setmalloctag(invert, getcallerpc(&name)); 	btinitnode(&invert->node, BT_INVERT, name); 	if(btaddchild(invert, child) < 0){		free(invert);		invert = nil;	} 	return (BehaviorNode*)invert;} voidbtsetguard(BehaviorNode *node, BehaviorNode *guard){	if(node != nil)		node->guard = guard;} voidbtsetend(BehaviorNode *node, void (*end)(void*)){	if(node != nil)		node->end = end;} static voidbtfreetree(BehaviorNode *node){	int i;	BehaviorBranch *branch; 	if(--node->ref > 0)		return; 	if(node->guard != nil){		btfreetree(node->guard);		node->guard = nil;	} 	if(node->type != BT_LEAF){		branch = (BehaviorBranch*)node;		if(branch->children != nil){			for(i = 0; i < branch->childcount; i++){				btfreetree(branch->children[i]);				branch->children[i] = nil;			}			branch->childcount = 0;			free(branch->children);			branch->children = nil;		}	} 	free(node);} voidbtfreenode(BehaviorNode *node){	btfreetree(node);} voidbtfree(Behavior *b){	btfreetree(b->root);	free(b);}