diff --git a/hipadaba.c b/hipadaba.c index 20308d59..2b4585b7 100644 --- a/hipadaba.c +++ b/hipadaba.c @@ -20,6 +20,7 @@ static char get[] = {"get"}; static char update[] = {"update"}; static char treeChange[] = {"treeChange"}; static char dataSearch[] = {"dataSearch"}; +static char killNode[] = {"killNode"}; /*------------------------------------------------------------------------*/ pHdbDataMessage GetHdbSetMessage(pHdbMessage toTest){ if(toTest->type == set){ @@ -55,6 +56,13 @@ pHdbDataSearch GetHdbDataSearchMessage(pHdbMessage toTest){ } return NULL; } +/*-------------------------------------------------------------------------*/ +pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest){ + if(toTest->type == killNode){ + return toTest; + } + return NULL; +} /*================== internal functions ===================================*/ void DeleteCallbackChain(pHdbCallback root){ pHdbCallback current = NULL, thisEntry; @@ -106,26 +114,18 @@ void DeleteNodeData(pHdb node){ free(node); } /*------------------------------------------------------------------------*/ -static pHdbCallback CleanCallbackChain(pHdbCallback chain){ - pHdbCallback head = chain; - pHdbCallback current = chain; +static pHdbCallback CleanCallbackChain(pHdbCallback head){ + pHdbCallback current = head; pHdbCallback next; + pHdbCallback *ptr2last = &head; while(current != NULL){ if(current->killFlag == 1){ next = current->next; - if(current == head){ - head = next; - } /* * unlink */ - if(next != NULL){ - next->previous = current->previous; - } - if(current->previous != NULL){ - current->previous->next = next; - } + *ptr2last = next; /* * delete */ @@ -138,6 +138,7 @@ static pHdbCallback CleanCallbackChain(pHdbCallback chain){ */ current = next; } else { + ptr2last = ¤t->next; current = current->next; } } @@ -209,19 +210,6 @@ int CountHdbChildren(pHdb node){ } return count; } -/*-----------------------------------------------------------------------*/ -static void RemoveCallbackNode(pHdbCallback victim){ - if(victim->previous != NULL) { - victim->previous->next = victim->next; - } - if(victim->next != NULL){ - victim->next->previous = victim->previous; - } - if(victim->killFunc != NULL){ - victim->killFunc(victim->userData); - } - free(victim); -} /*----------------------------------------------------------------------*/ char *hdbTrim(char *str) { @@ -297,6 +285,7 @@ hdbValue makeHdbValue(int datatype, int length){ memset(&val,0,sizeof(hdbValue)); val.dataType = datatype; + val.doNotFree = 0; switch(datatype){ case HIPINTAR: @@ -322,63 +311,6 @@ hdbValue makeHdbValue(int datatype, int length){ } return val; } -/*------------------------------------------------------------------------*/ -hdbValue makeHdbData(int datatype, int length, void *data){ - hdbValue val; - - memset(&val,0,sizeof(hdbValue)); - val.dataType = datatype; - - switch(datatype){ - case HIPINT: - if(data != NULL){ - memcpy(&val.v.intValue,data,sizeof(int)); - } - break; - case HIPFLOAT: - if(data != NULL){ - memcpy(&val.v.doubleValue,data,sizeof(double)); - } - break; - case HIPINTAR: - case HIPINTVARAR: - val.arrayLength = length; - val.v.intArray = malloc(length*sizeof(int)); - if(val.v.intArray != NULL){ - memset(val.v.intArray,0,length*sizeof(int)); - } - if(data != NULL){ - memcpy(val.v.intArray,data,length*sizeof(int)); - } - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - val.arrayLength = length; - val.v.floatArray = malloc(length*sizeof(double)); - if(val.v.floatArray != NULL){ - memset(val.v.floatArray,0,length*sizeof(double)); - } - if(data != NULL){ - memcpy(val.v.floatArray,data,length*sizeof(double)); - } - break; - case HIPTEXT: - if(data != NULL){ - val.v.text = strdup((char *)data); - } else { - val.v.text = strdup("UNKNOWN"); - } - val.arrayLength = strlen(val.v.text); - break; - case HIPOBJ: - val.v.obj = data; - break; - case HIPFUNC: - val.v.obj = data; - break; - } - return val; -} /*-------------------------------------------------------------------------*/ hdbValue MakeHdbInt(int initValue){ hdbValue result; @@ -402,7 +334,7 @@ hdbValue MakeHdbText(char *initText){ hdbValue result; result.dataType = HIPTEXT; - result.v.text = strdup(initText); + result.v.text = initText; /* no strdup here ! */ result.arrayLength = strlen(initText); return result; } @@ -425,6 +357,22 @@ hdbValue MakeHdbFloatArray(int length, double *data){ return result; } /*-------------------------------------------------------------------------*/ +hdbValue MakeHdbFunc(voidFunc *func){ + hdbValue result; + + result.dataType = HIPFUNC; + result.v.func = func; + return result; +} +/*-------------------------------------------------------------------------*/ +hdbValue MakeHdbObj(void *obj){ + hdbValue result; + + result.dataType = HIPOBJ; + result.v.obj = obj; + return result; +} +/*-------------------------------------------------------------------------*/ void ReleaseHdbValue(hdbValue *v){ if(v->doNotFree == 1){ @@ -516,13 +464,19 @@ int compareHdbValue(hdbValue v1, hdbValue v2){ return 1; break; case HIPOBJ: - case HIPFUNC: if(v2.v.obj == v1.v.obj) { return 1; } else { return 0; } break; + case HIPFUNC: + if(v2.v.func == v1.v.func) { + return 1; + } else { + return 0; + } + break; default: assert(0); break; @@ -561,9 +515,11 @@ int getHdbValueLength(hdbValue v){ length = strlen(v.v.text); break; case HIPOBJ: - case HIPFUNC: length = sizeof(void *); break; + case HIPFUNC: + length = sizeof(voidFunc *); + break; } return length; } @@ -639,11 +595,15 @@ void AddHipadabaChild(pHdb parent, pHdb child, void *callData){ /*--------------------------------------------------------------------------*/ void DeleteHipadabaNode(pHdb node, void *callData){ pHdb current = NULL, tmp = NULL; + hdbMessage killNodeMsg; if(node == NULL){ return; } + killNodeMsg.type = killNode; + InvokeCallbackChain(node, &killNodeMsg); + RemoveHdbNodeFromParent(node, callData); DeleteNodeData(node); @@ -765,35 +725,28 @@ void AppendHipadabaCallback(pHdb node, pHdbCallback newCB){ assert(node); current = node->callBackChain; + newCB->next = NULL; if(current == NULL){ node->callBackChain = newCB; return; } - if(current != NULL){ - while(current->next != NULL){ - current = (pHdbCallback)current->next; - } - current->next= newCB; - newCB->previous = current; + while(current->next != NULL){ + current = (pHdbCallback)current->next; } + current->next = newCB; } /*---------------------------------------------------------------------------*/ void PrependHipadabaCallback(pHdb node,pHdbCallback newCB){ assert(node != NULL); newCB->next = node->callBackChain; - if(node->callBackChain != NULL){ - node->callBackChain->previous = newCB; - } node->callBackChain = newCB; } /*----------------------------------------------------------------------------*/ -void *FindHdbCallbackData(pHdb node, hdbCallbackFunction func, - void *userPtr){ +void *FindHdbCallbackData(pHdb node, void *userPtr){ hdbDataSearch dsm; dsm.type = dataSearch; - dsm.testFunc = func; dsm.testPtr = userPtr; dsm.result = NULL; @@ -887,9 +840,11 @@ int copyHdbValue(hdbValue *source, hdbValue *target){ } break; case HIPOBJ: - case HIPFUNC: target->v.obj = source->v.obj; break; + case HIPFUNC: + target->v.func = source->v.func; + break; default: /* * unknown data type @@ -903,21 +858,16 @@ int copyHdbValue(hdbValue *source, hdbValue *target){ static int SendDataMessage(pHdb node, char *type, hdbValue v, void *callData){ hdbDataMessage dataMes; - - if(strstr(type,"set") != NULL){ - dataMes.type = set; - } else if(strstr(type,"get") != NULL){ - dataMes.type = get; - } else if(strstr(type,"update") != NULL){ - dataMes.type = update; - } + + assert(type == set || type == get || type == update); + dataMes.type = type; dataMes.v = &v; dataMes.callData = callData; return InvokeCallbackChain(node, (pHdbMessage)&dataMes); } /*----------------------------------------------------------------------------*/ int SetHipadabaPar(pHdb node, hdbValue v, void *callData){ - return SendDataMessage(node, set, v,callData); + return SendDataMessage(node, set, v,callData); } /*-----------------------------------------------------------------------------*/ int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData){ @@ -939,6 +889,7 @@ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){ int status; v->dataType = node->value.dataType; + v->doNotFree = 0; v->v.text = NULL; /* this sets all pointers in the union to NULL */ status = SendDataMessage(node, get, *v,callData); @@ -960,103 +911,6 @@ static int calcDataLength(pHdb node, int testLength){ } return length; } -/*--------------------------------------------------------------------------*/ -int SetHdbPar(pHdb node, int dataType, void *data, int length, - void *callData){ - int status; - hdbValue v; - - if(node->value.dataType == HIPNONE){ - return 1; - } - - if(dataType != node->value.dataType){ - return HDBTYPEMISMATCH; - } - if(length != calcDataLength(node,length)){ - return HDBLENGTHMISMATCH; - } - - v = makeHdbData(dataType, length, data); - status = SetHipadabaPar(node, v, callData); - ReleaseHdbValue(&v); - return status; -} -/*--------------------------------------------------------------------------*/ -int UpdateHdbPar(pHdb node, int dataType, void *data, int length, - void *callData){ - int status; - hdbValue v; - - if(node->value.dataType == HIPNONE){ - return 1; - } - - if(dataType != node->value.dataType){ - return HDBTYPEMISMATCH; - } - if(length != calcDataLength(node,length)){ - return HDBLENGTHMISMATCH; - } - - v = makeHdbData(dataType,length,data); - status = UpdateHipadabaPar(node,v,callData); - ReleaseHdbValue(&v); - return status; -} -/*-----------------------------------------------------------------------------*/ -int GetHdbPar(pHdb node, int dataType, void *data, int length, - void *callData){ - int status, toCopy; - hdbValue v; - - if(dataType != node->value.dataType){ - return HDBTYPEMISMATCH; - } - - if(length != calcDataLength(node,length)){ - return HDBLENGTHMISMATCH; - } - - status = GetHipadabaPar(node, &v, callData); - if(status != 1 ){ - return status; - } - switch(dataType){ - case HIPNONE: - break; - case HIPINT: - memcpy(data,&node->value.v.intValue,sizeof(int)); - break; - case HIPFLOAT: - memcpy(data,&node->value.v.doubleValue,sizeof(double)); - break; - case HIPINTAR: - case HIPINTVARAR: - memcpy(data,node->value.v.intArray, - node->value.arrayLength*sizeof(int)); - break; - case HIPTEXT: - toCopy = strlen(node->value.v.text); - if(toCopy > length){ - toCopy = length; - } - memcpy(data,&node->value.v.text, toCopy); - break; - case HIPFLOATAR: - case HIPFLOATVARAR: - memcpy(data,node->value.v.floatArray, - node->value.arrayLength*sizeof(double)); - break; - case HIPOBJ: - memcpy(data,&node->value.v.obj,sizeof(void *)); - break; - default: - assert(0); - break; - } - return 1; -} /*============================= Property Functions ==========================*/ void SetHdbProperty(pHdb node, char *key, char *value){ if(node != NULL && key != NULL && node->properties != NULL){ @@ -1076,6 +930,14 @@ int GetHdbProperty(pHdb node, char *key, char *value, int len){ } } /*---------------------------------------------------------------------------*/ +char *GetHdbProp(pHdb node, char *key){ + if(node != NULL && node->properties != NULL){ + return StringDictGetShort(node->properties,key); + } else { + return NULL; + } +} +/*---------------------------------------------------------------------------*/ void InitHdbPropertySearch(pHdb node){ if(node != NULL && node->properties != NULL){ StringDictKillScan(node->properties); diff --git a/hipadaba.h b/hipadaba.h index 3ec100ee..b4ec26f5 100644 --- a/hipadaba.h +++ b/hipadaba.h @@ -1,4 +1,4 @@ -/** +/** @file * Hipadaba is a hierarchical database of parameters. Parameters can be of * various types. What happens when a parameter is being set, updated or read * is largely determined through callbacks which can be registered on @@ -46,16 +46,19 @@ #define HDBTYPEMISMATCH -7701 #define HDBLENGTHMISMATCH -7702 /*===================== structure definitions ===================================*/ +typedef void voidFunc(void); + typedef struct __hdbValue { int dataType; int arrayLength; int doNotFree; union __value { - int intValue; + int intValue; double doubleValue; char *text; int *intArray; double *floatArray; + voidFunc *func; void *obj; }v; }hdbValue; @@ -90,7 +93,13 @@ typedef struct { char *type; void *callData; }hdbTreeChangeMessage, *pHdbTreeChangeMessage; -/*-------------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------------*/ +typedef struct { + char *type; + void *testPtr; + void *result; +}hdbDataSearch, *pHdbDataSearch; +/*-------------------------------------------------------------------------------*/ typedef hdbCallbackReturn (*hdbCallbackFunction)(pHdb currentNode, void *userData, pHdbMessage message); @@ -105,13 +114,6 @@ typedef struct __hdbcallback { struct __hdbcallback *next; struct __hdbcallback *previous; }hdbCallback, *pHdbCallback; -/*--------------- another message: must be here for seqeunce --------------------*/ -typedef struct { - char *type; - hdbCallbackFunction testFunc; - void *testPtr; - void *result; -}hdbDataSearch, *pHdbDataSearch; /*============= Message Test Functions ==========================================*/ /** * Test a message if it is a set message @@ -146,17 +148,22 @@ pHdbTreeChangeMessage GetHdbTreeChangeMessage(pHdbMessage toTest); * pointer if it is. */ pHdbDataSearch GetHdbDataSearchMessage(pHdbMessage toTest); -/*======================== Function protoypes: hdbData ========================*/ -hdbValue makeHdbValue(int datatype, int length); /** - * make a hdbValue and initailize it with the data in the void - * pointer. Do not initialise when data = NULL. - * @param dataType The datatype of the hdbValue - * @param The array length of the hdbValue - * @param data Initialisation data for hdbValue + * Test a message if it is a kill node message + * @param toTest The message to test. + * @return NULL if the message is no kill node message or a message + * pointer if it is. + */ +pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest); +/*======================== Function protoypes: hdbData ========================*/ +/** + * make a hdbValue with the given datatype and length + * Do not initialise + * @param datatype The datatype of the hdbValue + * @param length The array length of the hdbValue * @return a suitably defined hdbValue */ -hdbValue makeHdbData(int datatype, int length, void *data); +hdbValue makeHdbValue(int datatype, int length); /** * wrap an integer as an hdbValue * @param initValue the initial value of the int @@ -198,6 +205,18 @@ hdbValue MakeHdbIntArray(int length, int *data); * @return: A properly initialized hdbValue structure */ hdbValue MakeHdbFloatArray(int length, double *data); +/** + * wrap a function as an hdbValue + * @param func the function + * @return: A properly initialized hdbValue structure + */ +hdbValue MakeHdbFunc(voidFunc *func); +/** + * wrap an object as an hdbValue + * @param obj the object + * @return: A properly initialized hdbValue structure + */ +hdbValue MakeHdbObj(void *obj); /** * release any dynamic memory associated with v * @param v The hdbValue to check for dynamic memory allocation to be @@ -238,6 +257,7 @@ int getHdbValueLength(hdbValue v); * make a new hipadaba node * @param name The name of the new node * @param datatype The datatype of the new node + * @param length the array length * @return a new node or NULL when out of memory */ pHdb MakeHipadabaNode(char *name, int datatype, int length); @@ -256,7 +276,7 @@ void DeleteNodeData(pHdb node); /** * delete a hipadaba node and all its children. Then invoke the tree * change callback to notify listeners. - * @parma node The node to delete + * @param node The node to delete * @param callData User data for the tree change callback */ void DeleteHipadabaNode(pHdb node, void *callData); @@ -282,7 +302,7 @@ pHdb GetHipadabaNode(pHdb root, char *path); char *GetHipadabaPath(pHdb node); /** * removes a node from the parents child list. - * @node the node to remove + * @param node the node to remove * @param callData User data for the tree change callback */ void RemoveHdbNodeFromParent(pHdb node, void *callData); @@ -307,33 +327,27 @@ pHdbCallback MakeHipadabaCallback(hdbCallbackFunction func, /** * add a callback at the end of the callback chain * @param node The node to which to append the callback - * @param type the type of the callback to append * @param newCB The callback to append */ void AppendHipadabaCallback(pHdb node,pHdbCallback newCB); /** * add a callback at the head of the callback chain * @param node The node to which to append the callback - * @param type the type of the callback to append * @param newCB The callback prepend */ void PrependHipadabaCallback(pHdb node,pHdbCallback newCB); /** * find the callback data * @param node the node from where callbacks have to be searched - * @param func the function registered with the searched callback - * @param userPtr A pointer to some user data whih the callback + * @param userPtr A pointer to some user data which the callback * uses to determine if it is the right one. * @return the found callback user data or NULL on failure */ -void *FindHdbCallbackData(pHdb node,hdbCallbackFunction func, - void *userPtr); +void *FindHdbCallbackData(pHdb node, void *userPtr); /** * invoke a callback chain. - * @param root The callback chain to invoke - * @param node The node reposnible for this callback chain - * @param callData Some data belonging to the callback - * @param v The new value for this callback + * @param node The node reponsible for this callback chain + * @param message the message to send * @return 1 on success, 0 on failure */ int InvokeCallbackChain(pHdb node, pHdbMessage message); @@ -384,42 +398,6 @@ int NotifyHipadabaPar(pHdb node,void *callData); * @return 0 on failure, 1 on success */ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData); -/** - * Set a hipadaba parameter. This is an external set for a parameter. It may cause - * motors to start driving etc. - * @param node The node for which to set the parameter - * param dataType The datatype the value ought to have - * @param data A pointer to the data to set. - * @param length The length of data - * @param callData Additonal context data to be passed to the callback functions - * @return 0 on failure, a negative error code on failure - */ -int SetHdbPar(pHdb node, int dataType, void *data, int length, - void *callData); -/** - * Updates a hipadaba parameter. This does not cause an active parameter to - * start driving but invokes all notifications which may be registered on - * this parameter. - * @param node The node for which to set the parameter - * param dataType The datatype the value ought to have - * @param data A pointer to the data to set. - * @param length The length of data - * @param callData Additonal context data to be passed to the callback functions - * @return 0 on failure, a negative error code on failure - */ -int UpdateHdbPar(pHdb node, int dataType, void *data, int length, - void *callData); -/** - * Read a hipadaba parameter - * @param node The node for which to read the parameter - * @param dataType The expected type of the data - * @param data A pointer to which data will be copied - * @param length The length of data. - * @param callData Additonal context data to be passed to the callback functions - * @return 0 on failure, a negative error code on failures. - */ -int GetHdbPar(pHdb node, int dataType, void *data, int length, - void *callData); /*================================ Property Interface ==============================================*/ /** * set a property @@ -437,6 +415,14 @@ int GetHdbPar(pHdb node, int dataType, void *data, int length, * @return 0 on failure, 1 on success */ int GetHdbProperty(pHdb node, char *key, char *value, int len); + /** + * get the value of a property + * @param node The node to get the property from + * @param key The properties key + * @return the property or NULL on failure. Warning: the string is + * only valid as long as the property has not changed + */ + char *GetHdbProp(pHdb node, char *key); /** * initialize a property scan on this node * @param node The node for which to scan properties