/** * 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 #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; }