/*--------------------------------------------------------------------- S I C S D A T A An attempt to a generic interface to SICS data for all sorts of SICS clients. copyright: see file COPYRIGHT Mark Koennecke, June 2003 ----------------------------------------------------------------------*/ #include #include #include #include "fortify.h" #include "sics.h" #include "splitter.h" #include "scan.h" #include "HistMem.h" #include "sicsdata.h" #define ABS(x) (x < 0 ? -(x) : (x)) /*--------------------------------------------------------------------*/ static void KillSICSData(void *pData){ pSICSData self = NULL; self = (pSICSData)pData; if(!self){ return; } if(self->data != NULL){ free(self->data); } if(self->dataType != NULL){ free(self->dataType); } if(self->pDes != NULL){ DeleteDescriptor(self->pDes); } free(self); } /*---------------------------------------------------------------------*/ pSICSData createSICSData(void){ pSICSData pNew = NULL; pNew = (pSICSData)malloc(sizeof(SICSData)); if(!pNew){ return NULL; } memset(pNew,0,sizeof(SICSData)); pNew->pDes = CreateDescriptor("SICSData"); pNew->data = (int *)malloc(1024*sizeof(int)); pNew->dataType = (char *)malloc(1024*sizeof(char)); if(pNew->pDes == NULL || pNew->data == NULL || pNew->dataType == NULL){ KillSICSData(pNew); return NULL; } memset(pNew->data,0,1024*sizeof(int)); memset(pNew->dataType,0,1024*sizeof(char)); pNew->currentDataSize = 1024; pNew->dataUsed = 0; return pNew; } /*-------------------------------------------------------------------*/ int *getSICSDataPointer(pSICSData self, int start, int end){ int newSize; int *newData = NULL; char *newType = NULL; assert(self); if(end >= self->currentDataSize) { /* we have to resize */ if(self->currentDataSize*2 > end){ newSize = self->currentDataSize * 2.; }else { newSize = end + self->dataUsed; } newData = (int *)malloc(newSize*sizeof(int)); newType = (char *)malloc(newSize*sizeof(char)); if(newData == NULL || newType == NULL){ return NULL; } memset(newData,0,newSize*sizeof(int)); memset(newType,0,newSize*sizeof(char)); memcpy(newData,self->data,self->dataUsed*sizeof(int)); memcpy(newType,self->dataType,self->dataUsed*sizeof(char)); free(self->data); free(self->dataType); self->data = newData; self->dataType = newType; self->currentDataSize = newSize; } if(end > self->dataUsed){ self->dataUsed = end; } return &self->data[start]; } /*------------------------------------------------------------------------ assign a type to a couple of data values --------------------------------------------------------------------------*/ static void assignType(pSICSData self, int start, int end, int type){ int i; assert(self); assert(end <= self->currentDataSize); assert(type == INTTYPE || type == FLOATTYPE); for(i = start; i < end; i++){ self->dataType[i] = type; } } /*-----------------------------------------------------------------------*/ void assignSICSType(pSICSData self, int start, int end, int type){ assignType(self,start,end,type); } /*------------------------------------------------------------------------ netEncode transforms the data in the array into network format. - int become ints in network byte order - floats become fixed point and thus ints in network byte order as well -------------------------------------------------------------------------*/ static void netEncode(pSICSData self){ int i; float fVal; assert(self); for(i = 0; i < self->dataUsed; i++){ if(self->dataType[i] == INTTYPE){ self->data[i] = htonl(self->data[i]); } if(self->dataType[i] == FLOATTYPE){ memcpy(&fVal,self->data + i,sizeof(float)); fVal *= 65536.; self->data[i] = htonl((int)fVal); } } } /*---------------------------------------------------------------------*/ static void clearSICSData(pSICSData self){ assert(self); self->dataUsed = 0; memset(self->data,0,self->currentDataSize*sizeof(int)); memset(self->dataType,0,self->currentDataSize*sizeof(char)); } /*--------------------------------------------------------------------*/ static int dumpSICSData(pSICSData self, char *filename, SConnection *pCon){ FILE *fd = NULL; char pBueffel[132]; int i; float fVal; fd = fopen(filename,"w"); if(fd == NULL){ snprintf(pBueffel,131,"ERROR: cannot open %s", filename); SCWrite(pCon,pBueffel,eError); return 0; } for(i = 0; i < self->dataUsed; i++){ if(self->dataType[i] == INTTYPE){ fprintf(fd,"%10d %25d\n",i,self->data[i]); } if(self->dataType[i] == FLOATTYPE){ memcpy(&fVal,self->data + i,sizeof(float)); fprintf(fd,"%10d %25.5f\n",i,fVal); } } fclose(fd); SCSendOK(pCon); return 1; } /*-------------------------------------------------------------------*/ static int putInt(pSICSData self, int argc, char *argv[], SConnection *pCon, SicsInterp *pSics){ int status, iVal, pos, *iData = NULL; assert(self); if(argc < 2) { SCWrite(pCon,"ERROR: not enough arguments to SICSData putint",eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[0],&pos); if(status != TCL_OK){ SCWrite(pCon,"ERROR: failed to convert putint position to integer", eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[1],&iVal); if(status != TCL_OK){ SCWrite(pCon,"ERROR: failed to convert putint value to integer", eError); return 0; } iData = getSICSDataPointer(self,pos,pos+1); if(!iData){ SCWrite(pCon,"ERROR: out of memory in putint",eError); return 0; } *iData = iVal; SCSendOK(pCon); self->dataType[pos] = INTTYPE; return 1; } /*-------------------------------------------------------------------*/ static int putFloat(pSICSData self, int argc, char *argv[], SConnection *pCon, SicsInterp *pSics){ int status, pos, *iData = NULL; float fVal; double dVal; assert(self); if(argc < 2) { SCWrite(pCon,"ERROR: not enough arguments to SICSData putfloat",eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[0],&pos); if(status != TCL_OK){ SCWrite(pCon,"ERROR: failed to convert putfloat position to integer", eError); return 0; } status = Tcl_GetDouble(InterpGetTcl(pSics),argv[1],&dVal); if(status != TCL_OK){ SCWrite(pCon,"ERROR: failed to convert putint value to float", eError); return 0; } iData = getSICSDataPointer(self,pos,pos+1); if(!iData){ SCWrite(pCon,"ERROR: out of memory in putfloat",eError); return 0; } fVal = (float)dVal; memcpy(iData,&fVal,sizeof(float)); self->dataType[pos] = FLOATTYPE; SCSendOK(pCon); return 1; } /*------------------------------------------------------------------*/ static int getPos(pSICSData self, char *name, SConnection *pCon, int pos){ char pBueffel[512]; float value; if(pos >= self->dataUsed){ SCWrite(pCon,"ERROR: requested position out of range",eError); return 0; } if(self->dataType[pos] == FLOATTYPE){ memcpy(&value,&self->data[pos],sizeof(float)); snprintf(pBueffel,511,"%s = %f", name, value); SCWrite(pCon,pBueffel,eValue); return 1; } if(self->dataType[pos] == INTTYPE){ snprintf(pBueffel,511,"%s = %d", name, self->data[pos]); SCWrite(pCon,pBueffel,eValue); return 1; } return 0; } /*------------------------------------------------------------------*/ static float getDataPos(pSICSData self, int pos){ float value; assert(pos < self->dataUsed); if(self->dataType[pos] == FLOATTYPE){ memcpy(&value,&self->data[pos],sizeof(float)); } else { value = (float)self->data[pos]; } return value; } /*------------------------------------------------------------------*/ static int divideSicsData(pSICSData self, SicsInterp *pSics, SConnection *pCon, char *name){ int i; pSICSData other = NULL; float val, div; other = (pSICSData)FindCommandData(pSics,name,"SICSData"); if(other == NULL){ SCWrite(pCon,"ERROR: requested SICSData object to divide not found", eError); return 0; } if(other->dataUsed < self->dataUsed){ SCWrite(pCon,"ERROR: not enough data in SICSData for division", eError); return 0; } for(i = 0; i < self->dataUsed; i++){ div = getDataPos(other,i); if(ABS(div) > .00001){ val = getDataPos(self,i)/div; } else { val = .0; } if(self->dataType[i] == INTTYPE){ self->data[i] = (int)val; } else { memcpy(&self->data[i],&val,sizeof(float)); } } return 1; } /*-------------------------------------------------------------------*/ static int copyScanCounts(pSICSData self, int argc, char *argv[], SConnection *pCon, SicsInterp *pSics){ int status, pos, np ,i; pScanData pScan = NULL; int *iData = NULL; long *lData = NULL; if(argc < 2){ SCWrite(pCon,"ERROR: not enough arguments to SICSData copyscancounts", eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[0],&pos); if(status != TCL_OK){ SCWrite(pCon, "ERROR: failed to convert copyscancounts position to integer", eError); return 0; } pScan = FindCommandData(pSics,argv[1],"ScanObject"); if(!pScan){ SCWrite(pCon,"ERROR: scan object not found in copyscancounts", eError); return 0; } np = GetScanNP(pScan); iData = getSICSDataPointer(self,pos,pos+np); lData = (long *)malloc(np*sizeof(long)); if(!iData || !lData){ SCWrite(pCon,"ERROR: out of memory in copyscancounts",eError); return 0; } memset(lData,0,np*sizeof(long)); GetScanCounts(pScan,lData,np); for(i = 0; i < np; i++){ self->data[pos + i] = (int)lData[i]; self->dataType[pos + i] = INTTYPE; } free(lData); SCSendOK(pCon); return 1; } /*-------------------------------------------------------------------*/ static int copyScanMonitor(pSICSData self, int argc, char *argv[], SConnection *pCon, SicsInterp *pSics){ int status, pos, np ,i, monitor; pScanData pScan = NULL; int *iData = NULL; long *lData = NULL; if(argc < 2){ SCWrite(pCon,"ERROR: not enough arguments to SICSData copyscanmon", eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[0],&pos); if(status != TCL_OK){ SCWrite(pCon, "ERROR: failed to convert copyscancounts position to integer", eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&monitor); if(status != TCL_OK){ SCWrite(pCon, "ERROR: failed to convert copyscancounts monitor to integer", eError); return 0; } pScan = FindCommandData(pSics,argv[1],"ScanObject"); if(!pScan){ SCWrite(pCon,"ERROR: scan object not found in copyscanmonitor", eError); return 0; } np = GetScanNP(pScan); iData = getSICSDataPointer(self,pos,pos+np); lData = (long *)malloc(np*sizeof(long)); if(!iData || !lData){ SCWrite(pCon,"ERROR: out of memory in copyscanmonitor",eError); return 0; } memset(lData,0,np*sizeof(long)); GetScanMonitor(pScan,monitor,lData,np); for(i = 0; i < np; i++){ self->data[pos + i] = (int)lData[i]; self->dataType[pos + i] = INTTYPE; } free(lData); SCSendOK(pCon); return 1; } /*-------------------------------------------------------------------*/ static int copyScanVar(pSICSData self, int argc, char *argv[], SConnection *pCon, SicsInterp *pSics){ int status, pos, np ,i, var; pScanData pScan = NULL; int *iData = NULL; float *fData = NULL; if(argc < 2){ SCWrite(pCon,"ERROR: not enough arguments to SICSData copyscanvar", eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[0],&pos); if(status != TCL_OK){ SCWrite(pCon, "ERROR: failed to convert copyscanvar position to integer", eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&var); if(status != TCL_OK){ SCWrite(pCon, "ERROR: failed to convert copyscanvar varID to integer", eError); return 0; } pScan = FindCommandData(pSics,argv[1],"ScanObject"); if(!pScan){ SCWrite(pCon,"ERROR: scan object not found in copyscanvar", eError); return 0; } np = GetScanNP(pScan); iData = getSICSDataPointer(self,pos,pos+np); fData = (float *)malloc(np*sizeof(float)); if(!iData || !fData){ SCWrite(pCon,"ERROR: out of memory in copyscanvar",eError); return 0; } memset(fData,0,np*sizeof(float)); GetSoftScanVar(pScan,var,fData,np); for(i = 0; i < np; i++){ memcpy(self->data + pos +i,fData + i,sizeof(float)); self->dataType[pos + i] = FLOATTYPE; } free(fData); SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------*/ static int copyTimeBin(pSICSData self, int argc, char *argv[], SConnection *pCon, SicsInterp *pSics){ int status, noTimeBin, pos, i; pHistMem pHist = NULL; const float *fTimeBin = NULL; int *iData = NULL; if(argc < 2){ SCWrite(pCon,"ERROR: not enough arguments to SICSData copytimebin", eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[0],&pos); if(status != TCL_OK){ SCWrite(pCon, "ERROR: failed to convert copytimebin position to integer", eError); return 0; } pHist = (pHistMem)FindCommandData(pSics,argv[1],"HistMem"); if(!pHist){ SCWrite(pCon,"ERROR: histogram memory not found in copytimebin", eError); return 0; } fTimeBin = GetHistTimeBin(pHist,&noTimeBin); iData = getSICSDataPointer(self,pos,pos+noTimeBin); if(!fTimeBin || !iData){ SCWrite(pCon,"ERROR: out of memory in SICSData copytimebin",eError); return 0; } for(i = 0; i < noTimeBin; i++){ memcpy(iData + pos + i, fTimeBin + i, sizeof(float)); self->dataType[pos+i] = FLOATTYPE; } SCSendOK(pCon); return 1; } /*--------------------------------------------------------------------*/ static int copyHM(pSICSData self, int argc, char *argv[], SConnection *pCon, SicsInterp *pSics){ int status, pos, i, subset = 0, start, end; pHistMem pHist = NULL; const float *fTimeBin = NULL; int *iData = NULL; if(argc < 2){ SCWrite(pCon,"ERROR: not enough arguments to SICSData copyhm", eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[0],&pos); if(status != TCL_OK){ SCWrite(pCon, "ERROR: failed to convert copyhm position to integer", eError); return 0; } pHist = (pHistMem)FindCommandData(pSics,argv[1],"HistMem"); if(!pHist){ SCWrite(pCon,"ERROR: histogram memory not found in copytimebin", eError); return 0; } start = 0; end = GetHistLength(pHist); if(argc > 3) { subset = 1; status = Tcl_GetInt(InterpGetTcl(pSics),argv[2],&start); if(status != TCL_OK){ SCWrite(pCon, "ERROR: failed to convert copyhm start to integer", eError); return 0; } status = Tcl_GetInt(InterpGetTcl(pSics),argv[3],&end); if(status != TCL_OK){ SCWrite(pCon, "ERROR: failed to convert copyhm end to integer", eError); return 0; } } iData = getSICSDataPointer(self,pos,pos+(end-start)); if(!iData){ SCWrite(pCon,"ERROR: out of memory in SICSData copyhm",eError); return 0; } GetHistogramDirect(pHist,pCon,0,start,end,iData,(end-start)*sizeof(int)); assignType(self,pos,pos+(end-start),INTTYPE); SCSendOK(pCon); return 1; } /*---------------------------------------------------------------------- Look here in order to find out about commands understood ----------------------------------------------------------------------*/ int SICSDataAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pSICSData self = NULL; char pBueffel[132]; int pos; self = (pSICSData)pData; assert(self); if(argc < 2){ SCWrite(pCon,"ERROR: not enough arguments to act upon data",eError); return 0; } strtolower(argv[1]); /*------ clear*/ if(strcmp(argv[1],"clear") == 0){ clearSICSData(self); SCSendOK(pCon); return 1; } else if (strcmp(argv[1],"used") == 0){ /*--------- used */ snprintf(pBueffel,131,"%s = %d", argv[0], self->dataUsed); SCWrite(pCon,pBueffel,eValue); return 1; } else if(strcmp(argv[1],"dump") == 0){ /* --------- dump */ if(argc < 3){ SCWrite(pCon,"ERROR: need a file name to dump to",eError); return 0; } return dumpSICSData(self,argv[2],pCon); } else if(strcmp(argv[1],"get") == 0){ if(argc < 3){ SCWrite(pCon,"ERROR: need a position to read",eError); return 0; } pos = atoi(argv[2]); return getPos(self,argv[0],pCon,pos); } else if(strcmp(argv[1],"divideby") == 0){ if(argc < 3){ SCWrite(pCon,"ERROR: need a SICSdata to divide by",eError); return 0; } return divideSicsData(self,pSics,pCon,argv[2]); } else if(strcmp(argv[1],"putint") == 0){ /*---------- putint */ return putInt(self,argc-2,&argv[2],pCon, pSics); } else if(strcmp(argv[1],"putfloat") == 0){ /*---------- putfloat */ return putFloat(self,argc-2,&argv[2],pCon, pSics); } else if(strcmp(argv[1],"copyscancounts") == 0){ /*-------- copyscancounts*/ return copyScanCounts(self,argc-2,&argv[2],pCon,pSics); } else if(strcmp(argv[1],"copyscanmon") == 0){ /*-------- copyscanmon*/ return copyScanMonitor(self,argc-2,&argv[2],pCon,pSics); } else if(strcmp(argv[1],"copyscanvar") == 0){ /*--------- copyscanvar */ return copyScanVar(self,argc-2,&argv[2],pCon,pSics); } else if(strcmp(argv[1],"copytimebin") == 0){ /*--------- copytimebin */ return copyTimeBin(self,argc-2,&argv[2],pCon,pSics); } else if(strcmp(argv[1],"copyhm") == 0){ /*--------- copytimebin */ return copyHM(self,argc-2,&argv[2],pCon,pSics); } else if(strcmp(argv[1],"writezipped") == 0){ /*--------- writezipped */ if(argc < 3){ SCWrite(pCon,"ERROR: need a name for writezipped",eError); return 0; } netEncode(self); SCWriteZipped(pCon,argv[2],self->data,self->dataUsed*sizeof(int)); return 1; } else if(strcmp(argv[1],"writeuu") == 0){ /*--------- writeuu */ if(argc < 3){ SCWrite(pCon,"ERROR: need a name for writeuu",eError); return 0; } netEncode(self); SCWriteUUencoded(pCon,argv[2],self->data,self->dataUsed*sizeof(int)); return 1; } SCWrite(pCon,"ERROR: object command to SICSData not recognized",eError); return 0; } /*----------------------------------------------------------------------*/ int SICSDataFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pSICSData self = NULL; int iRet; if(argc < 3){ SCWrite(pCon,"ERROR: not enough arguments to SICSDataFactory",eError); return 0; } strtolower(argv[1]); strtolower(argv[2]); if(strcmp(argv[1],"new") == 0){ self = createSICSData(); if(self == NULL){ SCWrite(pCon,"ERROR: not enough memory to create SICSData",eError); return 0; } iRet = AddCommand(pSics,argv[2],SICSDataAction,KillSICSData, self); if(!iRet){ SCWrite(pCon,"ERROR: new SICSData not created due to name collision", eError); KillSICSData(self); return 0; } SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"del") == 0){ self = (pSICSData)FindCommandData(pSics,argv[2],"SICSData"); if(self == NULL){ SCWrite(pCon,"ERROR: SICSData to kill not found!",eError); return 0; } RemoveCommand(pSics,argv[2]); SCSendOK(pCon); return 1; } SCWrite(pCon,"ERROR: object command to SICSData not recognized",eError); return 0; }