- Changes to Hipadaba - Added project to histogram memory code - Started regression testing code - Added hill climbing as optimization method to optimise
821 lines
23 KiB
C
821 lines
23 KiB
C
/*-------------------------------------------------------------------------
|
|
The hierarchical parameter database code. For more information, see
|
|
hipadaba.h
|
|
|
|
copyright: GPL
|
|
|
|
Mark Koennecke, June 2006
|
|
---------------------------------------------------------------------------*/
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <ctype.h>
|
|
#include "hipadaba.h"
|
|
|
|
#define ABS(x) (x < 0 ? -(x) : (x))
|
|
#define HDBMAGICK 77119900
|
|
/*================== internal functions ===================================*/
|
|
void DeleteCallbackChain(pHdbCallback root){
|
|
pHdbCallback current = NULL, thisEntry;
|
|
|
|
current = root;
|
|
while(current != NULL){
|
|
if(current->killFunc != NULL){
|
|
current->killFunc(current->userData);
|
|
}
|
|
thisEntry = current;
|
|
current = (pHdbCallback)current->next;
|
|
free(thisEntry);
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static void DeleteNodeData(pHdb node){
|
|
pHdb tmp = NULL;
|
|
|
|
if(node == NULL){
|
|
return;
|
|
}
|
|
DeleteCallbackChain(node->writeCallbacks);
|
|
DeleteCallbackChain(node->updateCallbacks);
|
|
DeleteCallbackChain(node->readCallbacks);
|
|
|
|
if(node->name != NULL){
|
|
free(node->name);
|
|
}
|
|
ReleaseHdbValue(&node->value);
|
|
node->magic = 000000;
|
|
|
|
while(node->child != NULL){
|
|
tmp = node->child;
|
|
node->child = node->child->next;
|
|
DeleteNodeData(tmp);
|
|
}
|
|
free(node);
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
void RemoveHdbNodeFromParent(pHdb node){
|
|
pHdb parent = NULL;
|
|
pHdb current = NULL;
|
|
|
|
parent = node->mama;
|
|
if(parent != NULL){
|
|
if(parent->child == node){
|
|
parent->child = node->next;
|
|
return;
|
|
}
|
|
current = parent->child;
|
|
while(current->next != node){
|
|
current = current->next;
|
|
}
|
|
current->next = current->next->next;
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
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);
|
|
}
|
|
/*-----------------------------------------------------------------------
|
|
* This code is ugly: the problem is fixing up the start of the chain.
|
|
* Think about it and improve
|
|
* ----------------------------------------------------------------------*/
|
|
static pHdbCallback DeleteForID(pHdbCallback root, int id){
|
|
pHdbCallback current = root;
|
|
pHdbCallback tmp = NULL;
|
|
pHdbCallback result = NULL;
|
|
|
|
if(root == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* delete at the start of the chain
|
|
*/
|
|
result = root;
|
|
while(result->id == id){
|
|
tmp = result;
|
|
result = result->next;
|
|
RemoveCallbackNode(tmp);
|
|
if(result == NULL){
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* delete nodes in the middle of the chain
|
|
*/
|
|
current = result;
|
|
while(current != NULL){
|
|
if(current->id == id){
|
|
tmp = current;
|
|
current = (pHdbCallback)current->next;
|
|
RemoveCallbackNode(tmp);
|
|
} else {
|
|
current = (pHdbCallback)current->next;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
/*-----------------------------------------------------------------------*/
|
|
static pHdbCallback DeleteForInternalID(pHdbCallback root, int id){
|
|
pHdbCallback current = root;
|
|
pHdbCallback tmp = NULL;
|
|
pHdbCallback result = NULL;
|
|
|
|
if(root == NULL){
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* delete at the start of the chain
|
|
*/
|
|
result = root;
|
|
while(result->internalID == id){
|
|
tmp = result;
|
|
result = result->next;
|
|
if(tmp->killFunc != NULL){
|
|
tmp->killFunc(tmp->userData);
|
|
}
|
|
free(tmp);
|
|
if(result == NULL){
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* delete nodes in the middle of the chain
|
|
*/
|
|
current = result;
|
|
while(current != NULL){
|
|
if(current->internalID == id){
|
|
if(current->next != NULL){
|
|
current->next->previous = current->previous;
|
|
}
|
|
if(current->previous != NULL){
|
|
current->previous->next = current->next;
|
|
}
|
|
tmp = current;
|
|
current = (pHdbCallback)current->next;
|
|
if(tmp->killFunc != NULL){
|
|
tmp->killFunc(tmp->userData);
|
|
}
|
|
free(tmp);
|
|
} else {
|
|
current = (pHdbCallback)current->next;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
static int InvokeCallbackChain(pHdbCallback root, pHdb node,
|
|
void *callData, hdbValue v){
|
|
pHdbCallback current = root;
|
|
int status;
|
|
|
|
while(current != NULL){
|
|
status = current->userCallback(current->userData,callData,
|
|
node,v);
|
|
if(status != 1){
|
|
return status;
|
|
}
|
|
current = current->next;
|
|
}
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------*/
|
|
char *hdbTrim(char *str)
|
|
{
|
|
char *ibuf = str, *obuf = str;
|
|
int i = 0, cnt = 0;
|
|
|
|
/*
|
|
** Trap NULL
|
|
*/
|
|
|
|
if (str)
|
|
{
|
|
/*
|
|
** Remove leading spaces (from RMLEAD.C)
|
|
*/
|
|
|
|
for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf)
|
|
;
|
|
if (str != ibuf)
|
|
memmove(str, ibuf, ibuf - str);
|
|
|
|
/*
|
|
** Collapse embedded spaces (from LV1WS.C)
|
|
*/
|
|
|
|
while (*ibuf)
|
|
{
|
|
if (isspace(*ibuf) && cnt)
|
|
ibuf++;
|
|
else
|
|
{
|
|
if (!isspace(*ibuf))
|
|
cnt = 0;
|
|
else
|
|
{
|
|
*ibuf = ' ';
|
|
cnt = 1;
|
|
}
|
|
obuf[i++] = *ibuf++;
|
|
}
|
|
}
|
|
obuf[i] = '\0';
|
|
|
|
/*
|
|
** Remove trailing spaces (from RMTRAIL.C)
|
|
*/
|
|
|
|
while (--i >= 0)
|
|
{
|
|
if (!isspace(obuf[i]))
|
|
break;
|
|
}
|
|
obuf[++i] = '\0';
|
|
}
|
|
return str;
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
static pHdb locateChild(pHdb root, char *name){
|
|
pHdb current = NULL;
|
|
|
|
current = root->child;
|
|
while(current != NULL){
|
|
if(strcmp(current->name,name) == 0){
|
|
return current;
|
|
}
|
|
current = current->next;
|
|
}
|
|
return NULL;
|
|
}
|
|
/*================= data functions ========================================*/
|
|
hdbValue makeHdbValue(int datatype, int length){
|
|
hdbValue val;
|
|
|
|
memset(&val,0,sizeof(hdbValue));
|
|
val.dataType = datatype;
|
|
|
|
switch(datatype){
|
|
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));
|
|
}
|
|
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));
|
|
}
|
|
break;
|
|
case HIPTEXT:
|
|
val.v.text = strdup("UNKNOWN");
|
|
val.arrayLength = length;
|
|
break;
|
|
}
|
|
return val;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
hdbValue MakeHdbInt(int initValue){
|
|
hdbValue result;
|
|
|
|
result.dataType = HIPINT;
|
|
result.v.intValue = initValue;
|
|
return result;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
hdbValue MakeHdbFloat(double initValue){
|
|
hdbValue result;
|
|
|
|
result.dataType = HIPFLOAT;
|
|
result.v.doubleValue = initValue;
|
|
return result;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
hdbValue MakeHdbText(char *initText){
|
|
hdbValue result;
|
|
|
|
result.dataType = HIPTEXT;
|
|
result.v.text = initText;
|
|
result.arrayLength = strlen(initText);
|
|
return result;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
hdbValue MakeHdbIntArray(int length, int *data){
|
|
hdbValue result;
|
|
|
|
result.dataType = HIPINTAR;
|
|
result.arrayLength = length;
|
|
result.v.intArray = data;
|
|
return result;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
hdbValue MakeHdbFloatArrray(int length, double *data){
|
|
hdbValue result;
|
|
|
|
result.dataType = HIPFLOATAR;
|
|
result.arrayLength = length;
|
|
result.v.floatArray = data;
|
|
return result;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
void ReleaseHdbValue(hdbValue *v){
|
|
switch(v->dataType){
|
|
case HIPTEXT:
|
|
if(v->v.text != NULL){
|
|
free(v->v.text);
|
|
}
|
|
break;
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
if(v->v.intArray != NULL){
|
|
free(v->v.intArray);
|
|
}
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
if(v->v.floatArray != NULL){
|
|
free(v->v.floatArray);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
/*------------------------------------------------------------------------*/
|
|
int compareHdbValue(hdbValue v1, hdbValue v2){
|
|
int i;
|
|
|
|
if(v1.dataType != v2.dataType){
|
|
return 0;
|
|
}
|
|
switch(v1.dataType){
|
|
case HIPNONE:
|
|
return 0;
|
|
break;
|
|
case HIPINT:
|
|
if(v1.v.intValue == v2.v.intValue){
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
break;
|
|
case HIPFLOAT:
|
|
if(ABS(v1.v.doubleValue - v2.v.doubleValue) < .01){
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
break;
|
|
case HIPTEXT:
|
|
if(strcmp(v1.v.text,v2.v.text) == 0){
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
break;
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
if(v1.arrayLength != v2.arrayLength){
|
|
return 0;
|
|
}
|
|
for(i = 0; i < v1.arrayLength; i++){
|
|
if(v1.v.intArray[i] != v2.v.intArray[i]){
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
if(v1.arrayLength != v2.arrayLength){
|
|
return 0;
|
|
}
|
|
for(i = 0; i < v1.arrayLength; i++){
|
|
if(ABS(v1.v.floatArray[i] - v2.v.floatArray[i]) > .01){
|
|
return 0;
|
|
}
|
|
}
|
|
return 1;
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
int cloneHdbValue(hdbValue *source, hdbValue *clone){
|
|
|
|
memset(clone,0,sizeof(hdbValue));
|
|
clone->dataType = source->dataType;
|
|
return copyHdbValue(source, clone);
|
|
}
|
|
/*================= node functions ========================================*/
|
|
pHdb MakeHipadabaNode(char *name, int datatype, int length){
|
|
pHdb pNew = NULL;
|
|
|
|
pNew = malloc(sizeof(Hdb));
|
|
if(pNew == NULL){
|
|
return NULL;
|
|
}
|
|
memset(pNew,0,sizeof(Hdb));
|
|
pNew->magic = HDBMAGICK;
|
|
pNew->name = strdup(name);
|
|
pNew->value.dataType = datatype;
|
|
switch(datatype){
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
pNew->value.arrayLength = length;
|
|
pNew->value.v.intArray = malloc(length*sizeof(int));
|
|
if(pNew->value.v.intArray == NULL){
|
|
return NULL;
|
|
}
|
|
memset(pNew->value.v.intArray,0,length*sizeof(int));
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
pNew->value.arrayLength = length;
|
|
pNew->value.v.floatArray = malloc(length*sizeof(double));
|
|
if(pNew->value.v.floatArray == NULL){
|
|
return NULL;
|
|
}
|
|
memset(pNew->value.v.floatArray,0,length*sizeof(double));
|
|
break;
|
|
case HIPTEXT:
|
|
pNew->value.arrayLength = length;
|
|
pNew->value.v.text = strdup("UNKNOWN");
|
|
break;
|
|
}
|
|
return pNew;
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
void AddHipadabaChild(pHdb parent, pHdb child){
|
|
pHdb current = NULL, prev = NULL;
|
|
|
|
assert(parent != NULL);
|
|
if(child == NULL){
|
|
return;
|
|
}
|
|
|
|
current = parent->child;
|
|
child->mama = parent;
|
|
if(current == NULL){
|
|
parent->child = child;
|
|
child->next = NULL;
|
|
} else {
|
|
/*
|
|
* step to end of child chain
|
|
*/
|
|
while(current != NULL){
|
|
prev = current;
|
|
current = current->next;
|
|
}
|
|
child->next = NULL;
|
|
prev->next = child;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
void DeleteHipadabaNode(pHdb node){
|
|
pHdb current = NULL, tmp = NULL;
|
|
|
|
if(node == NULL){
|
|
return;
|
|
}
|
|
|
|
RemoveHdbNodeFromParent(node);
|
|
|
|
DeleteNodeData(node);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int isHdbNodeValid(pHdb node){
|
|
if(node == NULL){
|
|
return 0;
|
|
}
|
|
if(node->magic == HDBMAGICK){
|
|
return 1;
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
pHdb GetHipadabaNode(pHdb root, char *puth){
|
|
pHdb resultNode = NULL;
|
|
char *separator = NULL;
|
|
char *path = NULL, *pathData;
|
|
|
|
/*
|
|
* I need to make a copy in order to get the path in writable memory.
|
|
* Otherwise we SEGFAULT in hdbTrim when this function is called with
|
|
* a string constant in puth
|
|
*/
|
|
pathData = strdup(puth);
|
|
path = pathData;
|
|
if(path == NULL){
|
|
return NULL;
|
|
}
|
|
path = hdbTrim(path);
|
|
|
|
if(strcmp(path,"/") == 0 || strlen(path) == 0){
|
|
free(pathData);
|
|
return root;
|
|
}
|
|
|
|
if(path[0] == '/'){
|
|
path++;
|
|
}
|
|
|
|
separator = strchr(path,'/');
|
|
if(separator == NULL){
|
|
resultNode = locateChild(root,path);
|
|
free(pathData);
|
|
return resultNode;
|
|
} else {
|
|
*separator = '\0';
|
|
resultNode = locateChild(root, path);
|
|
if(resultNode == NULL){
|
|
free(pathData);
|
|
return NULL;
|
|
} else {
|
|
separator++;
|
|
resultNode = GetHipadabaNode(resultNode,separator);
|
|
free(pathData);
|
|
return resultNode;
|
|
}
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
char *GetHipadabaPath(pHdb node){
|
|
pHdb nodeStack[64];
|
|
int depth = 0, length = 0, i;
|
|
pHdb current = NULL;
|
|
char *pPtr = NULL;
|
|
|
|
/**
|
|
* build a nodestack and find out required string length for path
|
|
*/
|
|
current = node;
|
|
while(current != NULL){
|
|
length += strlen(current->name) + 1;
|
|
nodeStack[depth] = current;
|
|
depth++;
|
|
assert(depth < 64);
|
|
current = current->mama;
|
|
}
|
|
|
|
pPtr = malloc(length*sizeof(char));
|
|
if(pPtr == NULL){
|
|
return NULL;
|
|
}
|
|
memset(pPtr,0,length*sizeof(char));
|
|
|
|
/*
|
|
* we wish to decremement by one because above loop
|
|
* increments one to many and we wish to ignore the
|
|
* root node
|
|
*/
|
|
for(i = depth - 2; i >= 0; i--){
|
|
strcat(pPtr,"/");
|
|
strcat(pPtr,nodeStack[i]->name);
|
|
}
|
|
return pPtr;
|
|
}
|
|
/*==================== Callback Functions ==================================*/
|
|
pHdbCallback MakeHipadabaCallback(hdbCallbackFunction func,
|
|
void *userData, killUserData killFunc,
|
|
int id, int internalID){
|
|
pHdbCallback pNew = NULL;
|
|
|
|
assert(func != NULL);
|
|
|
|
pNew = malloc(sizeof(hdbCallback));
|
|
if(pNew == NULL){
|
|
return NULL;
|
|
}
|
|
memset(pNew,0,sizeof(hdbCallback));
|
|
|
|
pNew->userCallback = func;
|
|
pNew->userData = userData;
|
|
pNew->killFunc = killFunc;
|
|
pNew->id = id;
|
|
pNew->internalID = internalID;
|
|
return pNew;
|
|
}
|
|
/*-------------------------------------------------------------------*/
|
|
void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
|
pHdbCallback current = NULL;
|
|
|
|
switch(type){
|
|
case HCBSET:
|
|
if(node->writeCallbacks == NULL){
|
|
node->writeCallbacks = newCB;
|
|
return;
|
|
} else {
|
|
current = node->writeCallbacks;
|
|
}
|
|
break;
|
|
case HCBUPDATE:
|
|
if(node->updateCallbacks == NULL){
|
|
node->updateCallbacks = newCB;
|
|
return;
|
|
} else {
|
|
current = node->updateCallbacks;
|
|
}
|
|
break;
|
|
case HCBREAD:
|
|
if(node->readCallbacks == NULL){
|
|
node->readCallbacks = newCB;
|
|
return;
|
|
} else {
|
|
current = node->readCallbacks;
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
if(current != NULL){
|
|
while(current->next != NULL){
|
|
current = (pHdbCallback)current->next;
|
|
}
|
|
current->next= newCB;
|
|
newCB->previous = current;
|
|
}
|
|
}
|
|
/*-------------------------------------------------------------------------*/
|
|
/*---------------------------------------------------------------------------*/
|
|
void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
|
|
switch(type){
|
|
case HCBSET:
|
|
if(node->writeCallbacks == NULL){
|
|
node->writeCallbacks = newCB;
|
|
return;
|
|
} else {
|
|
newCB->next = node->writeCallbacks;
|
|
node->writeCallbacks->previous = newCB;
|
|
node->writeCallbacks = newCB;
|
|
}
|
|
break;
|
|
case HCBUPDATE:
|
|
if(node->updateCallbacks == NULL){
|
|
node->updateCallbacks = newCB;
|
|
return;
|
|
} else {
|
|
newCB->next = node->updateCallbacks;
|
|
node->updateCallbacks->previous = newCB;
|
|
node->updateCallbacks = newCB;
|
|
}
|
|
break;
|
|
case HCBREAD:
|
|
if(node->readCallbacks == NULL){
|
|
node->readCallbacks = newCB;
|
|
return;
|
|
} else {
|
|
newCB->next = node->readCallbacks;
|
|
node->readCallbacks->previous = newCB;
|
|
node->readCallbacks = newCB;
|
|
}
|
|
break;
|
|
default:
|
|
assert(0);
|
|
break;
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
void RemoveHipadabaCallback(pHdb root, int id){
|
|
pHdb current = NULL;
|
|
|
|
root->writeCallbacks = DeleteForID(root->writeCallbacks,id);
|
|
root->updateCallbacks = DeleteForID(root->updateCallbacks,id);
|
|
root->readCallbacks = DeleteForID(root->readCallbacks,id);
|
|
|
|
current = root->child;
|
|
while(current != NULL){
|
|
RemoveHipadabaCallback(current,id);
|
|
current = current->next;
|
|
}
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
void InternalRemoveHipadabaCallback(pHdb root, int internalID){
|
|
pHdb current = NULL;
|
|
|
|
root->writeCallbacks = DeleteForInternalID(root->writeCallbacks,internalID);
|
|
root->updateCallbacks = DeleteForInternalID(root->updateCallbacks,internalID);
|
|
root->readCallbacks = DeleteForInternalID(root->readCallbacks,internalID);
|
|
|
|
current = root->child;
|
|
while(current != NULL){
|
|
InternalRemoveHipadabaCallback(current,internalID);
|
|
current = current->next;
|
|
}
|
|
}
|
|
/*=================== parameter interface ====================================*/
|
|
int copyHdbValue(hdbValue *source, hdbValue *target){
|
|
int i;
|
|
|
|
if(source->dataType != target->dataType){
|
|
return 0;
|
|
}
|
|
|
|
switch(source->dataType){
|
|
case HIPNONE:
|
|
break;
|
|
case HIPINT:
|
|
target->v.intValue = source->v.intValue;
|
|
break;
|
|
case HIPFLOAT:
|
|
target->v.doubleValue = source->v.doubleValue;
|
|
break;
|
|
case HIPTEXT:
|
|
if(target->v.text != NULL){
|
|
free(target->v.text);
|
|
}
|
|
target->v.text = strdup(source->v.text);
|
|
break;
|
|
case HIPINTAR:
|
|
case HIPINTVARAR:
|
|
if(target->arrayLength != source->arrayLength){
|
|
if(target->v.intArray != NULL){
|
|
free(target->v.intArray);
|
|
}
|
|
target->v.intArray = malloc(source->arrayLength * sizeof(int));
|
|
if(target->v.intArray == NULL){
|
|
return 0;
|
|
}
|
|
memset(target->v.intArray,0,source->arrayLength * sizeof(int));
|
|
target->arrayLength = source->arrayLength;
|
|
}
|
|
for(i = 0; i < source->arrayLength; i++){
|
|
target->v.intArray[i] = source->v.intArray[i];
|
|
}
|
|
break;
|
|
case HIPFLOATAR:
|
|
case HIPFLOATVARAR:
|
|
if(target->arrayLength != source->arrayLength){
|
|
if(target->v.floatArray != NULL){
|
|
free(target->v.floatArray);
|
|
}
|
|
target->v.floatArray = malloc(source->arrayLength * sizeof(double));
|
|
if(target->v.floatArray == NULL){
|
|
return 0;
|
|
}
|
|
memset(target->v.floatArray,0,source->arrayLength * sizeof(double));
|
|
target->arrayLength = source->arrayLength;
|
|
}
|
|
for(i = 0; i < source->arrayLength; i++){
|
|
target->v.floatArray[i] = source->v.floatArray[i];
|
|
}
|
|
break;
|
|
default:
|
|
/*
|
|
* unknown data type
|
|
*/
|
|
assert(0);
|
|
break;
|
|
}
|
|
return 1;
|
|
}
|
|
/*----------------------------------------------------------------------------*/
|
|
int SetHipadabaPar(pHdb node, hdbValue v, void *callData){
|
|
int status;
|
|
|
|
status = InvokeCallbackChain(node->writeCallbacks, node, callData, v);
|
|
return status;
|
|
}
|
|
/*-----------------------------------------------------------------------------*/
|
|
int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData){
|
|
int status;
|
|
|
|
status = InvokeCallbackChain(node->updateCallbacks, node, callData, v);
|
|
if(status != 1 ){
|
|
return status;
|
|
}
|
|
copyHdbValue(&v,&node->value);
|
|
return 1;
|
|
}
|
|
/*-----------------------------------------------------------------------------*/
|
|
int GetHipadabaPar(pHdb node, hdbValue *v, void *callData){
|
|
int status;
|
|
|
|
status = InvokeCallbackChain(node->readCallbacks, node, callData, *v);
|
|
if(status != 1 ){
|
|
return status;
|
|
}
|
|
v->dataType = node->value.dataType;
|
|
copyHdbValue(&node->value,v);
|
|
return 1;
|
|
}
|