491 lines
13 KiB
C
491 lines
13 KiB
C
/**
|
|
* This defines a couple of Tcl functions which allow to copy data from the
|
|
* nxdataset's returned from the swig Tcl interface to NeXus files into
|
|
* SICS data structures.
|
|
*
|
|
* copyright: see file COPYRIGHT
|
|
*
|
|
* Mark Koennecke, October 2007
|
|
*/
|
|
#include <sics.h>
|
|
#include "nxdataset.h"
|
|
#include "sicshipadaba.h"
|
|
#include "sicsdata.h"
|
|
#include "nxcopy.h"
|
|
#include "HistMem.h"
|
|
#include "macro.h"
|
|
/*-------------------------------------------------------------------------------
|
|
* decode a SWIG style pointer into the real pointer value.
|
|
* Stolen from SWIG generated code.
|
|
--------------------------------------------------------------------------------*/
|
|
static const char *SWIG_UnpackData(const char *c, void *ptr, size_t sz)
|
|
{
|
|
register unsigned char *u = (unsigned char *) ptr;
|
|
register const unsigned char *eu = u + sz;
|
|
for (; u != eu; ++u) {
|
|
register char d = *(c++);
|
|
register unsigned char uu;
|
|
if ((d >= '0') && (d <= '9'))
|
|
uu = ((d - '0') << 4);
|
|
else if ((d >= 'a') && (d <= 'f'))
|
|
uu = ((d - ('a' - 10)) << 4);
|
|
else
|
|
return (char *) 0;
|
|
d = *(c++);
|
|
if ((d >= '0') && (d <= '9'))
|
|
uu |= (d - '0');
|
|
else if ((d >= 'a') && (d <= 'f'))
|
|
uu |= (d - ('a' - 10));
|
|
else
|
|
return (char *) 0;
|
|
*u = uu;
|
|
}
|
|
return c;
|
|
}
|
|
|
|
/*-------------------------------------------------------------------------------*/
|
|
int isTypeAllowed(int type)
|
|
{
|
|
switch (type) {
|
|
case NX_INT32:
|
|
case NX_UINT32:
|
|
case NX_FLOAT32:
|
|
return 1;
|
|
break;
|
|
default:
|
|
return 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------------
|
|
* copy an nxdataset to a sicsdata object
|
|
--------------------------------------------------------------------------------*/
|
|
static int NXDataToSicsdata(ClientData clientData, Tcl_Interp * interp,
|
|
int objc, Tcl_Obj * CONST objv[])
|
|
{
|
|
Tcl_Obj *resultPtr;
|
|
const char *text;
|
|
pNXDS data = NULL;
|
|
pSICSData sicsData;
|
|
int length, i;
|
|
|
|
if (objc < 3) {
|
|
Tcl_WrongNumArgs(interp, objc, objv,
|
|
"Usage: nxdatatosicsdata nxdata sicsdata");
|
|
return TCL_ERROR;
|
|
}
|
|
resultPtr = Tcl_GetObjResult(interp);
|
|
|
|
/*
|
|
* get nxdataset pointer
|
|
*/
|
|
text = Tcl_GetStringFromObj(objv[1], NULL);
|
|
if (strstr(text, "NULL") != NULL) {
|
|
Tcl_SetStringObj(resultPtr, "nxdata argument is NULL pointer", 38);
|
|
return TCL_ERROR;
|
|
}
|
|
text++;
|
|
SWIG_UnpackData(text, &data, sizeof(void *));
|
|
|
|
if (data->magic != MAGIC) {
|
|
Tcl_SetStringObj(resultPtr, "nxdata argument is no valid nxdataset",
|
|
strlen("nxdata argument is no valid nxdataset"));
|
|
return TCL_ERROR;
|
|
}
|
|
length = getNXDatasetLength(data);
|
|
if (!isTypeAllowed(data->type)) {
|
|
Tcl_SetStringObj(resultPtr, "can only copy int and float types",
|
|
strlen("can only copy int and float types"));
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/*
|
|
* locate sicsdata
|
|
*/
|
|
text = Tcl_GetStringFromObj(objv[2], NULL);
|
|
sicsData =
|
|
(pSICSData) FindCommandData(pServ->pSics, (char *) text, "SICSData");
|
|
if (sicsData == NULL) {
|
|
Tcl_SetStringObj(resultPtr, "sicsdata argument is no valid SICSData",
|
|
strlen("sicsdata argument is no valid SICSData"));
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/*
|
|
* copy the data
|
|
*/
|
|
if (data->type == NX_FLOAT32) {
|
|
for (i = 0; i < length; i++) {
|
|
setSICSDataFloat(sicsData, i, data->u.fPtr[i]);
|
|
}
|
|
} else {
|
|
for (i = 0; i < length; i++) {
|
|
setSICSDataInt(sicsData, i, data->u.iPtr[i]);
|
|
}
|
|
}
|
|
|
|
return TCL_OK;
|
|
}
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
static hdbValue NXDatasetToHdbValue(pNXDS data)
|
|
{
|
|
hdbValue val;
|
|
int length, i;
|
|
|
|
length = getNXDatasetLength(data);
|
|
switch (getNXDatasetType(data)) {
|
|
case NX_INT32:
|
|
case NX_UINT32:
|
|
if (length == 1) {
|
|
val = MakeHdbInt(data->u.iPtr[0]);
|
|
} else {
|
|
val = MakeHdbIntArray(length, data->u.iPtr);
|
|
val.dataType = HIPINTVARAR;
|
|
}
|
|
break;
|
|
case NX_FLOAT32:
|
|
if (length == 1) {
|
|
val = MakeHdbFloat((double) data->u.fPtr[0]);
|
|
} else {
|
|
val = makeHdbValue(HIPFLOATAR, length);
|
|
for (i = 0; i < length; i++) {
|
|
val.v.floatArray[i] = (double) data->u.fPtr[i];
|
|
}
|
|
val.dataType = HIPFLOATVARAR;
|
|
}
|
|
break;
|
|
case NX_FLOAT64:
|
|
if (length == 1) {
|
|
val = MakeHdbFloat(data->u.dPtr[0]);
|
|
} else {
|
|
val = MakeHdbFloatArray(length, data->u.dPtr);
|
|
}
|
|
break;
|
|
case NX_CHAR:
|
|
case NX_INT8:
|
|
case NX_UINT8:
|
|
val = MakeHdbText(data->u.cPtr);
|
|
break;
|
|
case NX_INT16:
|
|
case NX_UINT16:
|
|
if (length == 1) {
|
|
val = MakeHdbInt((int) data->u.sPtr[0]);
|
|
} else {
|
|
val = makeHdbValue(HIPINTAR, length);
|
|
for (i = 0; i < length; i++) {
|
|
val.v.intArray[i] = (int) data->u.sPtr[i];
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
return val;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------
|
|
* copy the content of an nxdataset onto a Hipadaba node
|
|
*---------------------------------------------------------------------------*/
|
|
static int NXDataToHdbNode(ClientData clientData, Tcl_Interp * interp,
|
|
int objc, Tcl_Obj * CONST objv[])
|
|
{
|
|
pNXDS data = NULL;
|
|
Tcl_Obj *resultPtr;
|
|
int length, status;
|
|
const char *text;
|
|
pHdb node = NULL;
|
|
hdbValue val;
|
|
|
|
if (objc < 3) {
|
|
Tcl_WrongNumArgs(interp, objc, objv, "Usage: nxdatatohdb nxdata path");
|
|
return TCL_ERROR;
|
|
}
|
|
resultPtr = Tcl_GetObjResult(interp);
|
|
|
|
/*
|
|
* get nxdataset pointer
|
|
*/
|
|
text = Tcl_GetStringFromObj(objv[1], NULL);
|
|
if (strstr(text, "NULL") != NULL) {
|
|
Tcl_SetStringObj(resultPtr, "nxdata argument is NULL pointer", 38);
|
|
return TCL_ERROR;
|
|
}
|
|
text++;
|
|
SWIG_UnpackData(text, &data, sizeof(void *));
|
|
|
|
if (data->magic != MAGIC) {
|
|
Tcl_SetStringObj(resultPtr, "nxdata argument is no valid nxdataset",
|
|
strlen("nxdata argument is no valid nxdataset"));
|
|
return TCL_ERROR;
|
|
}
|
|
length = getNXDatasetLength(data);
|
|
|
|
/*
|
|
* locate node
|
|
*/
|
|
text = Tcl_GetStringFromObj(objv[2], NULL);
|
|
node = GetHipadabaNode(GetHipadabaRoot(), (char *) text);
|
|
if (node == NULL) {
|
|
Tcl_SetStringObj(resultPtr, "path does not point to a valid node",
|
|
strlen("path does not point to a valid node"));
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
val = NXDatasetToHdbValue(data);
|
|
status = UpdateHipadabaPar(node, val, NULL);
|
|
if (status != 1) {
|
|
Tcl_SetStringObj(resultPtr, "data type mismatch",
|
|
strlen("data type mismatch"));
|
|
return TCL_ERROR;
|
|
}
|
|
return TCL_OK;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int NXDataSend(ClientData clientData, Tcl_Interp *interp,
|
|
int objc, Tcl_Obj *CONST objv[])
|
|
{
|
|
Tcl_Obj *resultPtr;
|
|
pNXDS data = NULL;
|
|
SConnection *pCon = NULL;
|
|
char *sendName = NULL;
|
|
int *dataToSend = NULL;
|
|
int length, i;
|
|
const char *text;
|
|
char buffer[256];
|
|
|
|
if (objc < 3) {
|
|
Tcl_WrongNumArgs(interp, objc, objv, "Usage: nxdatasend nxdata sendname");
|
|
return TCL_ERROR;
|
|
}
|
|
resultPtr = Tcl_GetObjResult(interp);
|
|
|
|
/*
|
|
* get nxdataset pointer
|
|
*/
|
|
text = Tcl_GetStringFromObj(objv[1], NULL);
|
|
if (strstr(text, "NULL") != NULL) {
|
|
strncpy(buffer, "nxdata argument is NULL pointer", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
text++;
|
|
SWIG_UnpackData(text, &data, sizeof(void *));
|
|
|
|
if (data->magic != MAGIC) {
|
|
strncpy(buffer, "nxdata argument is no valid nxdataset" , sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
length = getNXDatasetLength(data);
|
|
|
|
/*
|
|
* get connection
|
|
*/
|
|
pCon = MacroPeek();
|
|
if(pCon == NULL){
|
|
strncpy(buffer, "connection not FOUND!", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/*
|
|
* get send name
|
|
*/
|
|
sendName = Tcl_GetStringFromObj(objv[2], NULL);
|
|
if (strstr(text, "NULL") != NULL) {
|
|
strncpy(buffer, "sendname argument is NULL pointer", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
dataToSend = malloc(length*sizeof(int));
|
|
if(dataToSend == NULL){
|
|
strncpy(buffer, "Out-of-memory in NXDataSend", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
switch(getNXDatasetType(data)){
|
|
case NX_INT32:
|
|
case NX_UINT32:
|
|
for(i = 0; i < length; i++){
|
|
dataToSend[i] = htonl(data->u.iPtr[i]);
|
|
}
|
|
break;
|
|
case NX_INT16:
|
|
case NX_UINT16:
|
|
for(i = 0; i < length; i++){
|
|
dataToSend[i] = htonl((int)data->u.sPtr[i]);
|
|
}
|
|
break;
|
|
default:
|
|
strncpy(buffer, "Datatype not supported", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
SCWriteZipped(pCon, sendName, dataToSend, length * sizeof(int));
|
|
free(dataToSend);
|
|
strncpy(buffer, "OK", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
|
|
return TCL_OK;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int NXDataSendBin(ClientData clientData, Tcl_Interp *interp,
|
|
int objc, Tcl_Obj *CONST objv[])
|
|
{
|
|
Tcl_Obj *resultPtr;
|
|
pNXDS data = NULL;
|
|
SConnection *pCon = NULL;
|
|
char *sendName = NULL;
|
|
int *dataToSend = NULL;
|
|
int length, i;
|
|
const char *text;
|
|
char buffer[256];
|
|
|
|
if (objc < 3) {
|
|
Tcl_WrongNumArgs(interp, objc, objv, "Usage: nxdatasend nxdata sendname");
|
|
return TCL_ERROR;
|
|
}
|
|
resultPtr = Tcl_GetObjResult(interp);
|
|
|
|
/*
|
|
* get nxdataset pointer
|
|
*/
|
|
text = Tcl_GetStringFromObj(objv[1], NULL);
|
|
if (strstr(text, "NULL") != NULL) {
|
|
strncpy(buffer, "nxdata argument is NULL pointer", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
text++;
|
|
SWIG_UnpackData(text, &data, sizeof(void *));
|
|
|
|
if (data->magic != MAGIC) {
|
|
strncpy(buffer, "nxdata argument is no valid nxdataset" , sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
length = getNXDatasetLength(data);
|
|
|
|
/*
|
|
* get connection
|
|
*/
|
|
pCon = MacroPeek();
|
|
if(pCon == NULL){
|
|
strncpy(buffer, "connection not FOUND!", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
/*
|
|
* get send name
|
|
*/
|
|
sendName = Tcl_GetStringFromObj(objv[2], NULL);
|
|
if (strstr(text, "NULL") != NULL) {
|
|
strncpy(buffer, "sendname argument is NULL pointer", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
dataToSend = malloc(length*sizeof(int));
|
|
if(dataToSend == NULL){
|
|
strncpy(buffer, "Out-of-memory in NXDataSend", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
switch(getNXDatasetType(data)){
|
|
case NX_INT32:
|
|
case NX_UINT32:
|
|
for(i = 0; i < length; i++){
|
|
dataToSend[i] = htonl(data->u.iPtr[i]);
|
|
}
|
|
break;
|
|
case NX_INT16:
|
|
case NX_UINT16:
|
|
for(i = 0; i < length; i++){
|
|
dataToSend[i] = htonl((int)data->u.sPtr[i]);
|
|
}
|
|
break;
|
|
default:
|
|
strncpy(buffer, "Datatype not supported", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
return TCL_ERROR;
|
|
}
|
|
SCWriteBinary(pCon, sendName, dataToSend, length * sizeof(int));
|
|
free(dataToSend);
|
|
strncpy(buffer, "OK", sizeof(buffer));
|
|
Tcl_SetStringObj(resultPtr,buffer,strlen(buffer));
|
|
|
|
return TCL_OK;
|
|
}
|
|
/*---------------------------------------------------------------------------*/
|
|
static int NXDataToHM(ClientData clientData, Tcl_Interp * interp,
|
|
int objc, Tcl_Obj * CONST objv[])
|
|
{
|
|
pNXDS data = NULL;
|
|
Tcl_Obj *resultPtr;
|
|
int length, status;
|
|
const char *text;
|
|
pHistMem pHM = NULL;
|
|
SConnection *pCon = NULL;
|
|
|
|
if (objc < 3) {
|
|
Tcl_WrongNumArgs(interp, objc, objv, "Usage: nxdatatohdb nxdata path");
|
|
return TCL_ERROR;
|
|
}
|
|
resultPtr = Tcl_GetObjResult(interp);
|
|
|
|
/*
|
|
* get nxdataset pointer
|
|
*/
|
|
text = Tcl_GetStringFromObj(objv[1], NULL);
|
|
if (strstr(text, "NULL") != NULL) {
|
|
Tcl_SetStringObj(resultPtr, "nxdata argument is NULL pointer", 38);
|
|
return TCL_ERROR;
|
|
}
|
|
text++;
|
|
SWIG_UnpackData(text, &data, sizeof(void *));
|
|
|
|
if (data->magic != MAGIC) {
|
|
Tcl_SetStringObj(resultPtr, "nxdata argument is no valid nxdataset",
|
|
strlen("nxdata argument is no valid nxdataset"));
|
|
return TCL_ERROR;
|
|
}
|
|
length = getNXDatasetLength(data);
|
|
|
|
/*
|
|
* get HM
|
|
*/
|
|
text = Tcl_GetStringFromObj(objv[2], NULL);
|
|
pHM = (pHistMem) FindCommandData(pServ->pSics, (char *) text, "HistMem");
|
|
if (pHM == NULL) {
|
|
Tcl_SetStringObj(resultPtr, "hm argument is not histogram memory",
|
|
strlen("hm argument is not histogram memory"));
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
if (getNXDatasetType(data) != NX_INT32 || GetHistLength(pHM) < length) {
|
|
Tcl_SetStringObj(resultPtr, "data to hm type or length mismatch",
|
|
strlen("data to hm type or length mismatch"));
|
|
return TCL_ERROR;
|
|
}
|
|
|
|
pCon = SCCreateDummyConnection(pServ->pSics);
|
|
SetHistogram(pHM, pCon, 0, 0, length, data->u.iPtr);
|
|
SCDeleteConnection(pCon);
|
|
|
|
return TCL_OK;
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
int NXcopy_Init(Tcl_Interp * pInter)
|
|
{
|
|
Tcl_CreateObjCommand(pInter, "nxToSicsData", NXDataToSicsdata, NULL,
|
|
NULL);
|
|
Tcl_CreateObjCommand(pInter, "nxToHdb", NXDataToHdbNode, NULL, NULL);
|
|
Tcl_CreateObjCommand(pInter, "nxToHM", NXDataToHM, NULL, NULL);
|
|
Tcl_CreateObjCommand(pInter, "nxSend", NXDataSend, NULL, NULL);
|
|
Tcl_CreateObjCommand(pInter, "nxSendBin", NXDataSendBin, NULL, NULL);
|
|
return 1;
|
|
}
|