Files
sics/hipadaba.c
zolliker 61341b52f4 various improvements
- use dig for resolving host names
- ascon.c: fix terminator parsing
- property callback: change property before callback
- logger.c:default for logger period must be the old value instead of 1
- add frappy type history writing
- increase max. logreader line length
- HIPNONE returns "null" with json protocol
- encode strings properly in formatNameValue
- fix memory leak in json2tcl
- scriptcontext: do not show debug messages when script starts with underscore or when the "send" property is empty
- scriptcontext: remove args for action timestamp
- scriptcontext: "que" function will replace an already queued action, e.g. for 'halt
- introduced updatestatus script
2021-09-16 12:26:18 +02:00

1221 lines
28 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 <math.h>
#include "hipadaba.h"
#define ABS(x) (x < 0 ? -(x) : (x))
#define HDBMAGICK 77119900
/*================== Message Stuff ========================================*/
static char set[] = { "set" };
static char get[] = { "get" };
static char update[] = { "update" };
static char treeChange[] = { "treeChange" };
static char dataSearch[] = { "dataSearch" };
static char killNode[] = { "killNode" };
static char propertyChange[] = { "propertyChange" };
/*------------------------------------------------------------------------*/
pHdbDataMessage GetHdbSetMessage(pHdbMessage toTest)
{
if (toTest->type == set) {
return (pHdbDataMessage) toTest;
}
return NULL;
}
/*------------------------------------------------------------------------*/
pHdbDataMessage GetHdbGetMessage(pHdbMessage toTest)
{
if (toTest->type == get) {
return (pHdbDataMessage) toTest;
}
return NULL;
}
/*------------------------------------------------------------------------*/
pHdbDataMessage GetHdbUpdateMessage(pHdbMessage toTest)
{
if (toTest->type == update) {
return (pHdbDataMessage) toTest;
}
return NULL;
}
/*-------------------------------------------------------------------------*/
pHdbTreeChangeMessage GetHdbTreeChangeMessage(pHdbMessage toTest)
{
if (toTest->type == treeChange) {
return (pHdbTreeChangeMessage) toTest;
}
return NULL;
}
/*-------------------------------------------------------------------------*/
pHdbDataSearch GetHdbDataSearchMessage(pHdbMessage toTest)
{
if (toTest->type == dataSearch) {
return (pHdbDataSearch) toTest;
}
return NULL;
}
/*-------------------------------------------------------------------------*/
pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest)
{
if (toTest->type == killNode) {
return toTest;
}
return NULL;
}
/*-------------------------------------------------------------------------*/
pHdbPropertyChange GetPropertyChangeMessage(pHdbMessage toTest)
{
if (toTest->type == propertyChange) {
return (pHdbPropertyChange)toTest;
}
return NULL;
}
/*================== internal functions ===================================*/
void DeleteCallbackChain(pHdb node)
{
pHdbCallback current = NULL, thisEntry;
hdbMessage killNodeMsg;
killNodeMsg.type = killNode;
InvokeCallbackChain(node, &killNodeMsg);
current = node->callBackChain;
node->callBackChain = NULL;
while (current != NULL) {
if (current->killFunc != NULL) {
current->killFunc(current->userData);
}
thisEntry = current;
current = (pHdbCallback) current->next;
free(thisEntry);
}
}
/*----------------------------------------------------------------------*/
void RecurseCallbackChains(pHdb node, pHdbMessage message)
{
pHdb current = NULL;
InvokeCallbackChain(node, message);
current = node->child;
while (current != NULL) {
RecurseCallbackChains(current, message);
current = current->next;
}
}
/*-----------------------------------------------------------------------*/
void DeleteNodeData(pHdb node)
{
pHdb tmp = NULL, next = NULL;
if (node == NULL) {
return;
}
DeleteCallbackChain(node);
if (node->properties != NULL) {
DeleteStringDict(node->properties);
}
if (node->name != NULL) {
free(node->name);
}
if (node->path != NULL) {
free(node->path);
}
ReleaseHdbValue(&node->value);
node->magic = 000000;
while (node->child != NULL) {
tmp = node->child;
next = node->child->next;
DeleteNodeData(tmp);
node->child = next;
}
free(node);
}
/*------------------------------------------------------------------------*/
static pHdbCallback CleanCallbackChain(pHdbCallback head)
{
pHdbCallback current = head;
pHdbCallback next;
pHdbCallback *ptr2last = &head;
while (current != NULL) {
if (current->killFlag == 1) {
next = current->next;
/*
* unlink
*/
*ptr2last = next;
/*
* delete
*/
if (current->killFunc != NULL) {
current->killFunc(current->userData);
}
free(current);
/*
* move on
*/
current = next;
} else {
ptr2last = &current->next;
current = current->next;
}
}
return head;
}
/*-------------------------------------------------------------------------*/
int InvokeCallbackChain(pHdb node, pHdbMessage message)
{
pHdbCallback current = node->callBackChain;
hdbCallbackReturn status;
int killFlag = 0;
while (current != NULL) {
status = current->userCallback(node, current->userData, message);
switch (status) {
case hdbAbort:
return 0;
break;
case hdbKill:
current->killFlag = 1;
killFlag = 1;
break;
case hdbContinue:
break;
}
current = current->next;
}
if (killFlag == 1) {
node->callBackChain = CleanCallbackChain(node->callBackChain);
}
return 1;
}
/*-----------------------------------------------------------------------*/
void SendTreeChangeMessage(pHdb node, void *callData)
{
hdbTreeChangeMessage treeChangeMes;
treeChangeMes.type = treeChange;
treeChangeMes.callData = callData;
InvokeCallbackChain(node, (pHdbMessage) & treeChangeMes);
}
/*------------------------------------------------------------------------*/
void RemoveHdbNodeFromParent(pHdb node, void *callData)
{
pHdb parent = NULL;
pHdb current = NULL;
hdbTreeChangeMessage treeChangeMes;
parent = node->mama;
if (parent != NULL) {
if (parent->child == node) {
parent->child = node->next;
} else {
current = parent->child;
while (current->next != node) {
current = current->next;
}
current->next = current->next->next;
}
SendTreeChangeMessage(parent, callData);
node->mama = NULL;
}
}
/*----------------------------------------------------------------------*/
int CountHdbChildren(pHdb node)
{
int count = 0;
pHdb current = NULL;
current = node->child;
while (current != NULL) {
current = current->next;
count++;
}
return count;
}
/*----------------------------------------------------------------------*/
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;
if(root == NULL){
return 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;
val.doNotFree = 0;
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.arrayLength = 1;
result.v.intValue = initValue;
result.doNotFree = 0;
return result;
}
/*-------------------------------------------------------------------------*/
hdbValue MakeHdbFloat(double initValue)
{
hdbValue result;
result.dataType = HIPFLOAT;
result.arrayLength = 1;
result.v.doubleValue = initValue;
result.doNotFree = 0;
return result;
}
/*-------------------------------------------------------------------------*/
hdbValue MakeHdbText(char *initText)
{
hdbValue result;
result.dataType = HIPTEXT;
result.v.text = initText; /* no strdup here ! */
result.arrayLength = strlen(initText);
result.doNotFree = 0;
return result;
}
/*-------------------------------------------------------------------------*/
hdbValue MakeHdbIntArray(int length, int *data)
{
hdbValue result;
result.dataType = HIPINTAR;
result.arrayLength = length;
result.v.intArray = data;
result.doNotFree = 0;
return result;
}
/*-------------------------------------------------------------------------*/
hdbValue MakeHdbFloatArray(int length, double *data)
{
hdbValue result;
result.dataType = HIPFLOATAR;
result.arrayLength = length;
result.v.floatArray = data;
result.doNotFree = 0;
return result;
}
/*-------------------------------------------------------------------------*/
hdbValue MakeHdbFunc(voidFunc * func)
{
hdbValue result;
result.dataType = HIPFUNC;
result.v.func = func;
result.doNotFree = 0;
return result;
}
/*-------------------------------------------------------------------------*/
hdbValue MakeHdbObj(void *obj)
{
hdbValue result;
result.dataType = HIPOBJ;
result.v.obj = obj;
result.doNotFree = 0;
return result;
}
/*-------------------------------------------------------------------------*/
void ReleaseHdbValue(hdbValue * v)
{
if (v->doNotFree == 1) {
return;
}
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;
}
}
/*-----------------------------------------------------------------------------*/
static unsigned short fletcher16( char *data, size_t len)
{
unsigned short sum1 = 0xff, sum2 = 0xff, result;
unsigned char checkA, checkB;
if(data == NULL){
return 0;
}
while (len) {
size_t tlen = len > 21 ? 21 : len;
len -= tlen;
do {
sum1 += *data++;
sum2 += sum1;
} while (--tlen);
sum1 = (sum1 & 0xff) + (sum1 >> 8);
sum2 = (sum2 & 0xff) + (sum2 >> 8);
}
/* Second reduction step to reduce sums to 8 bits */
sum1 = (sum1 & 0xff) + (sum1 >> 8);
sum2 = (sum2 & 0xff) + (sum2 >> 8);
checkA = (unsigned char)sum1;
checkB = (unsigned char)sum2;
result = checkA;
result = result << 8 | checkB;
return result ;
}
#define MAXLEN 65536
/*------------------------------------------------------------------------*/
static unsigned short longfletcher16(char *data, size_t len)
{
char buffer[MAXLEN];
int i, j, div, count;
char *pPtr;
if(len < MAXLEN){
return fletcher16(data,len);
}
/**
* sum together to run the more complex checksum on
* more juicy data
*/
div = (int)trunc((float)len/(float)MAXLEN);
for(i = 0; i < MAXLEN; i++){
pPtr = data + div*i;
for(j = 0; j < div; j++){
buffer[i] += *(pPtr + j);
}
}
return fletcher16(buffer,MAXLEN);
}
/*------------------------------------------------------------------------*/
unsigned short getHdbCheckSum(hdbValue *val)
{
char *data;
size_t len;
len = getHdbValueLength(*val);
/*
if(len > MAXLEN){
len = MAXLEN;
}
*/
switch (val->dataType) {
case HIPNONE:
return 0;
break;
case HIPINT:
data = (char *)&val->v.intValue;
return fletcher16(data,len);
break;
case HIPFLOAT:
data = (char *)&val->v.doubleValue;
return fletcher16(data,len);
break;
case HIPTEXT:
data = val->v.text;
return fletcher16(data,len);
break;
case HIPINTAR:
case HIPINTVARAR:
data = (char *)val->v.intArray;
return fletcher16(data,len);
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
data = (char *)val->v.floatArray;
return fletcher16(data,len);
break;
case HIPOBJ:
data = (char *)val->v.obj;
return fletcher16(data,len);
break;
case HIPFUNC:
data = (char *)val->v.func;
return fletcher16(data,len);
break;
default:
assert(0);
break;
}
return 0;
}
/*------------------------------------------------------------------------*/
int compareHdbValue(hdbValue v1, hdbValue v2)
{
int i;
if (v1.dataType != v2.dataType) {
return 0;
}
if((v1.doNotFree == 1 && v1.v.obj == NULL)
|| (v2.doNotFree == 1 && v2.v.obj == NULL)){
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) < .0001) { /* DFC */
return 1;
} else {
return 0;
}
break;
case HIPTEXT:
if (v1.v.text == NULL || v2.v.text == NULL) {
return 0;
}
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;
}
if (v1.v.intArray == NULL || v2.v.intArray == NULL) {
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;
}
if (v1.v.floatArray == NULL || v2.v.floatArray == NULL) {
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;
case HIPOBJ:
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;
}
return 0;
}
/*-------------------------------------------------------------------------*/
int cloneHdbValue(hdbValue * source, hdbValue * clone)
{
memset(clone, 0, sizeof(hdbValue));
clone->v.text = NULL; /* this sets all pointers in the union to NULL */
clone->dataType = source->dataType;
return copyHdbValue(source, clone);
}
/*-------------------------------------------------------------------------*/
int getHdbValueLength(hdbValue v)
{
int length = 0;
switch (v.dataType) {
case HIPNONE:
break;
case HIPINT:
length = sizeof(int);
break;
case HIPFLOAT:
length = sizeof(double);
break;
case HIPINTAR:
case HIPINTVARAR:
length = v.arrayLength * sizeof(int);
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
length = v.arrayLength * sizeof(double);
break;
case HIPTEXT:
length = strlen(v.v.text);
break;
case HIPOBJ:
length = sizeof(void *);
break;
case HIPFUNC:
length = sizeof(voidFunc *);
break;
}
return length;
}
/*================= 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;
pNew->properties = CreateStringDict();
if (pNew->properties == NULL || pNew->name == NULL) {
return NULL;
}
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, void *callData)
{
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;
}
SendTreeChangeMessage(parent, callData);
}
/*--------------------------------------------------------------------------*/
void DeleteHipadabaNode(pHdb node, void *callData)
{
pHdb current = NULL, tmp = NULL;
if (node == NULL) {
return;
}
RemoveHdbNodeFromParent(node, callData);
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);
}
node->path = pPtr;
return pPtr;
}
/*==================== Callback Functions ==================================*/
pHdbCallback MakeHipadabaCallback(hdbCallbackFunction func,
void *userData, killUserData killFunc)
{
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;
return pNew;
}
/*-------------------------------------------------------------------*/
void AppendHipadabaCallback(pHdb node, pHdbCallback newCB)
{
pHdbCallback current = NULL;
assert(node);
current = node->callBackChain;
newCB->next = NULL;
if (current == NULL) {
node->callBackChain = newCB;
return;
}
while (current->next != NULL) {
current = (pHdbCallback) current->next;
}
current->next = newCB;
}
/*---------------------------------------------------------------------------*/
void PrependHipadabaCallback(pHdb node, pHdbCallback newCB)
{
assert(node != NULL);
newCB->next = node->callBackChain;
node->callBackChain = newCB;
}
/*----------------------------------------------------------------------------*/
void *FindHdbCallbackData(pHdb node, void *userPtr)
{
hdbDataSearch dsm;
dsm.type = dataSearch;
dsm.testPtr = userPtr;
dsm.result = NULL;
InvokeCallbackChain(node, (pHdbMessage) & dsm);
return dsm.result;
}
/*=================== parameter interface ====================================*/
static int canCopy(hdbValue * source, hdbValue * target)
{
if (target->dataType == HIPINTVARAR) {
if (source->dataType == HIPINTAR || source->dataType == HIPINTVARAR) {
return 1;
}
}
if(target->dataType == HIPINTAR &&
(source->dataType == HIPINTAR || source->dataType == HIPINTVARAR)
&& target->arrayLength == source->arrayLength){
return 1;
}
if (target->dataType == HIPFLOATVARAR) {
if (source->dataType == HIPFLOATAR ||
source->dataType == HIPFLOATVARAR) {
return 1;
}
}
if(target->dataType == HIPFLOATAR &&
(source->dataType == HIPFLOATAR || source->dataType == HIPFLOATVARAR)
&& target->arrayLength == source->arrayLength){
return 1;
}
if (source->dataType != target->dataType) {
return 0;
} else {
return 1;
}
}
/*----------------------------------------------------------------------------*/
int copyHdbValue(hdbValue * source, hdbValue * target)
{
int i;
if (!canCopy(source, target)) {
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
|| target->v.intArray == NULL) {
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;
}
if (source->v.intArray != NULL) {
/*
for (i = 0; i < source->arrayLength; i++) {
target->v.intArray[i] = source->v.intArray[i];
}
*/
memcpy(target->v.intArray,source->v.intArray,source->arrayLength*sizeof(int));
}
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
if (target->arrayLength != source->arrayLength
|| target->v.floatArray == NULL) {
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;
}
if (source->v.floatArray != NULL) {
for (i = 0; i < source->arrayLength; i++) {
target->v.floatArray[i] = source->v.floatArray[i];
}
}
break;
case HIPOBJ:
target->v.obj = source->v.obj;
break;
case HIPFUNC:
target->v.func = source->v.func;
break;
default:
/*
* unknown data type
*/
assert(0);
break;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int SendDataMessage(pHdb node, char *type,
hdbValue *v, void *callData)
{
hdbDataMessage dataMes;
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);
}
/*-----------------------------------------------------------------------------*/
int UpdateHipadabaPar(pHdb node, hdbValue v, void *callData)
{
int status;
status = SendDataMessage(node, update, &v, callData);
if (status == 1) {
copyHdbValue(&v, &node->value);
}
return status;
}
/*-----------------------------------------------------------------------------*/
int NotifyHipadabaPar(pHdb node, void *callData)
{
SendDataMessage(node, update, &node->value, callData);
return 1;
}
/*-----------------------------------------------------------------------------*/
int GetHipadabaPar(pHdb node, hdbValue *v, void *callData)
{
int status;
unsigned short checksum;
memset(v,0,sizeof(hdbValue));
v->dataType = node->value.dataType;
checksum = getHdbCheckSum(&node->value);
status = SendDataMessage(node, get, v, callData);
copyHdbValue(&node->value, v);
if(getHdbCheckSum(&node->value) != checksum){
NotifyHipadabaPar(node, callData);
}
if (status != 1) {
return status;
}
return 1;
}
/*----------------------------------------------------------------------------*/
static int calcDataLength(pHdb node, int testLength)
{
int length = 0;
length = getHdbValueLength(node->value);
if (node->value.dataType == HIPFLOATVARAR ||
node->value.dataType == HIPINTVARAR ||
node->value.dataType == HIPTEXT) {
length = testLength;
}
return length;
}
/*============================= Property Functions ==========================*/
void SetHdbProperty(pHdb node, char *key, char *value)
{
hdbPropertyChange propMes;
if (node != NULL && key != NULL && node->properties != NULL) {
propMes.type = propertyChange;
propMes.key = key;
propMes.value = value;
InvokeCallbackChain(node,(pHdbMessage)&propMes);
if (value == NULL) {
StringDictDelete(node->properties, key);
} else if (StringDictExists(node->properties, key)) {
StringDictUpdate(node->properties, key, value);
} else {
StringDictAddPair(node->properties, key, value);
}
}
}
/*---------------------------------------------------------------------------*/
int HasHdbProperty(pHdb node, char *key)
{
if (node != NULL && node->properties != NULL) {
return StringDictExists(node->properties, key);
} else {
return 0;
}
}
/*---------------------------------------------------------------------------*/
int GetHdbProperty(pHdb node, char *key, char *value, int len)
{
if (node != NULL && node->properties != NULL) {
return StringDictGet(node->properties, key, value, len);
} else {
return 0;
}
}
/*---------------------------------------------------------------------------*/
char *GetHdbProp(pHdb node, char *key)
{
if (node != NULL && isHdbNodeValid(node) && node->properties != NULL) {
return StringDictGetShort(node->properties, key);
} else {
return NULL;
}
}
/*---------------------------------------------------------------------------*/
void InitHdbPropertySearch(pHdb node)
{
if (node != NULL && node->properties != NULL) {
StringDictKillScan(node->properties);
}
}
/*--------------------------------------------------------------------------*/
const char *GetNextHdbProperty(pHdb node, char *value, int len)
{
if (node != NULL && node->properties != NULL) {
return StringDictGetNext(node->properties, value, len);
} else {
return NULL;
}
}