Files
sics/hdbtable.c
Ferdi Franceschini 10d29d597c Cleaned up ANSTO code to merge with sinqdev.sics
This is our new RELEASE-4_0 branch which was taken from ansto/93d9a7c
Conflicts:
	.gitignore
	SICSmain.c
	asynnet.c
	confvirtualmot.c
	counter.c
	devexec.c
	drive.c
	event.h
	exebuf.c
	exeman.c
	histmem.c
	interface.h
	motor.c
	motorlist.c
	motorsec.c
	multicounter.c
	napi.c
	napi.h
	napi4.c
	network.c
	nwatch.c
	nxscript.c
	nxxml.c
	nxxml.h
	ofac.c
	reflist.c
	scan.c
	sicshipadaba.c
	sicsobj.c
	site_ansto/docs/Copyright.txt
	site_ansto/instrument/lyrebird/config/tasmad/sicscommon/nxsupport.tcl
	site_ansto/instrument/lyrebird/config/tasmad/taspub_sics/tasscript.tcl
	statusfile.c
	tasdrive.c
	tasub.c
	tasub.h
	tasublib.c
	tasublib.h
2015-04-23 20:49:26 +10:00

522 lines
14 KiB
C

/**
* Hdbtable is a more generic implementation for a table based on a Hipadaba
* tree structure. This table will be used at various instances in SICS. The general
* approach is that there is a child node called template whose children will be
* the nodes describing each column. Another entry called data will hold the
* rows of the table. Each row is a clone of the template. The result is
* an inefficient mapping of a table into a tree. But then, for smaller tables this
* is good enough and fits nicely into the Hipadaba and gumtree schemes. This file
* provides a couple of commands to deal with such tables. A user of this module will
* have to add content to the template first. And then run readtemplate in order
* to activate the new structure.
*
* I use a descriptor key called rowcount for the row ID management rather then
* the private data structure. This leaves clients of this module to use the
* private data structure at will.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, March 2009
*
* Added CountTblCmd
*
* Mark Koennecke, march 2013
*/
#include <stdlib.h>
#include "sicshipadaba.h"
#include <hdbtable.h>
/*------------------------------------------------------------------------*/
int SaveHdbTable(void *data, char *name, FILE * fd)
{
pSICSOBJ self = (pSICSOBJ) data;
pHdb datanode, row, child;
pDynString val;
datanode = GetHipadabaNode(self->objectNode,"data");
assert(datanode != NULL);
row = datanode->child;
fprintf(fd,"%s clear\n", name);
while(row != NULL){
fprintf(fd,"%s addrow ", name);
child = row->child;
while(child != NULL){
val = formatValue(child->value, child);
if(val != NULL){
fprintf(fd," %s", GetCharArray(val));
DeleteDynString(val);
}
child = child->next;
}
fprintf(fd,"\n");
row = row->next;
}
return 1;
}
/*------------------------------------------------------------------------*/
static int ClearTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb node, child, tmp;
node = GetHipadabaNode(self->objectNode,"data");
if(node != NULL){
if(CountHdbChildren(node) < 1){
return 1;
}
child = node->child;
while(child != NULL){
tmp = child;
child = child->next;
DeleteNodeData(tmp);
}
}
node->child = NULL;
SendTreeChangeMessage(node,pCon);
SetDescriptorKey(self->pDes,"rowcount","0");
if(pCon != NULL){
SCparChange(pCon);
}
return 1;
}
/*----------------------------------------------------------------------*/
int CountTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb node;
int nRows = 0;
node = GetHipadabaNode(self->objectNode,"data");
if(node != NULL){
nRows = CountHdbChildren(node);
}
SCPrintf(pCon,eValue,"rows = %d", nRows);
return 1;
}
/*----------------------------------------------------------------------*/
static int AddTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
int count;
char *ct, number[10];
pHdb row, val, child, template;
ct = GetDescriptorKey(self->pDes,"rowcount");
count = atoi(ct);
snprintf(number,10,"%4.4d", count);
row = MakeHipadabaNode(number,HIPNONE,1);
if(row == NULL){
SCWrite(pCon,"ERROR: out of memory in AddTblRow", eError);
return 0;
}
count++;
snprintf(number,10,"%d",count);
SetDescriptorKey(self->pDes,"rowcount",number);
SetHdbProperty(row,"__save","true");
template = GetHipadabaNode(self->objectNode,"template");
assert(template != NULL);
child = template->child;
count = 0;
while(child != NULL){
val = MakeSICSHdbPar(child->name,usUser,
makeHdbValue(child->value.dataType, child->value.arrayLength));
if(count < nPar){
UpdateHipadabaPar(val,par[count]->value,pCon);
}
AddHipadabaChild(row,val, pCon);
SetHdbProperty(val,"__save","true");
count++;
child = child->next;
}
child = GetHipadabaNode(self->objectNode,"data");
assert(child != NULL);
AddHipadabaChild(child,row, pCon);
SendTreeChangeMessage(child,pCon);
if(pCon != NULL){
SCparChange(pCon);
}
return 1;
}
/*----------------------------------------------------------------------*/
static int RepTblRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
int count;
char path[132];
pHdb row, val, child;
if(nPar < 1) {
SCPrintf(pCon,eError,"ERROR: no parameters found to reprow");
return 0;
}
snprintf(path,131,"data/%s", par[0]->value.v.text);
row = GetHipadabaNode(self->objectNode,path);
if(row == NULL){
SCPrintf(pCon,eError,"ERROR: row with ID %s not found", par[0]->value.v.text);
return 0;
}
child = row->child;
count = 1;
while(child != NULL && count < nPar){
if(count < nPar){
UpdateHipadabaPar(child,par[count]->value,pCon);
}
count++;
child = child->next;
}
if(pCon != NULL){
SCparChange(pCon);
}
return 1;
}
/*----------------------------------------------------------------------
* ReadTemplateCmd does something interesting: it rewrites the parameter
* lists of both addrow and reprow according to the template
* ---------------------------------------------------------------------*/
int ReadTableTemplate(pSICSOBJ self, SConnection *con)
{
pHdb node, template, child, cmd;
SConnection *pCon = con;
if(pCon == NULL){
pCon = pServ->dummyCon;
}
template = GetHipadabaNode(self->objectNode,"template");
assert(template != NULL);
/* mogrify addrow */
node = GetHipadabaNode(self->objectNode,"addrow");
if(node != NULL){
DeleteHipadabaNode(node,pCon);
}
cmd = AddSICSHdbPar(self->objectNode, "addrow", usUser,
MakeSICSFunc(AddTblRowCmd));
if(cmd == NULL){
SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError );
return 0;
}
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","user");
child = template->child;
while(child != NULL){
node = MakeSICSHdbPar(child->name, usUser,
makeHdbValue(child->value.dataType, child->value.arrayLength));
if(node == NULL){
SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError );
return 0;
}
AddHipadabaChild(cmd,node,pCon);
child = child->next;
}
/* mogrify reprow */
node = GetHipadabaNode(self->objectNode,"reprow");
if(node != NULL){
DeleteHipadabaNode(node,pCon);
}
cmd = AddSICSHdbPar(self->objectNode, "reprow", usUser,
MakeSICSFunc(RepTblRowCmd));
if(cmd == NULL){
SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError );
return 0;
}
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","user");
node = MakeSICSHdbPar("id",usUser, makeHdbValue(HIPTEXT,1));
AddHipadabaChild(cmd,node, pCon);
child = template->child;
while(child != NULL){
node = MakeSICSHdbPar(child->name, usUser,
makeHdbValue(child->value.dataType, child->value.arrayLength));
if(node == NULL){
SCWrite(pCon,"ERROR: out of memory in ReadTemplateCmd",eError );
return 0;
}
AddHipadabaChild(cmd,node,pCon);
child = child->next;
}
return 1;
}
/*----------------------------------------------------------------------*/
static int ReadTemplateCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
return ReadTableTemplate(self,pCon);
}
/*----------------------------------------------------------------------*/
static int DelRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb row = NULL, data;
char path[132];
if(nPar < 1){
SCWrite(pCon,"ERROR: need ID of row to kill",eError);
return 0;
}
snprintf(path,132,"data/%s",par[0]->value.v.text);
row = GetHipadabaNode(self->objectNode,path);
if(row == NULL){
SCPrintf(pCon,eError,"ERROR: row with ID %s not found", par[0]->value.v.text);
return 0;
}
data = row->mama;
DeleteHipadabaNode(row,pCon);
if(pCon != NULL){
SCparChange(pCon);
}
SendTreeChangeMessage(data,pCon);
SCSendOK(pCon);
return 1;
}
/*----------------------------------------------------------------------*/
static int GetRowCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb row = NULL, child;
char path[132];
pDynString result, val;
if(nPar < 1){
SCWrite(pCon,"ERROR: need ID of row to read",eError);
return 0;
}
snprintf(path,132,"data/%s",par[0]->value.v.text);
row = GetHipadabaNode(self->objectNode,path);
if(row == NULL){
SCPrintf(pCon,eError,"ERROR: row with ID %s not found", par[0]->value.v.text);
return 0;
}
result = CreateDynString(128,128);
if(result == NULL){
SCWrite(pCon,"ERROR: out of memory in GetRowCmd", eError);
return 0;
}
child = row->child;
while(child != NULL){
val = formatValue(child->value, child);
if(val != NULL){
DynStringConcat(result,GetCharArray(val));
if(child->next != NULL){
DynStringConcatChar(result,',');
}
DeleteDynString(val);
}
child = child->next;
}
SCWrite(pCon,GetCharArray(result),eValue);
DeleteDynString(result);
return 1;
}
/*----------------------------------------------------------------------*/
static int GetRowNoCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb row = NULL, child, data;
int i, nodeNo;
char path[132];
pDynString result, val;
if(nPar < 1){
SCWrite(pCon,"ERROR: need index of row to read",eError);
return 0;
}
nodeNo = par[0]->value.v.intValue;
data = GetHipadabaNode(self->objectNode,"data");
assert(data != NULL);
row = data->child;
for(i = 0; i < nodeNo; i++){
row = row->next;
if(row == NULL){
SCPrintf(pCon,eError,"ERROR: row %d not found", nodeNo);
return 0;
}
}
result = CreateDynString(128,128);
if(result == NULL){
SCWrite(pCon,"ERROR: out of memory in GetRowCmd", eError);
return 0;
}
child = row->child;
while(child != NULL){
val = formatValue(child->value, child);
if(val != NULL){
DynStringConcat(result,GetCharArray(val));
if(child->next != NULL){
DynStringConcatChar(result,',');
}
DeleteDynString(val);
}
child = child->next;
}
SCWrite(pCon,GetCharArray(result),eValue);
DeleteDynString(result);
return 1;
}
/*----------------------------------------------------------------------*/
static int ListTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
pHdb par[], int nPar)
{
pHdb node, row, child, data, template;
char buffer[20];
pDynString list = NULL, val;
list = CreateDynString(25,256);
if(list == NULL){
SCWrite(pCon,"ERROR: out of memory in LisTblCmd", eError);
return 0;
}
/*
* create the list header
*/
DynStringConcat(list," ID");
template = GetHipadabaNode(self->objectNode,"template");
assert(template != NULL);
child = template->child;
while(child != NULL){
snprintf(buffer,20," %8s", child->name);
DynStringConcat(list,buffer);
child = child->next;
}
DynStringConcatChar(list,'\n');
data = GetHipadabaNode(self->objectNode,"data");
assert(data != NULL);
/*
* list the data
*/
row = data->child;
while(row != NULL){
snprintf(buffer,20," %8s", row->name);
DynStringConcat(list,buffer);
child = row->child;
while(child != NULL){
val = formatValue(child->value,child);
snprintf(buffer,20," %8s", GetCharArray(val));
DynStringConcat(list,buffer);
DeleteDynString(val);
child = child->next;
}
DynStringConcatChar(list,'\n');
row = row->next;
}
SCWrite(pCon,GetCharArray(list),eValue);
DeleteDynString(list);
return 1;
}
/*----------------------------------------------------------------------*/
pSICSOBJ MakeHdbTable(char *name, char *hdbclass)
{
pSICSOBJ result = NULL;
pHdb node, cmd;
result = MakeSICSOBJv(name,hdbclass,HIPNONE,usSpy);
if(result == NULL){
return NULL;
}
SetDescriptorKey(result->pDes,"rowcount","0");
SetHdbProperty(result->objectNode,"viewer","mountaingumui.TableViewer");
result->pDes->SaveStatus = SaveHdbTable;
node = MakeSICSHdbPar("template",usMugger,MakeHdbText("x,y"));
if(node == NULL){
return NULL;
}
SetHdbProperty(node,"__save","true");
AddHipadabaChild(result->objectNode,node,NULL);
node = MakeHipadabaNode("data",HIPNONE,1);
if(node == NULL){
return NULL;
}
SetHdbProperty(node,"__save","true");
AddHipadabaChild(result->objectNode,node,NULL);
cmd = AddSICSHdbPar(result->objectNode, "clear", usUser,
MakeSICSFunc(ClearTblCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","user");
cmd = AddSICSHdbPar(result->objectNode, "print", usUser,
MakeSICSFunc(ListTblCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","user");
cmd = AddSICSHdbPar(result->objectNode, "addrow", usUser,
MakeSICSFunc(AddTblRowCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","user");
cmd = AddSICSHdbPar(result->objectNode, "reprow", usUser,
MakeSICSFunc(RepTblRowCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","user");
cmd = AddSICSHdbPar(result->objectNode, "readtemplate", usUser,
MakeSICSFunc(ReadTemplateCmd));
cmd = AddSICSHdbPar(result->objectNode, "del", usUser,
MakeSICSFunc(DelRowCmd));
node = MakeHipadabaNode("id",HIPTEXT,1);
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","user");
SetHdbProperty(node,"priv","user");
AddHipadabaChild(cmd,node, NULL);
cmd = AddSICSHdbPar(result->objectNode, "get", usUser,
MakeSICSFunc(GetRowCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","user");
node = MakeHipadabaNode("id",HIPTEXT,1);
SetHdbProperty(node,"priv","user");
AddHipadabaChild(cmd,node, NULL);
cmd = AddSICSHdbPar(result->objectNode, "getno", usUser,
MakeSICSFunc(GetRowNoCmd));
SetHdbProperty(cmd,"type","command");
SetHdbProperty(cmd,"priv","user");
node = MakeHipadabaNode("id",HIPINT,1);
SetHdbProperty(node,"priv","user");
AddHipadabaChild(cmd,node, NULL);
cmd = AddSICSHdbPar(result->objectNode, "count", usSpy,
MakeSICSFunc(CountTblCmd));
return result;
}
/*---------------------------------------------------------------------------*/
int HdbTableFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
{
pSICSOBJ pNew = NULL;
int status;
if(argc < 2) {
SCWrite(pCon,"ERROR: need name of table to create", eError);
return 0;
}
pNew = MakeHdbTable(argv[1],"HdbTable");
if(pNew == NULL){
SCWrite(pCon,"ERROR: out of memory in MakeHdbTable", eError);
return 0;
}
status = AddCommand(pSics, argv[1], InterInvokeSICSOBJ, DefaultKill, pNew);
if (status != 1) {
SCWrite(pCon, "ERROR: duplicate HdbTable command not created", eError);
return 0;
}
return 1;
}