From 9eca96b064130c0ab60fe323b44db8c9b6020fdb Mon Sep 17 00:00:00 2001 From: koennecke Date: Thu, 29 Mar 2012 08:41:05 +0000 Subject: [PATCH] - Fixes to make SL6 work - New NeXus libraries - Added new raw binary transfer mode for mass data - Added a check script option to configurable virtual motor SKIPPED: psi/dumprot.c psi/make_gen psi/psi.c psi/rebin.c psi/sanslirebin.c --- asynnet.c | 6 +- confvirtmot.h | 9 +- confvirtmot.i | 25 +- confvirtualmot.c | 40 +- confvirtualmot.w | 2 + conman.c | 156 ++ conman.h | 4 +- fourmess.c | 10 +- hipadaba.c | 3 + hkl.c | 106 +- hmdata.c | 6 +- lld.c | 2 +- macro.c | 22 +- macro.h | 1 + make_gen | 5 +- makefile_slinux | 11 +- motorlist.c | 4 +- mumo.c | 4 +- napi.c | 2594 +++++++++++++++++++------------ napi.h | 963 +++++++++--- napi4.c | 3504 +++++++++++++++++++++--------------------- napi4.h | 96 +- napi5.c | 3778 +++++++++++++++++++++++++--------------------- napi5.h | 85 +- napiconfig.h | 32 +- napiu.c | 208 ++- nread.c | 5 +- nx_stptok.h | 6 + nxcopy.c | 186 ++- nxdataset.c | 242 ++- nxdataset.h | 62 +- nxdict.c | 109 +- nxinter_wrap.c | 6 +- nxinterhelper.c | 24 +- nxio.c | 651 ++++---- nxio.h | 20 +- nxscript.c | 2 +- nxstack.c | 113 +- nxstack.h | 16 +- nxxml.c | 1836 +++++++++++++--------- nxxml.h | 90 +- protocol.c | 6 +- reflist.c | 23 +- scriptcontext.c | 2 +- sicshipadaba.c | 36 +- simidx.c | 33 - simindex.c | 4 +- singlenb.c | 2 +- singlex.c | 15 + singlex.h | 2 +- sllinux_def | 2 +- stdscan.c | 29 +- tasdrive.c | 2 + test/DataNumber | 2 +- trace.c | 4 +- ubcalc.c | 2 +- 56 files changed, 8881 insertions(+), 6327 deletions(-) create mode 100644 nx_stptok.h diff --git a/asynnet.c b/asynnet.c index ad7e9c85..78d022c3 100644 --- a/asynnet.c +++ b/asynnet.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -43,7 +44,8 @@ #define DATASOCKET 1 #define MAXCONNECTIONS 1024 #define RBUFFERSIZE 262144 /* 256kb */ -#define WBUFFERSIZE 20*262144 /* */ +#define WBUFFERSIZE 20*262144 +/* #define WBUFFERSIZE 100*262144 /* /*--------------------------------------------------------------------------*/ typedef struct { int socket; @@ -198,6 +200,8 @@ int ANETregisterSocket(int socket) if (status < 0) { return ANETSOCKERROR; } + flags =1; + setsockopt(socket,IPPROTO_TCP,TCP_NODELAY,(char *) &flags, sizeof(int)); socke.readBuffer = MakeRWPuffer(RBUFFERSIZE); socke.writeBuffer = MakeRWPuffer(WBUFFERSIZE); if (socke.readBuffer == NULL || socke.writeBuffer == NULL) { diff --git a/confvirtmot.h b/confvirtmot.h index a9fa2c44..6eb132bc 100644 --- a/confvirtmot.h +++ b/confvirtmot.h @@ -13,8 +13,9 @@ #include "sics.h" -int MakeConfigurableVirtualMotor(SConnection * pCon, SicsInterp * pSics, - void *data, int aargc, char *argv[]); -int ConfigurableVirtualMotorAction(SConnection * pCon, SicsInterp * pSics, - void *data, int argc, char *argv[]); +int MakeConfigurableVirtualMotor(SConnection *pCon, SicsInterp *pSics, + void *data, int aargc, char *argv[]); +int ConfigurableVirtualMotorAction(SConnection *pCon, SicsInterp *pSics, + void *data, int argc, char *argv[]); #endif + diff --git a/confvirtmot.i b/confvirtmot.i index d2ea3dec..2ebd6187 100644 --- a/confvirtmot.i +++ b/confvirtmot.i @@ -5,18 +5,19 @@ -----------------------------------------------------------------------*/ typedef struct __CONFVIRTMOT { - pObjectDescriptor pDes; - pIDrivable pDriv; - pICallBack pCall; - char *name; - char *scriptName; - char *readScript; - int motorList; - float targetValue; - int targetReached; - int posCount; - char scriptError[512]; - int parseOK; + pObjectDescriptor pDes; + pIDrivable pDriv; + pICallBack pCall; + char *name; + char *scriptName; + char *readScript; + char *checkScript; + int motorList; + float targetValue; + int targetReached; + int posCount; + char scriptError[512]; + int parseOK; }ConfigurableVirtualMotor, *pConfigurableVirtualMotor; diff --git a/confvirtualmot.c b/confvirtualmot.c index 74bcb0e4..8087dfe6 100644 --- a/confvirtualmot.c +++ b/confvirtualmot.c @@ -289,7 +289,24 @@ static int InterestCallback(int iEvent, void *pEvent, void *pUser) } return 1; } +/*---------------------------------------------------------------------*/ +static void invokeCheckScript(pConfigurableVirtualMotor self, + SConnection * pCon) +{ + Tcl_Interp *pTcl; + int status; + pTcl = InterpGetTcl(pServ->pSics); + + if(self->checkScript != NULL){ + status = Tcl_Eval(pTcl, self->readScript); + if (status != TCL_OK) { + snprintf(self->scriptError, 510, "ERROR: Tcl subsystem reported %s", + Tcl_GetStringResult(pTcl)); + SCWrite(pCon, self->scriptError, eError); + } + } +} /*------------------------------------------------------------------------*/ static int ConfCheckStatus(void *pData, SConnection * pCon) { @@ -327,6 +344,7 @@ static int ConfCheckStatus(void *pData, SConnection * pCon) } if (result == HWIdle) { + invokeCheckScript(self,pCon); event.pName = self->name; event.fVal = self->pDriv->GetValue(self, pCon); InvokeCallBack(self->pCall, MOTDRIVE, &event); @@ -575,6 +593,26 @@ int ConfigurableVirtualMotorAction(SConnection * pCon, SicsInterp * pSics, return 1; } } + } else if (strcmp(argv[1], "checkscript") == 0) { + if (argc > 2) { + /* set case */ + Arg2Text(argc - 2, &argv[2], pBueffel, 510); + self->checkScript = strdup(pBueffel); + SCSendOK(pCon); + return 1; + } else { + /* inquiry */ + if (self->checkScript == NULL) { + snprintf(pBueffel, 510, "%s.checkscript = UNDEFINED", argv[0]); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else { + snprintf(pBueffel, 510, "%s.checkscript = %s", argv[0], + self->checkScript); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } } else if (strcmp(argv[1], "interest") == 0) { pRegInfo = (pRegisteredInfo) malloc(sizeof(RegisteredInfo)); if (!pRegInfo) { @@ -584,7 +622,7 @@ int ConfigurableVirtualMotorAction(SConnection * pCon, SicsInterp * pSics, pRegInfo->pName = strdup(argv[0]); pRegInfo->pCon = SCCopyConnection(pCon); value = ConfGetValue(self, pCon); - if (!iRet) { + if (value < -9990.) { snprintf(pBueffel,511, "Failed to register interest, Reason:Error obtaining current position for %s", argv[0]); diff --git a/confvirtualmot.w b/confvirtualmot.w index 5a8110da..4e475465 100644 --- a/confvirtualmot.w +++ b/confvirtualmot.w @@ -16,6 +16,7 @@ typedef struct __CONFVIRTMOT { char *name; char *scriptName; char *readScript; + char *checkScript; int motorList; float targetValue; int targetReached; @@ -33,6 +34,7 @@ The fields are: \item[scriptName] The name of the program to calculate the new positions of the real motors. \item[readScript] A script to read back the current value of the virtual motor. +\item[checkScript] A script to check for success at the end of driving. \item[motorList] A list of the motors to start and control. \item[targetValue] The target value we wanted to have. \item[posCount] This counter prevents the callback from being invoked too often. The frequency is currently set to every 10 cycles through the task loop. diff --git a/conman.c b/conman.c index c4d5ad78..9d01496c 100644 --- a/conman.c +++ b/conman.c @@ -1066,6 +1066,162 @@ int SCWriteUUencoded(SConnection * pCon, char *pName, void *pData, #define ZIPBUF 8192 int SCWriteZipped(SConnection * self, char *pName, void *pData, int iDataLen) +{ + char outBuf[65536], *pBuf = NULL, noutBuf[ZIPBUF], *pHeader = NULL; + int compressedLength, iRet, iRet2, iCount, protocolID; + z_stream compStream; + commandContext cc; + + /* check for a valid connection */ + if (!VerifyConnection(self)) { + return 0; + } + + /* a telnet connection will corrupt the compressed stream, so + stop it! + */ + if (self->iTelnet) { + SCWrite(self, + "ERROR: the telnet protocol will corrupt compressed data!", + eError); + return 0; + } + + /* + do nothing if no data + */ + if (pName == NULL || pData == NULL) { + SCWrite(self, "ERROR: no data to write in SCWriteZiped", eError); + return 0; + } + pBuf = malloc(iDataLen*sizeof(char)); + memset(pBuf,0,iDataLen*sizeof(char)); + + compStream.zalloc = (alloc_func) NULL; + compStream.zfree = (free_func) NULL; + compStream.opaque = (voidpf) NULL; +/* iRet = deflateInit(&compStream, Z_DEFAULT_COMPRESSION); */ + iRet = deflateInit(&compStream, 2); + if (iRet != Z_OK) { + sprintf(outBuf, "ERROR: zlib error: %d", iRet); + SCWrite(self, outBuf, eError); + return 0; + } + + compStream.next_in = (Bytef *) pData; + compStream.next_out = (Bytef *) pBuf; + compStream.avail_in = iDataLen; + compStream.avail_out = iDataLen; + iRet = deflate(&compStream, Z_FINISH); + if (iRet != Z_STREAM_END) { + sprintf(outBuf, "ERROR: zlib error: %d", iRet); + SCWrite(self, outBuf, eError); + return 0; + } + compressedLength = compStream.total_out; + + + /* write header line */ + memset(outBuf, 0, 65536); + + protocolID = GetProtocolID(self); + if (protocolID == 5) { + cc = SCGetContext(self); + sprintf(outBuf, "SICSBIN ZIP %s %d %d\r\n", pName, + compressedLength, cc.transID); + } else { + sprintf(outBuf, "SICSBIN ZIP %s %d \r\n", pName, compressedLength); + } + pHeader = strdup(outBuf); + if (pHeader == NULL) { + SCWrite(self, "ERROR: out of memory in SCWriteZipped", eError); + return 0; + } + traceCommand(ConID(self),"out:SICSBIN ZIP %s %d", pName, compressedLength); + + + iRet = ANETwrite(self->sockHandle, pHeader, strlen(pHeader)); + iRet = ANETwrite(self->sockHandle, pBuf, compStream.total_out); + if (iRet != 1) { + sprintf(outBuf, "ERROR: network error %d on zipped send", iRet); + SCWrite(self, outBuf, eError); + return 0; + } + /* printf("Sent zipped data: %s with %d\n", pHeader, iRet); */ + + deflateEnd(&compStream); + free(pHeader); + free(pBuf); + + return 1; +} +/*------------------------------------------------------------------*/ +int SCWriteBinary(SConnection * self, char *pName, void *pData, + int iDataLen) +{ + char outBuf[65536], *pHeader = NULL; + int iRet, iRet2, iCount, protocolID; + commandContext cc; + + /* check for a valid connection */ + if (!VerifyConnection(self)) { + return 0; + } + + /* a telnet connection will corrupt the compressed stream, so + stop it! + */ + if (self->iTelnet) { + SCWrite(self, + "ERROR: the telnet protocol will corrupt compressed data!", + eError); + return 0; + } + + /* + do nothing if no data + */ + if (pName == NULL || pData == NULL) { + SCWrite(self, "ERROR: no data to write in SCWriteZiped", eError); + return 0; + } + + /* write header line */ + memset(outBuf, 0, 65536); + + protocolID = GetProtocolID(self); + if (protocolID == 5) { + cc = SCGetContext(self); + sprintf(outBuf, "SICSBIN BIN %s %d %d\r\n", pName, + iDataLen, cc.transID); + } else { + sprintf(outBuf, "SICSBIN BIN %s %d \r\n", pName, iDataLen); + } + pHeader = strdup(outBuf); + if (pHeader == NULL) { + SCWrite(self, "ERROR: out of memory in SCWriteBinary", eError); + return 0; + } + traceCommand(ConID(self),"out:SICSBIN BIN %s %d", pName, iDataLen); + + iRet = ANETwrite(self->sockHandle, pHeader, strlen(pHeader)); + iRet = ANETwrite(self->sockHandle, pData, iDataLen); + if (iRet != 1) { + sprintf(outBuf, "ERROR: network error %d on zipped send", iRet); + SCWrite(self, outBuf, eError); + return 0; + } + /* printf("Sent zipped data: %s with %d\n", pHeader, iRet); */ + + free(pHeader); + + return 1; +} +/*-------------------------------------------------------------- + * left in for documentation............ + */ +int SCWriteZippedOld(SConnection * self, char *pName, void *pData, + int iDataLen) { char outBuf[65546], *pBuf = NULL, noutBuf[ZIPBUF], *pHeader = NULL; int compressedLength, iRet, iRet2, iCount, protocolID; diff --git a/conman.h b/conman.h index b2c96bd2..27561052 100644 --- a/conman.h +++ b/conman.h @@ -15,7 +15,7 @@ copyright: see copyright.h - substantially for the new asynchronous I/O system + substantially revised for the new asynchronous I/O system Mark Koennecke, January 2009 ----------------------------------------------------------------------------*/ @@ -100,6 +100,8 @@ int SCWriteUUencoded(SConnection * pCon, char *pName, void *iData, int iLen); int SCWriteZipped(SConnection * pCon, char *pName, void *pData, int iDataLen); +int SCWriteBinary(SConnection * pCon, char *pName, void *pData, + int iDataLen); writeFunc SCGetWriteFunc(SConnection * pCon); void SCSetWriteFunc(SConnection * pCon, writeFunc x); int SCOnlySockWrite(SConnection * self, char *buffer, int iOut); diff --git a/fourmess.c b/fourmess.c index bf09019c..d54b0e59 100644 --- a/fourmess.c +++ b/fourmess.c @@ -877,7 +877,7 @@ static int SortRef(pSICSOBJ self, SConnection * pCon, pHdb commandNode, static int SortRefNew(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { - double *sortlist, d, lambda, om, hkl[4], ang[4]; + double *sortlist, d, lambda, om, hkl[4], ang[5]; const double *cell; double *hklc; int nRefl, i, j, status, count; @@ -916,6 +916,12 @@ static int SortRefNew(pSICSOBJ self, SConnection * pCon, pHdb commandNode, * 10. */ hkl[3] = ang[2]+10 + 0.1 * ang[0]; + } else if(mode == BiNB){ + /* + * sort for nu in the first place. In order to cope with negativity, add + * 10. + */ + hkl[3] = ang[4]+10 + 0.1 * ang[0]; } else { hkl[3] = ang[0]; } @@ -1007,7 +1013,7 @@ static int ReadTour(pSICSOBJ self, SConnection * pCon, pHdb commandNode, { FILE *fd = NULL; char buffer[132]; - double hkl[4], ang[4]; + double hkl[4], ang[5]; int idx, tour; pFourMess priv = self->pPrivate; pSingleDiff diffi = NULL; diff --git a/hipadaba.c b/hipadaba.c index 220a243e..ea862a6b 100644 --- a/hipadaba.c +++ b/hipadaba.c @@ -974,9 +974,12 @@ int copyHdbValue(hdbValue * source, hdbValue * target) 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: diff --git a/hkl.c b/hkl.c index 82c74d60..b4030f8b 100644 --- a/hkl.c +++ b/hkl.c @@ -395,13 +395,13 @@ int hklInRange(void *data, double fSet[4], int mask[4]) often restricted due to the cryogenic garbage around the sample. -------------------------------------------------------------------------*/ int CalculateSettings(pHKL self, float fHKL[3], float fPsi, int iHamil, - float fSet[4], SConnection * pCon) + float fSet[5], SConnection * pCon) { char pBueffel[512]; double myPsi = fPsi; int i, status; pSingleDiff single = NULL; - double dHkl[4], dSet[4]; + double dHkl[4], dSet[5]; /* catch shitty input */ if ((fHKL[0] == 0.) && (fHKL[1] == 0.) && (fHKL[2] == 0.)) { @@ -422,7 +422,7 @@ int CalculateSettings(pHKL self, float fHKL[3], float fPsi, int iHamil, dHkl[3] = myPsi; status = single->calculateSettings(single, dHkl, dSet); - for (i = 0; i < 4; i++) { + for (i = 0; i < 5; i++) { fSet[i] = dSet[i]; } @@ -446,17 +446,17 @@ void stopHKLMotors(pHKL self) } /*------------------------------------------------------------------------*/ -int startHKLMotors(pHKL self, SConnection * pCon, float fSet[4]) +int startHKLMotors(pHKL self, SConnection * pCon, float fSet[5]) { char pBueffel[512]; pSingleDiff single = NULL; - double dSet[4]; + double dSet[5]; int i, status; single = SXGetDiffractometer(); assert(single != NULL); - for (i = 0; i < 4; i++) { + for (i = 0; i < 5; i++) { dSet[i] = fSet[i]; } single->settingsToList(single, dSet); @@ -471,7 +471,7 @@ int startHKLMotors(pHKL self, SConnection * pCon, float fSet[4]) int RunHKL(pHKL self, float fHKL[3], float fPsi, int iHamil, SConnection * pCon) { - float fSet[4]; + float fSet[5]; int iRet, i; char pBueffel[512]; pDummy pDum; @@ -496,7 +496,7 @@ int RunHKL(pHKL self, float fHKL[3], } /*-------------------------------------------------------------------------*/ -int DriveSettings(pHKL self, float fSet[4], SConnection * pCon) +int DriveSettings(pHKL self, float fSet[5], SConnection * pCon) { int iRet; @@ -579,77 +579,6 @@ int DriveHKL(pHKL self, float fHKL[3], return iReturn; } -/*----------------------------------------------------------------------- - * This is only used in mesure, remove when mesure can be killed - * ----------------------------------------------------------------------*/ -int GetCurrentPosition(pHKL self, SConnection * pCon, float fPos[4]) -{ - float fVal; - int iRet, iResult; - pMotor pTheta, pOmega, pChi, pPhi, pNu; - - pTheta = SXGetMotor(TwoTheta); - pOmega = SXGetMotor(Omega); - pChi = SXGetMotor(Chi); - pPhi = SXGetMotor(Phi); - if (pTheta == NULL || pOmega == NULL || pChi == NULL || pPhi == NULL) { - SCWrite(pCon, - "ERROR: configuration problem, stt,om,chi,phi motors not found,", - eError); - return 0; - } - - assert(self); - assert(pCon); - - iResult = 1; - iRet = MotorGetSoftPosition(pTheta, pCon, &fVal); - if (iRet == 1) { - fPos[0] = fVal; - } else { - iResult = 0; - } - iRet = MotorGetSoftPosition(pOmega, pCon, &fVal); - if (iRet == 1) { - fPos[1] = fVal; - } else { - iResult = 0; - } - - /* normal beam geometry */ - if (SXGetMode() == NB) { - pNu = SXGetMotor(Nu); - if (pNu) { - SCWrite(pCon, "ERROR: configuration problem, nu motor not found,", - eError); - return 0; - } - iRet = MotorGetSoftPosition(pNu, pCon, &fVal); - if (iRet == 1) { - fPos[2] = fVal; - } else { - iResult = 0; - } - return iResult; - } - - /* bissecting geometry */ - iRet = MotorGetSoftPosition(pChi, pCon, &fVal); - if (iRet == 1) { - fPos[2] = fVal; - } else { - iResult = 0; - } - iRet = MotorGetSoftPosition(pPhi, pCon, &fVal); - if (iRet == 1) { - fPos[3] = fVal; - } else { - iResult = 0; - } - - return iResult; -} - /*------------------------------------------------------------------------- For the conversion from angles to HKL. -------------------------------------------------------------------------*/ @@ -803,14 +732,15 @@ int HKLAction(SConnection * pCon, SicsInterp * pSics, void *pData, int iRet, i, iHamil; char pBueffel[512]; float fUB[9], fPsi, fVal; - float fHKL[3], fSet[4]; - double dHKL[3], dSet[4]; + float fHKL[3], fSet[5]; + double dHKL[3], dSet[5]; double dVal, lambda, stt; const double *dUB; pHKL self = NULL; CommandList *pCom = NULL; pDummy pDum = NULL; pSingleDiff single = NULL; + int mode, nargs; assert(pCon); assert(pSics); @@ -857,13 +787,19 @@ int HKLAction(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, pBueffel, eValue); return 1; } else if (strcmp(argv[1], "fromangles") == 0) { - if (argc < 6) { + mode = SXGetMode(); + if(mode == BiNB) { + nargs = 7; + } else { + nargs = 6; + } + if (argc < nargs) { SCWrite(pCon, "ERROR: need stt, om, chi,phi to calculate HKL from angles", eError); return 0; } - for (i = 0; i < 4; i++) { + for (i = 0; i < nargs-2; i++) { iRet = Tcl_GetDouble(InterpGetTcl(pSics), argv[i + 2], &dVal); if (iRet != TCL_OK) { snprintf(pBueffel, 511, "ERROR: failed to convert %s to number", @@ -1031,6 +967,10 @@ int HKLAction(SConnection * pCon, SicsInterp * pSics, void *pData, snprintf(pBueffel,sizeof(pBueffel)-1, " gamma = %f, omega = %f, nu = %f", fSet[0], fSet[1], fSet[2]); SCWrite(pCon, pBueffel, eValue); + } else if(SXGetMode() == BiNB){ + snprintf(pBueffel,sizeof(pBueffel)-1, " 2-theta = %f, omega = %f, chi = %f, phi = %f, nu = %f", + fSet[0], fSet[1], fSet[2], fSet[3], fSet[4]); + SCWrite(pCon, pBueffel, eValue); } else { snprintf(pBueffel,sizeof(pBueffel)-1, " 2-theta = %f, omega = %f, chi = %f, phi = %f", fSet[0], fSet[1], fSet[2], fSet[3]); diff --git a/hmdata.c b/hmdata.c index ac6ca649..cc801e8c 100644 --- a/hmdata.c +++ b/hmdata.c @@ -563,7 +563,7 @@ static pNXDS hmDataToNXDataset(pHMdata self) static pNXDS subSampleCommand(pNXDS source, char *command, char *error, int errLen) { - int startDim[NX_MAXRANK], endDim[NX_MAXRANK]; + int64_t startDim[NX_MAXRANK], endDim[NX_MAXRANK]; int dim = 0, start = 0, i; char *pPtr = NULL, token[80]; @@ -590,12 +590,12 @@ static pNXDS subSampleCommand(pNXDS source, char *command, if (startDim[i] < 0 || startDim[i] >= source->dim[i]) { snprintf(error, errLen, "ERROR: invalid start value %d for dimension %d", - startDim[1], i); + (int)startDim[1], i); return NULL; } if (endDim[i] < startDim[i] || endDim[i] >= source->dim[i]) { snprintf(error, errLen, - "ERROR: invalid end value %d for dimension %d", endDim[1], + "ERROR: invalid end value %d for dimension %d", (int)endDim[1], i); return NULL; } diff --git a/lld.c b/lld.c index 9270fc35..18d2f5ae 100644 --- a/lld.c +++ b/lld.c @@ -582,7 +582,7 @@ int LLDnodePtr2Next(int List) } /* to point at the dummy tail node ... */ ListControl[List].current = ListControl[List].current->next; - return 1; + return 1; } int LLDnodePtr2Prev(int List) diff --git a/macro.c b/macro.c index ea2bd798..a5f265f1 100644 --- a/macro.c +++ b/macro.c @@ -119,6 +119,12 @@ int MacroPop(void) return 1; } /*---------------------------------------------------------------------------*/ +SConnection *MacroPeek(void) +{ + assert(pUnbekannt); + return pUnbekannt->pCon[pUnbekannt->iStack]; +} +/*---------------------------------------------------------------------------*/ static int SicsUnknownProc(ClientData pData, Tcl_Interp * pInter, int argc, char *argv[]) { @@ -269,11 +275,10 @@ static void KillExec(ClientData data) } } -/*------------------------------------------------------------------------ - This is in the Tcl sources -*/ -extern int Tcl_ExecObjCmd(ClientData data, Tcl_Interp * interp, - int objc, Tcl_Obj * CONST objv[]); +/*-----------------------------------------------------------------------*/ +/* static Tcl_ObjCmdProc oldExec = NULL; */ +static int (*oldExec)(ClientData clientData,Tcl_Interp *interp, + int objc,Tcl_Obj *const objv[] ) = NULL; /*-----------------------------------------------------------------------*/ static int ProtectedExec(ClientData clientData, Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[]) @@ -281,13 +286,13 @@ static int ProtectedExec(ClientData clientData, Tcl_Interp * interp, char *test = NULL; if (objc < 2) { - return Tcl_ExecObjCmd(clientData, interp, objc, objv); + return oldExec(clientData, interp, objc, objv); } test = Tcl_GetStringFromObj(objv[1], NULL); if (allowedCommands != NULL) { if (StringDictExists(allowedCommands, test)) { - return Tcl_ExecObjCmd(clientData, interp, objc, objv); + return oldExec(clientData, interp, objc, objv); } } @@ -313,6 +318,7 @@ Tcl_Interp *MacroInit(SicsInterp * pSics) FILE *fp = NULL; char pBueffel[512]; int iRet; + Tcl_CmdInfo execInfo; assert(pSics); @@ -338,6 +344,8 @@ Tcl_Interp *MacroInit(SicsInterp * pSics) Tcl_DeleteCommand(pInter, "exit"); Tcl_DeleteCommand(pInter, "socket"); Tcl_DeleteCommand(pInter, "vwait"); + Tcl_GetCommandInfo(pInter,"exec",&execInfo); + oldExec = execInfo.objProc; Tcl_DeleteCommand(pInter, "exec"); /* diff --git a/macro.h b/macro.h index f39c5346..166e25c0 100644 --- a/macro.h +++ b/macro.h @@ -50,6 +50,7 @@ int AllowExec(SConnection * pCon, SicsInterp * pInter, void *pData, */ int MacroPush(SConnection * pCon); int MacroPop(void); +SConnection *MacroPeek(void); void KillSicsUnknown(void); diff --git a/make_gen b/make_gen index 1e53fdf7..70253df2 100644 --- a/make_gen +++ b/make_gen @@ -41,7 +41,8 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ sgclib.o sgfind.o sgio.o sgsi.o sghkl.o singlediff.o singlebi.o \ singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.o \ rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \ - histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o + histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\ + singlebinb.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o @@ -64,7 +65,7 @@ all: libmat libhlib libtecsl libpsi SICServer full: purge all SICServer: $(OBJ) $(SUBLIBS) - $(CC) -g -o SICServer $(OBJ) $(LIBS) + $(CC) -g -o SICServer $(OBJ) $(LIBS) matrix/libmatrix.a: libmat diff --git a/makefile_slinux b/makefile_slinux index 8ac74d63..3602a289 100644 --- a/makefile_slinux +++ b/makefile_slinux @@ -9,13 +9,13 @@ SINQDIR=/afs/psi.ch/project/sinq NI= -DHAVENI NIOBJ= nigpib.o -NILIB=$(SINQDIR)/sl5/lib/cib.o +NILIB=$(SINQDIR)/sl6/lib/cib.o include sllinux_def CC = gcc -CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF4 -DHDF5 $(NI) \ - -Ipsi/hardsup -I. -MMD \ +CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF5 $(NI) \ + -Ipsi/hardsup -I. -MMD \ -Werror -DCYGNUS -DNONINTF -g $(DFORTIFY) \ -Wall -Wno-unused -Wunused-value -Wno-comment -Wno-switch @@ -25,10 +25,9 @@ SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \ psi/tecs/libtecsl.a LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\ -ltcl $(HDFROOT)/lib/libhdf5.a \ - $(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \ - $(HDFROOT)/lib/libjpeg.a $(HDFROOT)/lib/libsz.a \ + $(HDFROOT)/lib/libsz.a \ $(HDFROOT)/lib/libjson.a \ - -ldl -lz -lmxml $(HDFROOT)/lib/libghttp.a -lm -lc + -ldl -lz $(HDFROOT)/lib/libmxml.a $(HDFROOT)/lib/libghttp.a -lm -lc -lpthread include make_gen diff --git a/motorlist.c b/motorlist.c index a22c916b..6b13531e 100644 --- a/motorlist.c +++ b/motorlist.c @@ -145,8 +145,8 @@ static int MOLICheckStatus(void *data, SConnection * pCon) return result; } /*--------------------------------------------------------- - A special version for EIGER. I am coutious: I have problems - with this at EIGER but I do not want to propogate the fix + A special version for EIGER. I am cautious: I have problems + with this at EIGER but I do not want to propagate the fix elsewhere even if it may be the right thing to do. -----------------------------------------------------------*/ int MOLIEigerStatus(void *data, SConnection * pCon) diff --git a/mumo.c b/mumo.c index e5dcc621..94ae6139 100644 --- a/mumo.c +++ b/mumo.c @@ -460,7 +460,7 @@ const char *FindNamPos(pMulMot self, SConnection * pCon) int iRet, iTest; char pCurrCommand[1064], pTestCommand[1064]; const char *pAlias; - char *pName, *pVal; + char *pVal, *pName; float f1, f2; pMotor pMot = NULL; pStringDict motCache = NULL; @@ -481,7 +481,7 @@ const char *FindNamPos(pMulMot self, SConnection * pCon) iRet = MotorGetSoftPosition(pMot, pCon, &f1); if (!iRet) { snprintf(pTestCommand,sizeof(pTestCommand)-1, - "ERROR: failed to get motor position for %s", pName); + "ERROR: failed to get motor position for %s", pMot->name); SCWrite(pCon, pTestCommand, eError); return NULL; } diff --git a/napi.c b/napi.c index d229d0b6..921d618f 100644 --- a/napi.c +++ b/napi.c @@ -19,11 +19,11 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see ----------------------------------------------------------------------------*/ -static const char *rscid = "$Id: napi.c,v 1.15 2009/02/13 09:00:20 koennecke Exp $"; /* Revision inserted by CVS */ +static const char* rscid = "$Id: napi.c,v 1.16 2012/03/29 08:41:05 koennecke Exp $"; /* Revision inserted by CVS */ #include #include @@ -32,6 +32,9 @@ static const char *rscid = "$Id: napi.c,v 1.15 2009/02/13 09:00:20 koennecke Exp #include #include #include +#include + +#include "nxconfig.h" #include "napi.h" #include "nxstack.h" @@ -49,144 +52,338 @@ static int iFortifyScope; #ifdef _WIN32 #define LIBSEP ";" #define PATHSEP "\\" +#define THREAD_LOCAL __declspec(thread) #else #define LIBSEP ":" #define PATHSEP "/" +#define THREAD_LOCAL __thread #endif -extern char *stptok(char *s, char *tok, size_t toklen, char *brk); + +#ifdef _MSC_VER +#define snprintf _snprintf +#endif /* _MSC_VER */ + +#include "nx_stptok.h" + +#if defined(_WIN32) +/* + * HDF5 on windows does not do locking for multiple threads conveniently so we will implement it ourselves. + * Freddie Akeroyd, 16/06/2011 + */ +#include + + +static CRITICAL_SECTION nx_critical; + +static int nxilock() +{ + static int first_call = 1; + if (first_call) + { + first_call = 0; + InitializeCriticalSection(&nx_critical); + } + EnterCriticalSection(&nx_critical); + return NX_OK; +} + +static int nxiunlock(int ret) +{ + LeaveCriticalSection(&nx_critical); + return ret; +} + +#define LOCKED_CALL(__call) \ + ( nxilock() , nxiunlock(__call) ) + +#elif HAVE_LIBPTHREAD + +#include + +static pthread_mutex_t nx_mutex; + +#ifdef PTHREAD_MUTEX_RECURSIVE +#define RECURSIVE_LOCK PTHREAD_MUTEX_RECURSIVE +#else +#define RECURSIVE_LOCK PTHREAD_MUTEX_RECURSIVE_NP +#endif /* PTHREAD_MUTEX_RECURSIVE */ + +static void nx_pthread_init() +{ + pthread_mutexattr_t attr; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, RECURSIVE_LOCK); + pthread_mutex_init(&nx_mutex, &attr); +} + +static int nxilock() +{ + static pthread_once_t once_control = PTHREAD_ONCE_INIT; + if (pthread_once(&once_control, nx_pthread_init) != 0) + { + NXReportError("pthread_once failed"); + return NX_ERROR; + } + if (pthread_mutex_lock(&nx_mutex) != 0) + { + NXReportError("pthread_mutex_lock failed"); + return NX_ERROR; + } + return NX_OK; +} + +static int nxiunlock(int ret) +{ + if (pthread_mutex_unlock(&nx_mutex) != 0) + { + NXReportError("pthread_mutex_unlock failed"); + return NX_ERROR; + } + return ret; +} + +#define LOCKED_CALL(__call) \ + ( nxilock() , nxiunlock(__call) ) + +#else + +#define LOCKED_CALL(__call) \ + __call + +#endif /* _WIN32 */ + +/** + * valid NeXus names + */ +int validNXName(const char* name, int allow_colon) +{ + int i; + if (name == NULL) + { + return 0; + } + for(i=0; i= 'a' && name[i] <= 'z') || + (name[i] >= 'A' && name[i] <= 'Z') || + (name[i] >= '0' && name[i] <= '9') || + (name[i] == '_') ) + { + ; + } + else if (allow_colon && name[i] == ':') + { + ; + } + else + { + return 0; + } + } + return 1; +} + +static int64_t* dupDimsArray(int* dims_array, int rank) +{ + int i; + int64_t* dims64 = (int64_t*)malloc(rank * sizeof(int64_t)); + if (dims64 != NULL) + { + for(i=0; i 0) { + if(newVal > 0) + { nx_cacheSize = newVal; return NX_OK; } return NX_ERROR; } - + /*-----------------------------------------------------------------------*/ -static NXstatus NXisXML(CONSTCHAR * filename) +static NXstatus NXisXML(CONSTCHAR *filename) { FILE *fd = NULL; char line[132]; - fd = fopen(filename, "r"); - if (fd) { - fgets(line, 131, fd); + fd = fopen(filename,"r"); + if(fd) { + int fgets_ok = (fgets(line,131,fd) != NULL); fclose(fd); - if (strstr(line, "?xml") != NULL) { - return NX_OK; + if (fgets_ok) { + if(strstr(line,"?xml") != NULL){ + return NX_OK; + } + } + else { + return NX_ERROR; } } return NX_ERROR; } /*-------------------------------------------------------------------------*/ -static void NXNXNXReportError(void *pData, char *string) -{ - printf("%s \n", string); -} + static void NXNXNXReportError(void *pData, char *string) + { + fprintf(stderr, "%s \n", string); + } + /*---------------------------------------------------------------------*/ + + static void *NXEHpData = NULL; + static void (*NXEHIReportError)(void *pData, char *string) = NXNXNXReportError; +#ifdef HAVE_TLS + static THREAD_LOCAL void *NXEHpTData = NULL; + static THREAD_LOCAL void (*NXEHIReportTError)(void *pData, char *string) = NULL; +#endif + + void NXIReportError(void *pData, char *string) { + fprintf(stderr, "Your application uses NXIReportError, but its first parameter is ignored now - you should use NXReportError."); + NXReportError(string); + } + + void NXReportError(char *string) { +#ifdef HAVE_TLS + if (NXEHIReportTError) { + (*NXEHIReportTError)(NXEHpTData, string); + return; + } +#endif + if (NXEHIReportError) { + (*NXEHIReportError)(NXEHpData, string); + } + } /*---------------------------------------------------------------------*/ -void *NXpData = NULL; -void (*NXIReportError) (void *pData, char *string) = NXNXNXReportError; - /*---------------------------------------------------------------------*/ -extern void NXMSetError(void *pData, - void (*NewError) (void *pD, char *text)) -{ - NXpData = pData; - NXIReportError = NewError; + extern void NXMSetError(void *pData, void (*NewError)(void *pD, char *text)) + { + NXEHpData = pData; + NXEHIReportError = NewError; + } +/*----------------------------------------------------------------------*/ + extern void NXMSetTError(void *pData, void (*NewError)(void *pD, char *text)) + { +#ifdef HAVE_TLS + NXEHpTData = pData; + NXEHIReportTError = NewError; +#else + NXMSetError(pData, NewError); +#endif + } +/*----------------------------------------------------------------------*/ +extern ErrFunc NXMGetError(){ +#ifdef HAVE_TLS + if (NXEHIReportTError) { + return NXEHIReportTError; + } +#endif + return NXEHIReportError; } /*----------------------------------------------------------------------*/ -extern ErrFunc NXMGetError() -{ - return NXIReportError; -} - -/*----------------------------------------------------------------------*/ -void NXNXNoReport(void *pData, char *string) -{ +static void NXNXNoReport(void *pData, char *string){ /* do nothing */ -} - +} /*----------------------------------------------------------------------*/ -static ErrFunc last_errfunc = NXNXNXReportError; +static ErrFunc last_global_errfunc = NXNXNXReportError; +#ifdef HAVE_TLS +static THREAD_LOCAL ErrFunc last_thread_errfunc = NULL; +#endif extern void NXMDisableErrorReporting() { - last_errfunc = NXMGetError(); - NXMSetError(NXpData, NXNXNoReport); +#ifdef HAVE_TLS + if (NXEHIReportTError) { + last_thread_errfunc = NXEHIReportTError; + NXEHIReportTError = NXNXNoReport; + return; + } +#endif + if (NXEHIReportError) { + last_global_errfunc = NXEHIReportError; + NXEHIReportError = NXNXNoReport; + } } extern void NXMEnableErrorReporting() { - NXMSetError(NXpData, last_errfunc); +#ifdef HAVE_TLS + if (last_thread_errfunc) { + NXEHIReportTError = last_thread_errfunc; + last_thread_errfunc = NULL; + return; + } +#endif + if (last_global_errfunc) { + NXEHIReportError = last_global_errfunc; + last_global_errfunc = NULL; + } } /*----------------------------------------------------------------------*/ @@ -198,573 +395,774 @@ extern void NXMEnableErrorReporting() #endif #ifdef NXXML #include "nxxml.h" -#endif +#endif /* ---------------------------------------------------------------------- + + Definition of NeXus API - Definition of NeXus API - - --------------------------------------------------------------------- */ -static int determineFileType(CONSTCHAR * filename) + ---------------------------------------------------------------------*/ +static int determineFileTypeImpl(CONSTCHAR *filename) { FILE *fd = NULL; - int iRet, fapl; - NXhandle handle; - + int iRet; + /* - this is for reading, check for existence first - */ - fd = fopen(filename, "r"); - if (fd == NULL) { + this is for reading, check for existence first + */ + fd = fopen(filename,"r"); + if(fd == NULL){ return -1; } fclose(fd); #ifdef HDF5 - iRet = H5Fis_hdf5((const char *) filename); - if (iRet > 0) { + iRet=H5Fis_hdf5((const char*)filename); + if( iRet > 0){ return 2; } -#endif +#endif #ifdef HDF4 - iRet = Hishdf((const char *) filename); - if (iRet > 0) { + iRet=Hishdf((const char*)filename); + if( iRet > 0){ return 1; } #endif #ifdef NXXML iRet = NXisXML(filename); - if (iRet == NX_OK) { + if(iRet == NX_OK){ return 3; } #endif /* - file type not recognized - */ + file type not recognized + */ return 0; } -/*---------------------------------------------------------------------*/ -static pNexusFunction handleToNexusFunc(NXhandle fid) +static int determineFileType(CONSTCHAR *filename) { + return LOCKED_CALL(determineFileTypeImpl(filename)); +} + +/*---------------------------------------------------------------------*/ +static pNexusFunction handleToNexusFunc(NXhandle fid){ pFileStack fileStack = NULL; - fileStack = (pFileStack) fid; - if (fileStack != NULL) { + fileStack = (pFileStack)fid; + if(fileStack != NULL){ return peekFileOnStack(fileStack); } else { return NULL; } } - /*--------------------------------------------------------------------*/ -static NXstatus NXinternalopen(CONSTCHAR * userfilename, NXaccess am, - pFileStack fileStack); +static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, + pFileStack fileStack); /*----------------------------------------------------------------------*/ -NXstatus NXopen(CONSTCHAR * userfilename, NXaccess am, NXhandle * gHandle) -{ +NXstatus NXopen(CONSTCHAR *userfilename, NXaccess am, NXhandle *gHandle){ int status; pFileStack fileStack = NULL; - NXhandle hfile; + *gHandle = NULL; fileStack = makeFileStack(); - if (fileStack == NULL) { - NXIReportError(NXpData, "ERROR: no memory to create filestack"); - return NX_ERROR; + if(fileStack == NULL){ + NXReportError("ERROR: no memory to create filestack"); + return NX_ERROR; } - status = NXinternalopen(userfilename, am, fileStack); - if (status == NX_OK) { + status = NXinternalopen(userfilename,am,fileStack); + if(status == NX_OK){ *gHandle = fileStack; } return status; } - /*-----------------------------------------------------------------------*/ -static NXstatus NXinternalopen(CONSTCHAR * userfilename, NXaccess am, - pFileStack fileStack) -{ - int hdf_type = 0; - int iRet = 0; - NXhandle hdf5_handle = NULL; - NXhandle hdf4_handle = NULL; - NXhandle xmlHandle = NULL; - pNexusFunction fHandle = NULL; - NXstatus retstat = NX_ERROR; - char error[1024]; - char *filename = NULL; - - /* configure fortify - iFortifyScope = Fortify_EnterScope(); - Fortify_CheckAllMemory(); - */ - - /* - allocate data - */ - fHandle = (pNexusFunction) malloc(sizeof(NexusFunction)); - if (fHandle == NULL) { - NXIReportError(NXpData, - "ERROR: no memory to create Function structure"); - return NX_ERROR; - } - memset(fHandle, 0, sizeof(NexusFunction)); /* so any functions we miss are NULL */ - - /* - test the strip flag. Elimnate it for the rest of the tests to work - */ - fHandle->stripFlag = 1; - if (am & NXACC_NOSTRIP) { - fHandle->stripFlag = 0; - am -= NXACC_NOSTRIP; - } - - if (am == NXACC_CREATE) { - /* HDF4 will be used ! */ - hdf_type = 1; - filename = strdup(userfilename); - } else if (am == NXACC_CREATE4) { - /* HDF4 will be used ! */ - hdf_type = 1; - filename = strdup(userfilename); - } else if (am == NXACC_CREATE5) { - /* HDF5 will be used ! */ - hdf_type = 2; - filename = strdup(userfilename); - } else if (am == NXACC_CREATEXML) { - /* XML will be used ! */ - hdf_type = 3; - filename = strdup(userfilename); - } else { - filename = locateNexusFileInPath((char *) userfilename); - if (filename == NULL) { - NXIReportError(NXpData, "Out of memory in NeXus-API"); - free(fHandle); - return NX_ERROR; - } - /* check file type hdf4/hdf5/XML for reading */ - iRet = determineFileType(filename); - if (iRet < 0) { - snprintf(error, 1023, "failed to open %s for reading", filename); - NXIReportError(NXpData, error); - free(filename); - return NX_ERROR; - } - if (iRet == 0) { - snprintf(error, 1023, "failed to determine filetype for %s ", - filename); - NXIReportError(NXpData, error); - free(filename); - free(fHandle); - return NX_ERROR; - } - hdf_type = iRet; - } - if (filename == NULL) { - NXIReportError(NXpData, "Out of memory in NeXus-API"); - return NX_ERROR; - } - - if (hdf_type == 1) { - /* HDF4 type */ -#ifdef HDF4 - retstat = NX4open((const char *) filename, am, &hdf4_handle); - if (retstat != NX_OK) { - free(fHandle); - free(filename); - return retstat; - } - fHandle->pNexusData = hdf4_handle; - NX4assignFunctions(fHandle); - pushFileStack(fileStack, fHandle, filename); -#else - NXIReportError(NXpData, - "ERROR: Attempt to create HDF4 file when not linked with HDF4"); - retstat = NX_ERROR; -#endif /* HDF4 */ - free(filename); - return retstat; - } else if (hdf_type == 2) { - /* HDF5 type */ -#ifdef HDF5 - retstat = NX5open(filename, am, &hdf5_handle); - if (retstat != NX_OK) { - free(fHandle); - free(filename); - return retstat; - } - fHandle->pNexusData = hdf5_handle; - NX5assignFunctions(fHandle); - pushFileStack(fileStack, fHandle, filename); -#else - NXIReportError(NXpData, - "ERROR: Attempt to create HDF5 file when not linked with HDF5"); - retstat = NX_ERROR; -#endif /* HDF5 */ - free(filename); - return retstat; - } else if (hdf_type == 3) { +static NXstatus NXinternalopenImpl(CONSTCHAR *userfilename, NXaccess am, pFileStack fileStack) + { + int hdf_type=0; + int iRet=0; + NXhandle hdf5_handle = NULL; + NXhandle hdf4_handle = NULL; + NXhandle xmlHandle = NULL; + pNexusFunction fHandle = NULL; + NXstatus retstat = NX_ERROR; + char error[1024]; + char *filename = NULL; + int my_am = (am & NXACCMASK_REMOVEFLAGS); + + /* configure fortify + iFortifyScope = Fortify_EnterScope(); + Fortify_CheckAllMemory(); + */ + /* - XML type - */ -#ifdef NXXML - retstat = NXXopen(filename, am, &xmlHandle); - if (retstat != NX_OK) { - free(fHandle); + allocate data + */ + fHandle = (pNexusFunction)malloc(sizeof(NexusFunction)); + if (fHandle == NULL) { + NXReportError("ERROR: no memory to create Function structure"); + return NX_ERROR; + } + memset(fHandle, 0, sizeof(NexusFunction)); /* so any functions we miss are NULL */ + + /* + test the strip flag. Elimnate it for the rest of the tests to work + */ + fHandle->stripFlag = 1; + if(am & NXACC_NOSTRIP){ + fHandle->stripFlag = 0; + am = (NXaccess)(am & ~NXACC_NOSTRIP); + } + fHandle->checkNameSyntax = 0; + if (am & NXACC_CHECKNAMESYNTAX) { + fHandle->checkNameSyntax = 1; + am = (NXaccess)(am & ~NXACC_CHECKNAMESYNTAX); + } + + + if (my_am==NXACC_CREATE) { + /* HDF4 will be used ! */ + hdf_type=1; + filename = strdup(userfilename); + } else if (my_am==NXACC_CREATE4) { + /* HDF4 will be used ! */ + hdf_type=1; + filename = strdup(userfilename); + } else if (my_am==NXACC_CREATE5) { + /* HDF5 will be used ! */ + hdf_type=2; + filename = strdup(userfilename); + } else if (my_am==NXACC_CREATEXML) { + /* XML will be used ! */ + hdf_type=3; + filename = strdup(userfilename); + } else { + filename = locateNexusFileInPath((char *)userfilename); + if(filename == NULL){ + NXReportError("Out of memory in NeXus-API"); + free(fHandle); + return NX_ERROR; + } + /* check file type hdf4/hdf5/XML for reading */ + iRet = determineFileType(filename); + if(iRet < 0) { + snprintf(error,1023,"failed to open %s for reading", + filename); + NXReportError(error); + free(filename); + return NX_ERROR; + } + if(iRet == 0){ + snprintf(error,1023,"failed to determine filetype for %s ", + filename); + NXReportError(error); + free(filename); + free(fHandle); + return NX_ERROR; + } + hdf_type = iRet; + } + if(filename == NULL){ + NXReportError("Out of memory in NeXus-API"); + return NX_ERROR; + } + + if (hdf_type==1) { + /* HDF4 type */ +#ifdef HDF4 + retstat = NX4open((const char *)filename,am,&hdf4_handle); + if(retstat != NX_OK){ + free(fHandle); + free(filename); + return retstat; + } + fHandle->pNexusData=hdf4_handle; + NX4assignFunctions(fHandle); + pushFileStack(fileStack,fHandle,filename); +#else + NXReportError( + "ERROR: Attempt to create HDF4 file when not linked with HDF4"); + retstat = NX_ERROR; +#endif /* HDF4 */ + free(filename); + return retstat; + } else if (hdf_type==2) { + /* HDF5 type */ +#ifdef HDF5 + retstat = NX5open(filename,am,&hdf5_handle); + if(retstat != NX_OK){ + free(fHandle); + free(filename); + return retstat; + } + fHandle->pNexusData=hdf5_handle; + NX5assignFunctions(fHandle); + pushFileStack(fileStack,fHandle, filename); +#else + NXReportError( + "ERROR: Attempt to create HDF5 file when not linked with HDF5"); + retstat = NX_ERROR; +#endif /* HDF5 */ free(filename); return retstat; - } - fHandle->pNexusData = xmlHandle; - NXXassignFunctions(fHandle); - pushFileStack(fileStack, fHandle, filename); + } else if(hdf_type == 3){ + /* + XML type + */ +#ifdef NXXML + retstat = NXXopen(filename,am,&xmlHandle); + if(retstat != NX_OK){ + free(fHandle); + free(filename); + return retstat; + } + fHandle->pNexusData=xmlHandle; + NXXassignFunctions(fHandle); + pushFileStack(fileStack,fHandle, filename); #else - NXIReportError(NXpData, - "ERROR: Attempt to create XML file when not linked with XML"); - retstat = NX_ERROR; + NXReportError( + "ERROR: Attempt to create XML file when not linked with XML"); + retstat = NX_ERROR; #endif - } else { - NXIReportError(NXpData, - "ERROR: Format not readable by this NeXus library"); - retstat = NX_ERROR; + } else { + NXReportError( + "ERROR: Format not readable by this NeXus library"); + retstat = NX_ERROR; + } + if (filename != NULL) { + free(filename); + } + return retstat; } - if (filename != NULL) { - free(filename); - } - return retstat; + +static NXstatus NXinternalopen(CONSTCHAR *userfilename, NXaccess am, pFileStack fileStack) +{ + return LOCKED_CALL(NXinternalopenImpl(userfilename, am, fileStack)); } + +NXstatus NXreopen(NXhandle pOrigHandle, NXhandle* pNewHandle) +{ + pFileStack newFileStack; + pFileStack origFileStack = (pFileStack)pOrigHandle; + pNexusFunction fOrigHandle = NULL, fNewHandle = NULL; + *pNewHandle = NULL; + newFileStack = makeFileStack(); + if(newFileStack == NULL){ + NXReportError ("ERROR: no memory to create filestack"); + return NX_ERROR; + } + // The code below will only open the last file on a stack + // for the moment raise an error, but this behaviour may be OK + if (fileStackDepth(origFileStack) > 0) + { + NXReportError ( + "ERROR: handle stack referes to many files - cannot reopen"); + return NX_ERROR; + } + fOrigHandle = peekFileOnStack(origFileStack); + if (fOrigHandle->nxreopen == NULL) + { + NXReportError ( + "ERROR: NXreopen not implemented for this underlying file format"); + return NX_ERROR; + } + fNewHandle = (NexusFunction*)malloc(sizeof(NexusFunction)); + memcpy(fNewHandle, fOrigHandle, sizeof(NexusFunction)); + LOCKED_CALL(fNewHandle->nxreopen( fOrigHandle->pNexusData, &(fNewHandle->pNexusData) )); + pushFileStack( newFileStack, fNewHandle, peekFilenameOnStack(origFileStack) ); + *pNewHandle = newFileStack; + return NX_OK; +} + + /* ------------------------------------------------------------------------- */ -NXstatus NXclose(NXhandle * fid) -{ - NXhandle hfil; - int status; - pFileStack fileStack = NULL; + NXstatus NXclose (NXhandle *fid) + { + NXhandle hfil; + int status; + pFileStack fileStack = NULL; + pNexusFunction pFunc=NULL; + if (*fid == NULL) + { + return NX_OK; + } + fileStack = (pFileStack)*fid; + pFunc = peekFileOnStack(fileStack); + hfil = pFunc->pNexusData; + status = LOCKED_CALL(pFunc->nxclose(&hfil)); + pFunc->pNexusData = hfil; + free(pFunc); + popFileStack(fileStack); + if(fileStackDepth(fileStack) < 0){ + killFileStack(fileStack); + *fid = NULL; + } + /* we can't set fid to NULL always as the handle points to a stack of files for external file support */ + /* + Fortify_CheckAllMemory(); + */ - pNexusFunction pFunc = NULL; - fileStack = (pFileStack) * fid; - pFunc = peekFileOnStack(fileStack); - hfil = pFunc->pNexusData; - status = pFunc->nxclose(&hfil); - pFunc->pNexusData = hfil; - free(pFunc); - popFileStack(fileStack); - if (fileStackDepth(fileStack) < 0) { - killFileStack(fileStack); + return status; } - /* - Fortify_CheckAllMemory(); - */ - return status; -} - /*-----------------------------------------------------------------------*/ - -NXstatus NXmakegroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxmakegroup(pFunc->pNexusData, name, nxclass); -} + /*-----------------------------------------------------------------------*/ + NXstatus NXmakegroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) + { + char buffer[256]; + pNexusFunction pFunc = handleToNexusFunc(fid); + if ( pFunc->checkNameSyntax && (nxclass != NULL) /* && !strncmp("NX", nxclass, 2) */ && !validNXName(name, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in group name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxmakegroup(pFunc->pNexusData, name, nxclass)); + } /*------------------------------------------------------------------------*/ -static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, - char *extPath, int extPathLen) -{ +static int analyzeNapimount(char *napiMount, char *extFile, int extFileLen, + char *extPath, int extPathLen){ char *pPtr = NULL, *path = NULL; int length; - memset(extFile, 0, extFileLen); - memset(extPath, 0, extPathLen); - pPtr = strstr(napiMount, "nxfile://"); - if (pPtr == NULL) { + memset(extFile,0,extFileLen); + memset(extPath,0,extPathLen); + pPtr = strstr(napiMount,"nxfile://"); + if(pPtr == NULL){ return NXBADURL; } - path = strrchr(napiMount, '#'); - if (path == NULL) { + path = strrchr(napiMount,'#'); + if(path == NULL){ length = strlen(napiMount) - 9; - if (length > extFileLen) { - NXIReportError(NXpData, - "ERROR: internal errro with external linking"); + if(length > extFileLen){ + NXReportError("ERROR: internal errro with external linking"); return NXBADURL; } - memcpy(extFile, pPtr + 9, length); - strcpy(extPath, "/"); + memcpy(extFile,pPtr+9,length); + strcpy(extPath,"/"); return NXFILE; } else { pPtr += 9; length = path - pPtr; - if (length > extFileLen) { - NXIReportError(NXpData, - "ERROR: internal errro with external linking"); + if(length > extFileLen){ + NXReportError("ERROR: internal errro with external linking"); return NXBADURL; } - memcpy(extFile, pPtr, length); - length = strlen(path - 1); - if (length > extPathLen) { - NXIReportError(NXpData, - "ERROR: internal error with external linking"); + memcpy(extFile,pPtr,length); + length = strlen(path-1); + if(length > extPathLen){ + NXReportError("ERROR: internal error with external linking"); return NXBADURL; } - strcpy(extPath, path + 1); + strcpy(extPath,path+1); return NXFILE; } return NXBADURL; } - /*------------------------------------------------------------------------*/ -NXstatus NXopengroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass) -{ - int status, attStatus, type = NX_CHAR, length = 1023; - NXaccess access = NXACC_RDWR; - NXlink breakID; - pFileStack fileStack; - char nxurl[1024], exfile[512], expath[512]; - ErrFunc oldError; - pNexusFunction pFunc = NULL; + NXstatus NXopengroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) + { + int status, attStatus, type = NX_CHAR, length = 1023; + NXaccess access = NXACC_READ; + NXlink breakID; + pFileStack fileStack; + char nxurl[1024], exfile[512], expath[512]; + pNexusFunction pFunc = NULL; - fileStack = (pFileStack) fid; - pFunc = handleToNexusFunc(fid); + fileStack = (pFileStack)fid; + pFunc = handleToNexusFunc(fid); - status = pFunc->nxopengroup(pFunc->pNexusData, name, nxclass); - oldError = NXMGetError(); - NXIReportError = NXNXNoReport; - attStatus = NXgetattr(fid, "napimount", nxurl, &length, &type); - NXIReportError = oldError; - if (attStatus == NX_OK) { - /* - this is an external linking group - */ - status = analyzeNapimount(nxurl, exfile, 511, expath, 511); - if (status == NXBADURL) { - return NX_ERROR; + status = LOCKED_CALL(pFunc->nxopengroup(pFunc->pNexusData, name, nxclass)); + if(status == NX_OK){ + pushPath(fileStack,name); } - status = NXinternalopen(exfile, access, fileStack); - if (status == NX_ERROR) { + NXMDisableErrorReporting(); + attStatus = NXgetattr(fid,"napimount",nxurl,&length, &type); + NXMEnableErrorReporting(); + if(attStatus == NX_OK){ + /* + this is an external linking group + */ + status = analyzeNapimount(nxurl,exfile,511,expath,511); + if(status == NXBADURL){ + return NX_ERROR; + } + status = NXinternalopen(exfile, access, fileStack); + if(status == NX_ERROR){ + return status; + } + status = NXopenpath(fid, expath); + NXgetgroupID(fid,&breakID); + setCloseID(fileStack,breakID); + } + + return status; + } + + /* ------------------------------------------------------------------- */ + + NXstatus NXclosegroup (NXhandle fid) + { + int status; + pFileStack fileStack = NULL; + NXlink closeID, currentID; + + pNexusFunction pFunc = handleToNexusFunc(fid); + fileStack = (pFileStack)fid; + if(fileStackDepth(fileStack) == 0){ + status = LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData)); + if(status == NX_OK){ + popPath(fileStack); + } + return status; + } else { + /* we have to check for leaving an external file */ + NXgetgroupID(fid,¤tID); + peekIDOnStack(fileStack,&closeID); + if(NXsameID(fid,&closeID,¤tID) == NX_OK){ + NXclose(&fid); + status = NXclosegroup(fid); + } else { + status = LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData)); + if(status == NX_OK){ + popPath(fileStack); + } + } return status; } - status = NXopenpath(fid, expath); - NXgetgroupID(fid, &breakID); - setCloseID(fileStack, breakID); - } - - return status; -} - - /* ------------------------------------------------------------------- */ - -NXstatus NXclosegroup(NXhandle fid) -{ - int status; - pFileStack fileStack = NULL; - NXlink closeID, currentID; - - pNexusFunction pFunc = handleToNexusFunc(fid); - fileStack = (pFileStack) fid; - if (fileStackDepth(fileStack) == 0) { - return pFunc->nxclosegroup(pFunc->pNexusData); - } else { - /* we have to check for leaving an external file */ - NXgetgroupID(fid, ¤tID); - peekIDOnStack(fileStack, &closeID); - if (NXsameID(fid, &closeID, ¤tID) == NX_OK) { - NXclose(&fid); - status = NXclosegroup(fid); - } else { - status = pFunc->nxclosegroup(pFunc->pNexusData); - } - return status; - } -} + } /* --------------------------------------------------------------------- */ + + NXstatus NXmakedata (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int dimensions[]) + { + int status; + int64_t* dims64 = dupDimsArray(dimensions, rank); + status = NXmakedata64(fid, name, datatype, rank, dims64); + free(dims64); + return status; + } -NXstatus NXmakedata(NXhandle fid, CONSTCHAR * name, int datatype, - int rank, int dimensions[]) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxmakedata(pFunc->pNexusData, name, datatype, rank, - dimensions); -} - + NXstatus NXmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[]) + { + char buffer[256]; + pNexusFunction pFunc = handleToNexusFunc(fid); + if ( pFunc->checkNameSyntax && !validNXName(name, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxmakedata64(pFunc->pNexusData, name, datatype, rank, dimensions)); + } /* --------------------------------------------------------------------- */ - -NXstatus NXcompmakedata(NXhandle fid, CONSTCHAR * name, int datatype, - int rank, int dimensions[], int compress_type, - int chunk_size[]) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxcompmakedata(pFunc->pNexusData, name, datatype, rank, - dimensions, compress_type, chunk_size); -} - - + + NXstatus NXcompmakedata (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int dimensions[], int compress_type, int chunk_size[]) + { + int status; + int64_t* dims64 = dupDimsArray(dimensions, rank); + int64_t* chunk64 = dupDimsArray(chunk_size, rank); + status = NXcompmakedata64(fid, name, datatype, rank, dims64, compress_type, chunk64); + free(dims64); + free(chunk64); + return status; + } + + NXstatus NXcompmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[], int compress_type, int64_t chunk_size[]) + { + char buffer[256]; + pNexusFunction pFunc = handleToNexusFunc(fid); + if ( pFunc->checkNameSyntax && !validNXName(name, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxcompmakedata64 (pFunc->pNexusData, name, datatype, rank, dimensions, compress_type, chunk_size)); + } + /* --------------------------------------------------------------------- */ -NXstatus NXcompress(NXhandle fid, int compress_type) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxcompress(pFunc->pNexusData, compress_type); -} - - + NXstatus NXcompress (NXhandle fid, int compress_type) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxcompress (pFunc->pNexusData, compress_type)); + } + + /* --------------------------------------------------------------------- */ + + NXstatus NXopendata (NXhandle fid, CONSTCHAR *name) + { + int status, attStatus, type = NX_CHAR, length = 1023; + NXaccess access = NXACC_READ; + NXlink breakID; + pFileStack fileStack; + char nxurl[1024], exfile[512], expath[512]; + pNexusFunction pFunc = NULL; -NXstatus NXopendata(NXhandle fid, CONSTCHAR * name) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxopendata(pFunc->pNexusData, name); -} + fileStack = (pFileStack)fid; + pFunc = handleToNexusFunc(fid); + status = LOCKED_CALL(pFunc->nxopendata(pFunc->pNexusData, name)); + if(status == NX_OK){ + pushPath(fileStack,name); + } + + NXMDisableErrorReporting(); + attStatus = NXgetattr(fid,"napimount",nxurl,&length, &type); + NXMEnableErrorReporting(); + if(attStatus == NX_OK){ + /* + this is an external linking group + */ + status = analyzeNapimount(nxurl,exfile,511,expath,511); + if(status == NXBADURL){ + return NX_ERROR; + } + status = NXinternalopen(exfile, access, fileStack); + if(status == NX_ERROR){ + return status; + } + status = NXopenpath(fid,expath); + NXgetdataID(fid,&breakID); + setCloseID(fileStack,breakID); + } + + return status; + } /* ----------------------------------------------------------------- */ + + NXstatus NXclosedata (NXhandle fid) + { + int status; + pFileStack fileStack = NULL; + NXlink closeID, currentID; -NXstatus NXclosedata(NXhandle fid) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxclosedata(pFunc->pNexusData); -} + pNexusFunction pFunc = handleToNexusFunc(fid); + fileStack = (pFileStack)fid; - /* ------------------------------------------------------------------- */ - -NXstatus NXputdata(NXhandle fid, void *data) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxputdata(pFunc->pNexusData, data); -} - - /* ------------------------------------------------------------------- */ - -NXstatus NXputattr(NXhandle fid, CONSTCHAR * name, void *data, - int datalen, int iType) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxputattr(pFunc->pNexusData, name, data, datalen, iType); -} - - /* ------------------------------------------------------------------- */ - -NXstatus NXputslab(NXhandle fid, void *data, int iStart[], int iSize[]) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxputslab(pFunc->pNexusData, data, iStart, iSize); -} - - /* ------------------------------------------------------------------- */ - -NXstatus NXgetdataID(NXhandle fid, NXlink * sRes) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetdataID(pFunc->pNexusData, sRes); -} - - - /* ------------------------------------------------------------------- */ - -NXstatus NXmakelink(NXhandle fid, NXlink * sLink) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxmakelink(pFunc->pNexusData, sLink); -} - - /* ------------------------------------------------------------------- */ - -NXstatus NXmakenamedlink(NXhandle fid, CONSTCHAR * newname, NXlink * sLink) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxmakenamedlink(pFunc->pNexusData, newname, sLink); -} - - /* -------------------------------------------------------------------- */ -NXstatus NXopensourcegroup(NXhandle fid) -{ - char target_path[512]; - int status, type = NX_CHAR, length = 511; - - status = NXgetattr(fid, "target", target_path, &length, &type); - if (status != NX_OK) { - NXIReportError(NXpData, "ERROR: item not linked"); - return NX_ERROR; + if(fileStackDepth(fileStack) == 0){ + status = LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData)); + if(status == NX_OK){ + popPath(fileStack); + } + return status; + } else { + /* we have to check for leaving an external file */ + NXgetdataID(fid,¤tID); + peekIDOnStack(fileStack,&closeID); + if(NXsameID(fid,&closeID,¤tID) == NX_OK){ + NXclose(&fid); + status = NXclosedata(fid); + } else { + status = LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData)); + if(status == NX_OK){ + popPath(fileStack); + } + } + return status; + } } - return NXopengrouppath(fid, target_path); -} + /* ------------------------------------------------------------------- */ + + NXstatus NXputdata (NXhandle fid, const void *data) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxputdata(pFunc->pNexusData, data)); + } + + /* ------------------------------------------------------------------- */ + + NXstatus NXputattr (NXhandle fid, CONSTCHAR *name, const void *data, + int datalen, int iType) + { + char buffer[256]; + pNexusFunction pFunc = handleToNexusFunc(fid); + if (datalen > 1 && iType != NX_CHAR) + { + NXReportError("NXputattr: numeric arrays are not allowed as attributes - only character strings and single numbers"); + return NX_ERROR; + } + if ( pFunc->checkNameSyntax && !validNXName(name, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in attribute name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxputattr(pFunc->pNexusData, name, data, datalen, iType)); + } + + /* ------------------------------------------------------------------- */ + + NXstatus NXputslab (NXhandle fid, const void *data, const int iStart[], const int iSize[]) + { + int i, iType, rank; + int64_t iStart64[NX_MAXRANK], iSize64[NX_MAXRANK]; + if (NXgetinfo64(fid, &rank, iStart64, &iType) != NX_OK) + { + return NX_ERROR; + } + for(i=0; i < rank; ++i) + { + iStart64[i] = iStart[i]; + iSize64[i] = iSize[i]; + } + return NXputslab64(fid, data, iStart64, iSize64); + } + + NXstatus NXputslab64 (NXhandle fid, const void *data, const int64_t iStart[], const int64_t iSize[]) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxputslab64(pFunc->pNexusData, data, iStart, iSize)); + } + + /* ------------------------------------------------------------------- */ + + NXstatus NXgetdataID (NXhandle fid, NXlink* sRes) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxgetdataID(pFunc->pNexusData, sRes)); + } + + + /* ------------------------------------------------------------------- */ + + NXstatus NXmakelink (NXhandle fid, NXlink* sLink) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxmakelink(pFunc->pNexusData, sLink)); + } + /* ------------------------------------------------------------------- */ + + NXstatus NXmakenamedlink (NXhandle fid, CONSTCHAR *newname, NXlink* sLink) + { + char buffer[256]; + pNexusFunction pFunc = handleToNexusFunc(fid); + if ( pFunc->checkNameSyntax && !validNXName(newname, 0) ) + { + sprintf(buffer, "ERROR: invalid characters in link name \"%s\"", newname); + NXReportError(buffer); + return NX_ERROR; + } + return LOCKED_CALL(pFunc->nxmakenamedlink(pFunc->pNexusData, newname, sLink)); + } + /* --------------------------------------------------------------------*/ + NXstatus NXopensourcegroup(NXhandle fid) + { + char target_path[512]; + int status, type = NX_CHAR, length = 511; + + status = NXgetattr(fid,"target",target_path,&length,&type); + if(status != NX_OK) + { + NXReportError("ERROR: item not linked"); + return NX_ERROR; + } + return NXopengrouppath(fid,target_path); + } /*----------------------------------------------------------------------*/ -NXstatus NXflush(NXhandle * pHandle) -{ - NXhandle hfil; - pFileStack fileStack = NULL; - int status; - - pNexusFunction pFunc = NULL; - fileStack = (pFileStack) * pHandle; - pFunc = peekFileOnStack(fileStack); - hfil = pFunc->pNexusData; - status = pFunc->nxflush(&hfil); - pFunc->pNexusData = hfil; - return status; -} + NXstatus NXflush(NXhandle *pHandle) + { + NXhandle hfil; + pFileStack fileStack = NULL; + int status; + + pNexusFunction pFunc=NULL; + fileStack = (pFileStack)*pHandle; + pFunc = peekFileOnStack(fileStack); + hfil = pFunc->pNexusData; + status = LOCKED_CALL(pFunc->nxflush(&hfil)); + pFunc->pNexusData = hfil; + return status; + } /*-------------------------------------------------------------------------*/ - -NXstatus NXmalloc(void **data, int rank, int dimensions[], int datatype) -{ - int i; - size_t size = 1; - *data = NULL; - for (i = 0; i < rank; i++) - size *= dimensions[i]; - if ((datatype == NX_CHAR) || (datatype == NX_INT8) - || (datatype == NX_UINT8)) { - /* allow for terminating \0 */ - size += 2; - } else if ((datatype == NX_INT16) || (datatype == NX_UINT16)) { - size *= 2; - } else if ((datatype == NX_INT32) || (datatype == NX_UINT32) - || (datatype == NX_FLOAT32)) { - size *= 4; - } else if ((datatype == NX_INT64) || (datatype == NX_UINT64)) { - size *= 8; - } else if (datatype == NX_FLOAT64) { - size *= 8; - } else { - NXIReportError(NXpData, - "ERROR: NXmalloc - unknown data type in array"); - return NX_ERROR; + + + NXstatus NXmalloc (void** data, int rank, + int dimensions[], int datatype) + { + int status; + int64_t* dims64 = dupDimsArray(dimensions, rank); + status = NXmalloc64(data, rank, dims64, datatype); + free(dims64); + return status; } - *data = (void *) malloc(size); - memset(*data, 0, size); - return NX_OK; -} + NXstatus NXmalloc64 (void** data, int rank, + int64_t dimensions[], int datatype) + { + int i; + size_t size = 1; + *data = NULL; + for(i=0; inxgetnextentry(pFunc->pNexusData, name, nxclass, datatype); -} - + + + NXstatus NXgetnextentry (NXhandle fid, NXname name, NXname nxclass, int *datatype) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxgetnextentry(pFunc->pNexusData, name, nxclass, datatype)); + } /*----------------------------------------------------------------------*/ /* ** TRIM.C - Remove leading, trailing, & excess embedded spaces @@ -775,287 +1173,467 @@ NXstatus NXgetnextentry(NXhandle fid, NXname name, NXname nxclass, char *nxitrim(char *str) { - char *ibuf = str, *obuf = str; - int i = 0, cnt = 0; + char *ibuf = str; + int i = 0; - /* - ** Trap NULL - */ + /* + ** Trap NULL + */ - if (str) { - /* - ** Remove leading spaces (from RMLEAD.C) - */ + if (str) + { + /* + ** Remove leading spaces (from RMLEAD.C) + */ - for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf); - str = ibuf; + for (ibuf = str; *ibuf && isspace(*ibuf); ++ibuf) + ; + str = ibuf; - /* - ** Remove trailing spaces (from RMTRAIL.C) - */ - i = strlen(str); - while (--i >= 0) { - if (!isspace(str[i])) - break; + /* + ** Remove trailing spaces (from RMTRAIL.C) + */ + i = strlen(str); + while (--i >= 0) + { + if (!isspace(str[i])) + break; + } + str[++i] = NUL; + } + return str; +} + /*-------------------------------------------------------------------------*/ + + NXstatus NXgetdata (NXhandle fid, void *data) + { + int status, type, rank; + int64_t iDim[NX_MAXRANK]; + char *pPtr, *pPtr2; + + pNexusFunction pFunc = handleToNexusFunc(fid); + status = LOCKED_CALL(pFunc->nxgetinfo64(pFunc->pNexusData, &rank, iDim, &type)); /* unstripped size if string */ + /* only strip one dimensional strings */ + if ( (type == NX_CHAR) && (pFunc->stripFlag == 1) && (rank == 1) ) + { + pPtr = (char*)malloc(iDim[0]+5); + memset(pPtr, 0, iDim[0]+5); + status = LOCKED_CALL(pFunc->nxgetdata(pFunc->pNexusData, pPtr)); + pPtr2 = nxitrim(pPtr); + strncpy((char*)data, pPtr2, strlen(pPtr2)); /* not NULL terminated by default */ + free(pPtr); } - str[++i] = NUL; + else + { + status = LOCKED_CALL(pFunc->nxgetdata(pFunc->pNexusData, data)); + } + return status; } - return str; -} +/*---------------------------------------------------------------------------*/ + NXstatus NXgetrawinfo64 (NXhandle fid, int *rank, + int64_t dimension[], int *iType) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxgetinfo64(pFunc->pNexusData, rank, dimension, iType)); + } + + NXstatus NXgetrawinfo (NXhandle fid, int *rank, + int dimension[], int *iType) + { + int i, status; + int64_t dims64[NX_MAXRANK]; + pNexusFunction pFunc = handleToNexusFunc(fid); + status = LOCKED_CALL(pFunc->nxgetinfo64(pFunc->pNexusData, rank, dims64, iType)); + for(i=0; i < *rank; ++i) + { + dimension[i] = dims64[i]; + } + return status; + } + /*-------------------------------------------------------------------------*/ + + NXstatus NXgetinfo (NXhandle fid, int *rank, + int dimension[], int *iType) + { + int i, status; + int64_t dims64[NX_MAXRANK]; + status = NXgetinfo64(fid, rank, dims64, iType); + for(i=0; i < *rank; ++i) + { + dimension[i] = dims64[i]; + } + return status; + } + + NXstatus NXgetinfo64 (NXhandle fid, int *rank, + int64_t dimension[], int *iType) + { + int status; + char *pPtr = NULL; + pNexusFunction pFunc = handleToNexusFunc(fid); + *rank = 0; + status = LOCKED_CALL(pFunc->nxgetinfo64(pFunc->pNexusData, rank, dimension, iType)); + /* + the length of a string may be trimmed.... + */ + /* only strip one dimensional strings */ + if((*iType == NX_CHAR) && (pFunc->stripFlag == 1) && (*rank == 1)){ + pPtr = (char *)malloc((dimension[0]+1)*sizeof(char)); + if(pPtr != NULL){ + memset(pPtr,0,(dimension[0]+1)*sizeof(char)); + LOCKED_CALL(pFunc->nxgetdata(pFunc->pNexusData, pPtr)); + dimension[0] = strlen(nxitrim(pPtr)); + free(pPtr); + } + } + return status; + } + + /*-------------------------------------------------------------------------*/ + + NXstatus NXgetslab (NXhandle fid, void *data, + int iStart[], int iSize[]) + { + int i, iType, rank; + int64_t iStart64[NX_MAXRANK], iSize64[NX_MAXRANK]; + if (NXgetinfo64(fid, &rank, iStart64, &iType) != NX_OK) + { + return NX_ERROR; + } + for(i=0; i < rank; ++i) + { + iStart64[i] = iStart[i]; + iSize64[i] = iSize[i]; + } + return NXgetslab64(fid, data, iStart64, iSize64); + } + + NXstatus NXgetslab64 (NXhandle fid, void *data, + const int64_t iStart[], const int64_t iSize[]) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxgetslab64(pFunc->pNexusData, data, iStart, iSize)); + } + + /*-------------------------------------------------------------------------*/ + + NXstatus NXgetnextattr (NXhandle fileid, NXname pName, + int *iLength, int *iType) + { + pNexusFunction pFunc = handleToNexusFunc(fileid); + return LOCKED_CALL(pFunc->nxgetnextattr(pFunc->pNexusData, pName, iLength, iType)); + } + /*-------------------------------------------------------------------------*/ -NXstatus NXgetdata(NXhandle fid, void *data) -{ - int status, type, rank, iDim[NX_MAXRANK]; - char *pPtr, *pPtr2; - - pNexusFunction pFunc = handleToNexusFunc(fid); - status = pFunc->nxgetinfo(pFunc->pNexusData, &rank, iDim, &type); /* unstripped size if string */ - /* only strip one dimensional strings */ - if ((type == NX_CHAR) && (pFunc->stripFlag == 1) && (rank == 1)) { - pPtr = (char *) malloc(iDim[0] + 5); - memset(pPtr, 0, iDim[0] + 5); - status = pFunc->nxgetdata(pFunc->pNexusData, pPtr); - pPtr2 = nxitrim(pPtr); - strncpy((char *) data, pPtr2, strlen(pPtr2)); /* not NULL terminated by default */ - free(pPtr); - } else { - status = pFunc->nxgetdata(pFunc->pNexusData, data); + NXstatus NXgetattr (NXhandle fid, char *name, void *data, int* datalen, int* iType) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxgetattr(pFunc->pNexusData, name, data, datalen, iType)); } - return status; -} + /*-------------------------------------------------------------------------*/ -NXstatus NXgetinfo(NXhandle fid, int *rank, int dimension[], int *iType) -{ - int status; - char *pPtr = NULL; + NXstatus NXgetattrinfo (NXhandle fid, int *iN) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxgetattrinfo(pFunc->pNexusData, iN)); + } - pNexusFunction pFunc = handleToNexusFunc(fid); - status = pFunc->nxgetinfo(pFunc->pNexusData, rank, dimension, iType); - /* - the length of a string may be trimmed.... - */ - /* only strip one dimensional strings */ - if ((*iType == NX_CHAR) && (pFunc->stripFlag == 1) && (*rank == 1)) { - pPtr = (char *) malloc((dimension[0] + 1) * sizeof(char)); - if (pPtr != NULL) { - memset(pPtr, 0, (dimension[0] + 1) * sizeof(char)); - pFunc->nxgetdata(pFunc->pNexusData, pPtr); - dimension[0] = strlen(nxitrim(pPtr)); - free(pPtr); + + /*-------------------------------------------------------------------------*/ + + NXstatus NXgetgroupID (NXhandle fileid, NXlink* sRes) + { + pNexusFunction pFunc = handleToNexusFunc(fileid); + return LOCKED_CALL(pFunc->nxgetgroupID(pFunc->pNexusData, sRes)); + } + + /*-------------------------------------------------------------------------*/ + + NXstatus NXgetgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxgetgroupinfo(pFunc->pNexusData, iN, pName, pClass)); + } + + + /*-------------------------------------------------------------------------*/ + + NXstatus NXsameID (NXhandle fileid, NXlink* pFirstID, NXlink* pSecondID) + { + pNexusFunction pFunc = handleToNexusFunc(fileid); + return LOCKED_CALL(pFunc->nxsameID(pFunc->pNexusData, pFirstID, pSecondID)); + } + + /*-------------------------------------------------------------------------*/ + + NXstatus NXinitattrdir (NXhandle fid) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxinitattrdir(pFunc->pNexusData)); + } + /*-------------------------------------------------------------------------*/ + + NXstatus NXsetnumberformat (NXhandle fid, + int type, char *format) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + if(pFunc->nxsetnumberformat != NULL) + { + return LOCKED_CALL(pFunc->nxsetnumberformat(pFunc->pNexusData,type,format)); + } + else + { + /* + silently ignore this. Most NeXus file formats do not require + this + */ + return NX_OK; } } - return status; -} - + + /*-------------------------------------------------------------------------*/ - -NXstatus NXgetslab(NXhandle fid, void *data, int iStart[], int iSize[]) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetslab(pFunc->pNexusData, data, iStart, iSize); -} - - - /*-------------------------------------------------------------------------*/ - -NXstatus NXgetnextattr(NXhandle fileid, NXname pName, - int *iLength, int *iType) -{ - pNexusFunction pFunc = handleToNexusFunc(fileid); - return pFunc->nxgetnextattr(pFunc->pNexusData, pName, iLength, iType); -} - - - /*-------------------------------------------------------------------------*/ - -NXstatus NXgetattr(NXhandle fid, char *name, void *data, int *datalen, - int *iType) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetattr(pFunc->pNexusData, name, data, datalen, iType); -} - - - /*-------------------------------------------------------------------------*/ - -NXstatus NXgetattrinfo(NXhandle fid, int *iN) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetattrinfo(pFunc->pNexusData, iN); -} - - - /*-------------------------------------------------------------------------*/ - -NXstatus NXgetgroupID(NXhandle fileid, NXlink * sRes) -{ - pNexusFunction pFunc = handleToNexusFunc(fileid); - return pFunc->nxgetgroupID(pFunc->pNexusData, sRes); -} - - /*-------------------------------------------------------------------------*/ - -NXstatus NXgetgroupinfo(NXhandle fid, int *iN, NXname pName, NXname pClass) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxgetgroupinfo(pFunc->pNexusData, iN, pName, pClass); -} - - - /*-------------------------------------------------------------------------*/ - -NXstatus NXsameID(NXhandle fileid, NXlink * pFirstID, NXlink * pSecondID) -{ - pNexusFunction pFunc = handleToNexusFunc(fileid); - return pFunc->nxsameID(pFunc->pNexusData, pFirstID, pSecondID); -} - - /*-------------------------------------------------------------------------*/ - -NXstatus NXinitattrdir(NXhandle fid) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxinitattrdir(pFunc->pNexusData); -} - - /*-------------------------------------------------------------------------*/ - -NXstatus NXsetnumberformat(NXhandle fid, int type, char *format) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - if (pFunc->nxsetnumberformat != NULL) { - return pFunc->nxsetnumberformat(pFunc->pNexusData, type, format); - } else { - /* - silently ignore this. Most NeXus file formats do not require - this - */ - return NX_OK; + + NXstatus NXinitgroupdir (NXhandle fid) + { + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxinitgroupdir(pFunc->pNexusData)); } -} - - - /*-------------------------------------------------------------------------*/ - -NXstatus NXinitgroupdir(NXhandle fid) -{ - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxinitgroupdir(pFunc->pNexusData); -} - /*----------------------------------------------------------------------*/ -NXstatus NXinquirefile(NXhandle handle, char *filename, - int filenameBufferLength) -{ + NXstatus NXinquirefile(NXhandle handle, char *filename, + int filenameBufferLength){ pFileStack fileStack; char *pPtr = NULL; - int length; + int length, status; - fileStack = (pFileStack) handle; + pNexusFunction pFunc = handleToNexusFunc(handle); + if (pFunc->nxnativeinquirefile != NULL) { + + status = LOCKED_CALL(pFunc->nxnativeinquirefile(pFunc->pNexusData, filename, filenameBufferLength)); + if (status < 0) { + return NX_ERROR; + } else { + return NX_OK; + } + + } + + fileStack = (pFileStack)handle; pPtr = peekFilenameOnStack(fileStack); - if (pPtr != NULL) { + if(pPtr != NULL){ length = strlen(pPtr); - if (length > filenameBufferLength) { - length = filenameBufferLength - 1; + if(length > filenameBufferLength){ + length = filenameBufferLength -1; } - memset(filename, 0, filenameBufferLength); - memcpy(filename, pPtr, length); + memset(filename,0,filenameBufferLength); + memcpy(filename,pPtr, length); return NX_OK; } else { return NX_ERROR; } } - /*------------------------------------------------------------------------*/ -NXstatus NXisexternalgroup(NXhandle fid, CONSTCHAR * name, - CONSTCHAR * class, char *url, int urlLen) -{ +NXstatus NXisexternalgroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass, + char *url, int urlLen){ int status, attStatus, length = 1023, type = NX_CHAR; - ErrFunc oldError; char nxurl[1024]; pNexusFunction pFunc = handleToNexusFunc(fid); - status = pFunc->nxopengroup(pFunc->pNexusData, name, class); - if (status != NX_OK) { + if (pFunc->nxnativeisexternallink != NULL) { + status = LOCKED_CALL(pFunc->nxnativeisexternallink(pFunc->pNexusData, name, url, urlLen)); + if (status == NX_OK) { + return NX_OK; + } + // need to continue, could still be old style link + } + + status = LOCKED_CALL(pFunc->nxopengroup(pFunc->pNexusData, name, nxclass)); + if(status != NX_OK){ return status; } - oldError = NXMGetError(); - NXIReportError = NXNXNoReport; - attStatus = NXgetattr(fid, "napimount", nxurl, &length, &type); - NXIReportError = oldError; - pFunc->nxclosegroup(pFunc->pNexusData); - if (attStatus == NX_OK) { + NXMDisableErrorReporting(); + attStatus = NXgetattr(fid,"napimount",nxurl,&length, &type); + NXMEnableErrorReporting(); + LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData)); + if(attStatus == NX_OK){ length = strlen(nxurl); - if (length > urlLen) { + if(length >= urlLen){ length = urlLen - 1; } - memset(url, 0, urlLen); - memcpy(url, nxurl, length); + memset(url,0,urlLen); + memcpy(url,nxurl,length); return attStatus; } else { return NX_ERROR; } } - /*------------------------------------------------------------------------*/ -NXstatus NXlinkexternal(NXhandle fid, CONSTCHAR * name, CONSTCHAR * class, - CONSTCHAR * url) -{ - int status, type = NX_CHAR, length; +NXstatus NXisexternaldataset(NXhandle fid, CONSTCHAR *name, + char *url, int urlLen){ + int status, attStatus, length = 1023, type = NX_CHAR; + char nxurl[1024]; + pNexusFunction pFunc = handleToNexusFunc(fid); - status = pFunc->nxopengroup(pFunc->pNexusData, name, class); - if (status != NX_OK) { + if (pFunc->nxnativeisexternallink != NULL) { + status = LOCKED_CALL(pFunc->nxnativeisexternallink(pFunc->pNexusData, name, url, urlLen)); + if (status == NX_OK) { + return NX_OK; + } + // need to continue, could still be old style link + } + + status = LOCKED_CALL(pFunc->nxopendata(pFunc->pNexusData, name)); + if(status != NX_OK){ + return status; + } + NXMDisableErrorReporting(); + attStatus = NXgetattr(fid,"napimount",nxurl,&length, &type); + NXMEnableErrorReporting(); + LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData)); + if(attStatus == NX_OK){ + length = strlen(nxurl); + if(length >= urlLen){ + length = urlLen - 1; + } + memset(url,0,urlLen); + memcpy(url,nxurl,length); + return attStatus; + } else { + return NX_ERROR; + } +} +/*------------------------------------------------------------------------*/ +NXstatus NXlinkexternal(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass, CONSTCHAR *url) { + int status, type = NX_CHAR, length=1024, urllen; + char nxurl[1024], exfile[512], expath[512]; + pNexusFunction pFunc = handleToNexusFunc(fid); + + // in HDF5 we support external linking natively + if (pFunc->nxnativeexternallink != NULL) { + urllen = strlen(url); + memset(nxurl, 0, length); + if(urllen >= length){ + urllen = length - 1; + } + memcpy(nxurl, url, urllen); + status = analyzeNapimount(nxurl,exfile,511,expath,511); + if(status != NX_OK){ + return status; + } + status = LOCKED_CALL(pFunc->nxnativeexternallink(pFunc->pNexusData, name, exfile, expath)); + if(status != NX_OK){ + return status; + } + return NX_OK; + } + + NXMDisableErrorReporting(); + LOCKED_CALL(pFunc->nxmakegroup(pFunc->pNexusData,name,nxclass)); + NXMEnableErrorReporting(); + + status = LOCKED_CALL(pFunc->nxopengroup(pFunc->pNexusData,name,nxclass)); + if(status != NX_OK){ return status; } length = strlen(url); - status = NXputattr(fid, "napimount", (void *) url, length, type); - if (status != NX_OK) { + status = NXputattr(fid, "napimount",url,length, type); + if(status != NX_OK){ return status; } - pFunc->nxclosegroup(pFunc->pNexusData); + LOCKED_CALL(pFunc->nxclosegroup(pFunc->pNexusData)); return NX_OK; } +/*------------------------------------------------------------------------*/ +NXstatus NXlinkexternaldataset(NXhandle fid, CONSTCHAR *name, + CONSTCHAR *url){ + int status, type = NX_CHAR, length=1024, urllen; + char nxurl[1024], exfile[512], expath[512]; + pNexusFunction pFunc = handleToNexusFunc(fid); + int rank = 1; + int64_t dims[1] = {1}; + + //TODO cut and paste + // in HDF5 we support external linking natively + if (pFunc->nxnativeexternallink != NULL) { + urllen = strlen(url); + memset(nxurl, 0, length); + if(urllen > length){ + urllen = length - 1; + } + memcpy(nxurl, url, urllen); + status = analyzeNapimount(nxurl,exfile,511,expath,511); + if(status != NX_OK){ + return status; + } + status = LOCKED_CALL(pFunc->nxnativeexternallink(pFunc->pNexusData, name, exfile, expath)); + if(status != NX_OK){ + return status; + } + return NX_OK; + } + + + status = LOCKED_CALL(pFunc->nxmakedata64(pFunc->pNexusData, name, NX_CHAR, rank, dims)); + if(status != NX_OK){ + return status; + } + status = LOCKED_CALL(pFunc->nxopendata(pFunc->pNexusData, name)); + if(status != NX_OK){ + return status; + } + length = strlen(url); + status = NXputattr(fid, "napimount",url,length, type); + if(status != NX_OK){ + return status; + } + LOCKED_CALL(pFunc->nxclosedata(pFunc->pNexusData)); + return NX_OK; +} /*------------------------------------------------------------------------ - Implementation of NXopenpath. + Implementation of NXopenpath --------------------------------------------------------------------------*/ static int isDataSetOpen(NXhandle hfil) { NXlink id; - + /* - This uses the (sensible) feauture that NXgetdataID returns NX_ERROR - when no dataset is open - */ - if (NXgetdataID(hfil, &id) == NX_ERROR) { + This uses the (sensible) feauture that NXgetdataID returns NX_ERROR + when no dataset is open + */ + if(NXgetdataID(hfil,&id) == NX_ERROR) + { return 0; - } else { + } + else + { return 1; } } - /*----------------------------------------------------------------------*/ static int isRoot(NXhandle hfil) { NXlink id; - + /* - This uses the feauture that NXgetgroupID returns NX_ERROR - when we are at root level - */ - if (NXgetgroupID(hfil, &id) == NX_ERROR) { + This uses the feauture that NXgetgroupID returns NX_ERROR + when we are at root level + */ + if(NXgetgroupID(hfil,&id) == NX_ERROR) + { return 1; - } else { + } + else + { return 0; } } - /*-------------------------------------------------------------------- copies the next path element into element. returns a pointer into path beyond the extracted path @@ -1067,294 +1645,338 @@ static char *extractNextPath(char *path, NXname element) pPtr = path; /* - skip over leading / - */ - if (*pPtr == '/') { + skip over leading / + */ + if(*pPtr == '/') + { pPtr++; } pStart = pPtr; - + /* - find next / - */ - pPtr = strchr(pStart, '/'); - if (pPtr == NULL) { + find next / + */ + pPtr = strchr(pStart,'/'); + if(pPtr == NULL) + { /* - this is the last path element - */ - strcpy(element, pStart); + this is the last path element + */ + strcpy(element,pStart); return NULL; } else { length = pPtr - pStart; - strncpy(element, pStart, length); + strncpy(element,pStart,length); element[length] = '\0'; } return pPtr + 1; } - /*-------------------------------------------------------------------*/ static NXstatus gotoRoot(NXhandle hfil) { - int status; + int status; - if (isDataSetOpen(hfil)) { - status = NXclosedata(hfil); - if (status == NX_ERROR) { - return status; + if(isDataSetOpen(hfil)) + { + status = NXclosedata(hfil); + if(status == NX_ERROR) + { + return status; + } } - } - while (!isRoot(hfil)) { - status = NXclosegroup(hfil); - if (status == NX_ERROR) { - return status; + while(!isRoot(hfil)) + { + status = NXclosegroup(hfil); + if(status == NX_ERROR) + { + return status; + } } - } - return NX_OK; + return NX_OK; } - /*--------------------------------------------------------------------*/ static int isRelative(char *path) { - if (path[0] == '.' && path[1] == '.') + if(path[0] == '.' && path[1] == '.') return 1; else return 0; } - /*------------------------------------------------------------------*/ static NXstatus moveOneDown(NXhandle hfil) { - if (isDataSetOpen(hfil)) { + if(isDataSetOpen(hfil)) + { return NXclosedata(hfil); - } else { + } + else + { return NXclosegroup(hfil); } } - /*------------------------------------------------------------------- returns a pointer to the remaining path string to move up --------------------------------------------------------------------*/ static char *moveDown(NXhandle hfil, char *path, int *code) { int status; - NXname pathElem; char *pPtr; *code = NX_OK; - if (path[0] == '/') { + if(path[0] == '/') + { *code = gotoRoot(hfil); return path; - } else { + } + else + { pPtr = path; - while (isRelative(pPtr)) { + while(isRelative(pPtr)) + { status = moveOneDown(hfil); - if (status == NX_ERROR) { - *code = status; - return pPtr; + if(status == NX_ERROR) + { + *code = status; + return pPtr; } pPtr += 3; } return pPtr; } -} - +} /*--------------------------------------------------------------------*/ static NXstatus stepOneUp(NXhandle hfil, char *name) { - int status, datatype; + int datatype; NXname name2, xclass; - char pBueffel[256]; + char pBueffel[256]; /* - catch the case when we are there: i.e. no further stepping - necessary. This can happen with paths like ../ - */ + catch the case when we are there: i.e. no further stepping + necessary. This can happen with paths like ../ + */ if (strlen(name) < 1) { - return NX_OK; + return NX_OK; } - + NXinitgroupdir(hfil); - while (NXgetnextentry(hfil, name2, xclass, &datatype) != NX_EOD) { - if (strcmp(name2, name) == 0) { - if (strcmp(xclass, "SDS") == 0) { - return NXopendata(hfil, name); + while(NXgetnextentry(hfil, name2, xclass, &datatype) != NX_EOD) + { + if(strcmp(name2,name) == 0) + { + if(strcmp(xclass,"SDS") == 0) + { + return NXopendata(hfil,name); } else { - return NXopengroup(hfil, name, xclass); + return NXopengroup(hfil,name,xclass); } } } - snprintf(pBueffel, 255, "ERROR: NXopenpath cannot step into %s", name); - NXIReportError(NXpData, pBueffel); - return NX_ERROR; + snprintf(pBueffel,255,"ERROR: NXopenpath cannot step into %s",name); + NXReportError( pBueffel); + return NX_ERROR; } - /*--------------------------------------------------------------------*/ static NXstatus stepOneGroupUp(NXhandle hfil, char *name) { - int status, datatype; + int datatype; NXname name2, xclass; - char pBueffel[256]; + char pBueffel[256]; /* - catch the case when we are there: i.e. no further stepping - necessary. This can happen with paths like ../ - */ - if (strlen(name) < 1) { - return NX_OK; + catch the case when we are there: i.e. no further stepping + necessary. This can happen with paths like ../ + */ + if(strlen(name) < 1) + { + return NX_OK; } - + NXinitgroupdir(hfil); - while (NXgetnextentry(hfil, name2, xclass, &datatype) != NX_EOD) { - - if (strcmp(name2, name) == 0) { - if (strcmp(xclass, "SDS") == 0) { - return NX_EOD; - } else { - return NXopengroup(hfil, name, xclass); + while(NXgetnextentry(hfil,name2,xclass,&datatype) != NX_EOD) + { + + if(strcmp(name2,name) == 0) + { + if(strcmp(xclass,"SDS") == 0) { + return NX_EOD; + } + else + { + return NXopengroup(hfil,name,xclass); } } } - snprintf(pBueffel, 255, "ERROR: NXopenpath cannot step into %s", name); - NXIReportError(NXpData, pBueffel); - return NX_ERROR; + snprintf(pBueffel,255,"ERROR: NXopenpath cannot step into %s",name); + NXReportError( pBueffel); + return NX_ERROR; } - /*---------------------------------------------------------------------*/ -NXstatus NXopenpath(NXhandle hfil, CONSTCHAR * path) +NXstatus NXopenpath(NXhandle hfil, CONSTCHAR *path) { int status, run = 1; NXname pathElement; char *pPtr; - if (hfil == NULL || path == NULL) { - NXIReportError(NXpData, - "ERROR: NXopendata needs both a file handle and a path string"); + if(hfil == NULL || path == NULL) + { + NXReportError( + "ERROR: NXopendata needs both a file handle and a path string"); return NX_ERROR; } - pPtr = moveDown(hfil, (char *) path, &status); - if (status != NX_OK) { - NXIReportError(NXpData, - "ERROR: NXopendata failed to move down in hierarchy"); + pPtr = moveDown(hfil,(char *)path,&status); + if(status != NX_OK) + { + NXReportError( + "ERROR: NXopendata failed to move down in hierarchy"); return status; } - while (run == 1) { + while(run == 1) + { pPtr = extractNextPath(pPtr, pathElement); - status = stepOneUp(hfil, pathElement); - if (status != NX_OK) { + status = stepOneUp(hfil,pathElement); + if(status != NX_OK) + { return status; } - if (pPtr == NULL) { + if(pPtr == NULL) + { run = 0; } } return NX_OK; } - /*---------------------------------------------------------------------*/ -NXstatus NXopengrouppath(NXhandle hfil, CONSTCHAR * path) +NXstatus NXopengrouppath(NXhandle hfil, CONSTCHAR *path) { int status, run = 1; NXname pathElement; char *pPtr; - if (hfil == NULL || path == NULL) { - NXIReportError(NXpData, - "ERROR: NXopendata needs both a file handle and a path string"); + if(hfil == NULL || path == NULL) + { + NXReportError( + "ERROR: NXopendata needs both a file handle and a path string"); return NX_ERROR; } - pPtr = moveDown(hfil, (char *) path, &status); - if (status != NX_OK) { - NXIReportError(NXpData, - "ERROR: NXopendata failed to move down in hierarchy"); + pPtr = moveDown(hfil,(char *)path,&status); + if(status != NX_OK) + { + NXReportError( + "ERROR: NXopendata failed to move down in hierarchy"); return status; } - while (run == 1) { + while(run == 1) + { pPtr = extractNextPath(pPtr, pathElement); - status = stepOneGroupUp(hfil, pathElement); - if (status == NX_ERROR) { + status = stepOneGroupUp(hfil,pathElement); + if(status == NX_ERROR) + { return status; } - if (pPtr == NULL || status == NX_EOD) { + if(pPtr == NULL || status == NX_EOD) + { run = 0; } } return NX_OK; } - -NXstatus NXIprintlink(NXhandle fid, NXlink * link) +/*---------------------------------------------------------------------*/ +NXstatus NXIprintlink(NXhandle fid, NXlink* link) { - pNexusFunction pFunc = handleToNexusFunc(fid); - return pFunc->nxprintlink(pFunc->pNexusData, link); + pNexusFunction pFunc = handleToNexusFunc(fid); + return LOCKED_CALL(pFunc->nxprintlink(pFunc->pNexusData, link)); +} +/*----------------------------------------------------------------------*/ +NXstatus NXgetpath(NXhandle fid, char *path, int pathlen){ + int status; + pFileStack fileStack = NULL; + + fileStack = (pFileStack)fid; + status = buildPath(fileStack,path,pathlen); + if(status != 1){ + return NX_ERROR; + } + return NX_OK; } /*-------------------------------------------------------------------- format NeXus time. Code needed in every NeXus file driver ---------------------------------------------------------------------*/ -char *NXIformatNeXusTime() -{ - char *timeData; - time_t timer; - char *time_buffer = NULL; - struct tm *time_info; - const char *time_format; - long gmt_offset; +char *NXIformatNeXusTime(){ + time_t timer; + char* time_buffer = NULL; + struct tm *time_info; + const char* time_format; + long gmt_offset; #ifdef USE_FTIME - struct timeb timeb_struct; -#endif + struct timeb timeb_struct; +#endif - time_buffer = (char *) malloc(64 * sizeof(char)); - if (!time_buffer) { - NXIReportError(NXpData, "Failed to allocate buffer for time data"); - return NULL; - } -#ifdef NEED_TZSET - tzset(); -#endif - time(&timer); -#ifdef USE_FTIME - ftime(&timeb_struct); - gmt_offset = -timeb_struct.timezone * 60; - if (timeb_struct.dstflag != 0) { - gmt_offset += 3600; - } -#else - time_info = gmtime(&timer); - if (time_info != NULL) { - gmt_offset = (long) difftime(timer, mktime(time_info)); - } else { - NXIReportError(NXpData, - "Your gmtime() function does not work ... timezone information will be incorrect\n"); - gmt_offset = 0; - } -#endif - time_info = localtime(&timer); - if (time_info != NULL) { - if (gmt_offset < 0) { - time_format = "%04d-%02d-%02d %02d:%02d:%02d-%02d%02d"; - } else { - time_format = "%04d-%02d-%02d %02d:%02d:%02d+%02d%02d"; + time_buffer = (char *)malloc(64*sizeof(char)); + if(!time_buffer){ + NXReportError("Failed to allocate buffer for time data"); + return NULL; } - sprintf(time_buffer, time_format, + +#ifdef NEED_TZSET + tzset(); +#endif + time(&timer); +#ifdef USE_FTIME + ftime(&timeb_struct); + gmt_offset = -timeb_struct.timezone * 60; + if (timeb_struct.dstflag != 0) + { + gmt_offset += 3600; + } +#else + time_info = gmtime(&timer); + if (time_info != NULL) + { + gmt_offset = (long)difftime(timer, mktime(time_info)); + } + else + { + NXReportError( + "Your gmtime() function does not work ... timezone information will be incorrect\n"); + gmt_offset = 0; + } +#endif + time_info = localtime(&timer); + if (time_info != NULL) + { + if (gmt_offset < 0) + { + time_format = "%04d-%02d-%02dT%02d:%02d:%02d-%02d:%02d"; + } + else + { + time_format = "%04d-%02d-%02dT%02d:%02d:%02d+%02d:%02d"; + } + sprintf(time_buffer, time_format, 1900 + time_info->tm_year, 1 + time_info->tm_mon, time_info->tm_mday, time_info->tm_hour, time_info->tm_min, time_info->tm_sec, - abs(gmt_offset / 3600), abs((gmt_offset % 3600) / 60) + abs(gmt_offset / 3600), + abs((gmt_offset % 3600) / 60) ); - } else { - strcpy(time_buffer, "1970-01-01 00:00:00+0000"); - } - return time_buffer; + } + else + { + strcpy(time_buffer, "1970-01-01T00:00:00+00:00"); + } + return time_buffer; } - /*---------------------------------------------------------------------- F77 - API - Support - Routines ----------------------------------------------------------------------*/ @@ -1364,132 +1986,148 @@ char *NXIformatNeXusTime() * NXhandle. We could store the NXhandle value in the FORTRAN array * instead, but that would mean writing far more wrappers */ -NXstatus NXfopen(char *filename, NXaccess * am, NexusFunction * pHandle) -{ - NXstatus ret; - NXhandle fileid = NULL; - ret = NXopen(filename, *am, &fileid); - if (ret == NX_OK) { - memcpy(pHandle, fileid, sizeof(NexusFunction)); - } else { - memset(pHandle, 0, sizeof(NexusFunction)); + NXstatus NXfopen(char * filename, NXaccess* am, + NXhandle pHandle) + { + NXstatus ret; + NXhandle fileid = NULL; + ret = NXopen(filename, *am, &fileid); + if (ret == NX_OK) + { + memcpy(pHandle, fileid, getFileStackSize()); + } + else + { + memset(pHandle, 0, getFileStackSize()); + } + if (fileid != NULL) + { + free(fileid); + } + return ret; } - if (fileid != NULL) { - free(fileid); - } - return ret; -} - /* * The pHandle from FORTRAN is a pointer to a static FORTRAN * array holding the NexusFunction structure. We need to malloc() * a temporary copy as NXclose will try to free() this */ -NXstatus NXfclose(NexusFunction * pHandle) -{ - NXhandle h; - NXstatus ret; - h = (NXhandle) malloc(sizeof(NexusFunction)); - memcpy(h, pHandle, sizeof(NexusFunction)); - ret = NXclose(&h); /* does free(h) */ - memset(pHandle, 0, sizeof(NexusFunction)); - return ret; -} - -/*---------------------------------------------------------------------*/ -NXstatus NXfflush(NexusFunction * pHandle) -{ - NXhandle h; - NXstatus ret; - h = (NXhandle) malloc(sizeof(NexusFunction)); - memcpy(h, pHandle, sizeof(NexusFunction)); - ret = NXflush(&h); /* modifies and reallocates h */ - memcpy(pHandle, h, sizeof(NexusFunction)); - return ret; -} - + NXstatus NXfclose (NXhandle pHandle) + { + NXhandle h; + NXstatus ret; + h = (NXhandle)malloc(getFileStackSize()); + memcpy(h, pHandle, getFileStackSize()); + ret = NXclose(&h); /* does free(h) */ + memset(pHandle, 0, getFileStackSize()); + return ret; + } + +/*---------------------------------------------------------------------*/ + NXstatus NXfflush(NXhandle pHandle) + { + NXhandle h; + NXstatus ret; + h = (NXhandle)malloc(getFileStackSize()); + memcpy(h, pHandle, getFileStackSize()); + ret = NXflush(&h); /* modifies and reallocates h */ + memcpy(pHandle, h, getFileStackSize()); + return ret; + } /*----------------------------------------------------------------------*/ -NXstatus NXfmakedata(NXhandle fid, char *name, int *pDatatype, - int *pRank, int dimensions[]) -{ - NXstatus ret; - static char buffer[256]; - int i, *reversed_dimensions; - reversed_dimensions = (int *) malloc(*pRank * sizeof(int)); - if (reversed_dimensions == NULL) { - sprintf(buffer, - "ERROR: Cannot allocate space for array rank of %d in NXfmakedata", - *pRank); - NXIReportError(NXpData, buffer); - return NX_ERROR; - } + NXstatus NXfmakedata(NXhandle fid, char *name, int *pDatatype, + int *pRank, int dimensions[]) + { + NXstatus ret; + static char buffer[256]; + int i, *reversed_dimensions; + reversed_dimensions = (int*)malloc(*pRank * sizeof(int)); + if (reversed_dimensions == NULL) + { + sprintf (buffer, + "ERROR: Cannot allocate space for array rank of %d in NXfmakedata", + *pRank); + NXReportError( buffer); + return NX_ERROR; + } /* * Reverse dimensions array as FORTRAN is column major, C row major */ - for (i = 0; i < *pRank; i++) { - reversed_dimensions[i] = dimensions[*pRank - i - 1]; + for(i=0; i < *pRank; i++) + { + reversed_dimensions[i] = dimensions[*pRank - i - 1]; + } + ret = NXmakedata(fid, name, *pDatatype, *pRank, reversed_dimensions); + free(reversed_dimensions); + return ret; } - ret = NXmakedata(fid, name, *pDatatype, *pRank, reversed_dimensions); - free(reversed_dimensions); - return ret; -} - -NXstatus NXfcompmakedata(NXhandle fid, char *name, - int *pDatatype, - int *pRank, int dimensions[], - int *compression_type, int chunk[]) -{ - NXstatus ret; - static char buffer[256]; - int i, *reversed_dimensions, *reversed_chunk; - reversed_dimensions = (int *) malloc(*pRank * sizeof(int)); - reversed_chunk = (int *) malloc(*pRank * sizeof(int)); - if (reversed_dimensions == NULL || reversed_chunk == NULL) { - sprintf(buffer, - "ERROR: Cannot allocate space for array rank of %d in NXfcompmakedata", - *pRank); - NXIReportError(NXpData, buffer); - return NX_ERROR; - } +/*-----------------------------------------------------------------------*/ + NXstatus NXfcompmakedata(NXhandle fid, char *name, + int *pDatatype, + int *pRank, int dimensions[], + int *compression_type, int chunk[]) + { + NXstatus ret; + static char buffer[256]; + int i, *reversed_dimensions, *reversed_chunk; + reversed_dimensions = (int*)malloc(*pRank * sizeof(int)); + reversed_chunk = (int*)malloc(*pRank * sizeof(int)); + if (reversed_dimensions == NULL || reversed_chunk == NULL) + { + sprintf (buffer, + "ERROR: Cannot allocate space for array rank of %d in NXfcompmakedata", + *pRank); + NXReportError( buffer); + return NX_ERROR; + } /* * Reverse dimensions array as FORTRAN is column major, C row major */ - for (i = 0; i < *pRank; i++) { - reversed_dimensions[i] = dimensions[*pRank - i - 1]; - reversed_chunk[i] = chunk[*pRank - i - 1]; + for(i=0; i < *pRank; i++) + { + reversed_dimensions[i] = dimensions[*pRank - i - 1]; + reversed_chunk[i] = chunk[*pRank - i - 1]; + } + ret = NXcompmakedata(fid, name, *pDatatype, *pRank, + reversed_dimensions,*compression_type, reversed_chunk); + free(reversed_dimensions); + free(reversed_chunk); + return ret; } - ret = NXcompmakedata(fid, name, *pDatatype, *pRank, - reversed_dimensions, *compression_type, - reversed_chunk); - free(reversed_dimensions); - free(reversed_chunk); - return ret; -} - /*-----------------------------------------------------------------------*/ -NXstatus NXfcompress(NXhandle fid, int *compr_type) -{ - return NXcompress(fid, *compr_type); -} - + NXstatus NXfcompress(NXhandle fid, int *compr_type) + { + return NXcompress(fid,*compr_type); + } /*-----------------------------------------------------------------------*/ -NXstatus NXfputattr(NXhandle fid, char *name, void *data, - int *pDatalen, int *pIType) -{ - return NXputattr(fid, name, data, *pDatalen, *pIType); -} + NXstatus NXfputattr(NXhandle fid, const char *name, const void *data, + int *pDatalen, int *pIType) + { + return NXputattr(fid, name, data, *pDatalen, *pIType); + } /* * implement snprintf when it is not available */ -int nxisnprintf(char *buffer, int len, const char *format, ...) + int nxisnprintf(char* buffer, int len, const char* format, ... ) + { + int ret; + va_list valist; + va_start(valist,format); + ret = vsprintf(buffer, format, valist); + va_end(valist); + return ret; + } + +/*--------------------------------------------------------------------------*/ +NXstatus NXfgetpath(NXhandle fid, char *path, int *pathlen) { - int ret; - va_list valist; - va_start(valist, format); - ret = vsprintf(buffer, format, valist); - va_end(valist); - return ret; + return NXgetpath(fid,path,*pathlen); } + +const char* NXgetversion() +{ + return NEXUS_VERSION ; +} + diff --git a/napi.h b/napi.h index d3db9ddc..b7d3e1c9 100644 --- a/napi.h +++ b/napi.h @@ -3,7 +3,7 @@ Application Program Interface Header File - Copyright (C) 2000-2007 Mark Koennecke, Uwe Filges + Copyright (C) 2000-2011 Mark Koennecke, Uwe Filges This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -21,29 +21,49 @@ For further information, see - $Id: napi.h,v 1.13 2009/02/13 09:00:20 koennecke Exp $ + $Id: napi.h,v 1.14 2012/03/29 08:41:06 koennecke Exp $ ----------------------------------------------------------------------------*/ - +/** \file + * Documentation for the NeXus-API version 4.3 + * 2000-2011, the NeXus International Advisory Commitee + * \defgroup c_main C API + * \defgroup c_types Data Types + * \ingroup c_main + * \defgroup c_init General Initialisation and shutdown + * \ingroup c_main + * \defgroup c_group Reading and Writing Groups + * \ingroup c_main + * \defgroup c_readwrite Reading and Writing Data + * \ingroup c_main + * \defgroup c_navigation General File navigation + * \ingroup c_main + * \defgroup c_metadata Meta data routines + * \ingroup c_main + * \defgroup c_linking Linking + * \ingroup c_main + * \defgroup c_memory Memory allocation + * \ingroup c_main + * \defgroup c_external External linking + * \ingroup c_main + */ + #ifndef NEXUSAPI #define NEXUSAPI +#include + /* NeXus HDF45 */ -#define NEXUS_VERSION "4.1.0" /* major.minor.patch */ +#define NEXUS_VERSION "4.3.0" /* major.minor.patch */ #define CONSTCHAR const char -#ifdef _MSC_VER -#define snprintf nxisnprintf -extern int nxisnprintf(char *buffer, int len, const char *format, ...); -#endif /* _MSC_VER */ - -typedef void *NXhandle; /* really a pointer to a NexusFile structure */ +typedef void* NXhandle; /* really a pointer to a NexusFile structure */ typedef int NXstatus; typedef char NXname[128]; /* - * Any new NXaccess options should be numbered in 2^n format + * Any new NXaccess_mode options should be numbered in 2^n format * (8, 16, 32, etc) so that they can be bit masked and tested easily. * * To test older non bit masked options (values below 8) use e.g. @@ -55,18 +75,31 @@ typedef char NXname[128]; * if ( mode & NXACC_NOSTRIP ) * */ -#define NXACCMASK_REMOVEFLAGS (0x7) /* bit mask to remove higher flag options */ +#define NXACCMASK_REMOVEFLAGS (0x7) /* bit mask to remove higher flag options */ -typedef enum { NXACC_READ = 1, NXACC_RDWR = 2, NXACC_CREATE = - 3, NXACC_CREATE4 = 4, - NXACC_CREATE5 = 5, NXACC_CREATEXML = 6, NXACC_NOSTRIP = 128 -} NXaccess; +/** \enum NXaccess_mode + * NeXus file access codes. + * \li NXACC_READ read-only + * \li NXACC_RDWR open an existing file for reading and writing. + * \li NXACC_CREATE create a NeXus HDF-4 file + * \li NXACC_CREATE4 create a NeXus HDF-4 file + * \li NXACC_CREATE5 create a NeXus HDF-5 file. + * \li NXACC_CREATEXML create a NeXus XML file. + * \li NXACC_CHECKNAMESYNTAX Check names conform to NeXus allowed characters. + */ +typedef enum {NXACC_READ=1, NXACC_RDWR=2, NXACC_CREATE=3, NXACC_CREATE4=4, + NXACC_CREATE5=5, NXACC_CREATEXML=6, NXACC_TABLE=8, NXACC_NOSTRIP=128, NXACC_CHECKNAMESYNTAX=256 } NXaccess_mode; + +/** + * A combination of options from #NXaccess_mode + */ +typedef int NXaccess; typedef struct { - char *iname; - int type; -} info_type, *pinfo; - + char *iname; + int type; + }info_type, *pinfo; + #define NX_OK 1 #define NX_ERROR 0 #define NX_EOD -1 @@ -75,31 +108,41 @@ typedef struct { #define NX_MAXRANK 32 #define NX_MAXNAMELEN 64 +#define NX_MAXPATHLEN 1024 -/*------------------------------------------------------------------------- - HDF Datatype values for datatype parameters - in the Nexus API - NX_FLOAT32 32 bit float - NX_FLOAT64 64 nit float == double - NX_INT8 8 bit integer == byte - NX_UINT8 8 bit unsigned integer - NX_INT16 16 bit integer - NX_UINT16 16 bit unsigned integer - NX_INT32 32 bit integer - NX_UINT32 32 bit unsigned integer - NX_CHAR 8 bit character - NX_BINARY lump of binary data == NX_UINT8 - ---------------------------------------------------------------------------*/ +/** + * \ingroup c_types + * \def NX_FLOAT32 + * 32 bit float + * \def NX_FLOAT64 + * 64 bit float == double + * \def NX_INT8 + * 8 bit integer == byte + * \def NX_UINT8 + * 8 bit unsigned integer + * \def NX_INT16 + * 16 bit integer + * \def NX_UINT16 + * 16 bit unsigned integer + * \def NX_INT32 + * 32 bit integer + * \def NX_UINT32 + * 32 bit unsigned integer + * \def NX_CHAR + * 8 bit character + * \def NX_BINARY + * lump of binary data == NX_UINT8 +*/ +/*--------------------------------------------------------------------------*/ /* Map NeXus to HDF types */ #define NX_FLOAT32 5 #define NX_FLOAT64 6 -#define NX_INT8 20 +#define NX_INT8 20 #define NX_UINT8 21 #define NX_BOOLEAN NX_UINT -#define NX_INT16 22 +#define NX_INT16 22 #define NX_UINT16 23 #define NX_INT32 24 #define NX_UINT32 25 @@ -109,56 +152,79 @@ typedef struct { #define NX_BINARY 21 /* Map NeXus compression methods to HDF compression methods */ +#define NX_CHUNK 0 #define NX_COMP_NONE 100 #define NX_COMP_LZW 200 #define NX_COMP_RLE 300 -#define NX_COMP_HUF 400 +#define NX_COMP_HUF 400 + +/* to test for these we use ((value / 100) == NX_COMP_LZW) */ +#define NX_COMP_LZW_LVL0 (100*NX_COMP_LZW + 0) +#define NX_COMP_LZW_LVL1 (100*NX_COMP_LZW + 1) +#define NX_COMP_LZW_LVL2 (100*NX_COMP_LZW + 2) +#define NX_COMP_LZW_LVL3 (100*NX_COMP_LZW + 3) +#define NX_COMP_LZW_LVL4 (100*NX_COMP_LZW + 4) +#define NX_COMP_LZW_LVL5 (100*NX_COMP_LZW + 5) +#define NX_COMP_LZW_LVL6 (100*NX_COMP_LZW + 6) +#define NX_COMP_LZW_LVL7 (100*NX_COMP_LZW + 7) +#define NX_COMP_LZW_LVL8 (100*NX_COMP_LZW + 8) +#define NX_COMP_LZW_LVL9 (100*NX_COMP_LZW + 9) typedef struct { - long iTag; /* HDF4 variable */ - long iRef; /* HDF4 variable */ - char targetPath[1024]; /* path to item to link */ - int linkType; /* HDF5: 0 for group link, 1 for SDS link */ -} NXlink; + long iTag; /* HDF4 variable */ + long iRef; /* HDF4 variable */ + char targetPath[1024]; /* path to item to link */ + int linkType; /* HDF5: 0 for group link, 1 for SDS link */ + } NXlink; #define NXMAXSTACK 50 #define CONCAT(__a,__b) __a##__b /* token concatenation */ # ifdef __VMS -# define MANGLE(__arg) __arg +# define MANGLE(__arg) __arg # else # define MANGLE(__arg) CONCAT(__arg,_) # endif # define NXopen MANGLE(nxiopen) +# define NXreopen MANGLE(nxireopen) # define NXclose MANGLE(nxiclose) # define NXmakegroup MANGLE(nximakegroup) # define NXopengroup MANGLE(nxiopengroup) # define NXopenpath MANGLE(nxiopenpath) +# define NXgetpath MANGLE(nxigetpath) # define NXopengrouppath MANGLE(nxiopengrouppath) # define NXclosegroup MANGLE(nxiclosegroup) # define NXmakedata MANGLE(nximakedata) +# define NXmakedata64 MANGLE(nximakedata64) # define NXcompmakedata MANGLE(nxicompmakedata) +# define NXcompmakedata64 MANGLE(nxicompmakedata64) # define NXcompress MANGLE(nxicompress) # define NXopendata MANGLE(nxiopendata) # define NXclosedata MANGLE(nxiclosedata) # define NXputdata MANGLE(nxiputdata) # define NXputslab MANGLE(nxiputslab) +# define NXputslab64 MANGLE(nxiputslab64) # define NXputattr MANGLE(nxiputattr) # define NXgetdataID MANGLE(nxigetdataid) # define NXmakelink MANGLE(nximakelink) # define NXmakenamedlink MANGLE(nximakenamedlink) # define NXopensourcegroup MANGLE(nxiopensourcegroup) # define NXmalloc MANGLE(nximalloc) +# define NXmalloc64 MANGLE(nximalloc64) # define NXfree MANGLE(nxifree) # define NXflush MANGLE(nxiflush) # define NXgetinfo MANGLE(nxigetinfo) +# define NXgetinfo64 MANGLE(nxigetinfo64) +# define NXgetrawinfo MANGLE(nxigetrawinfo) +# define NXgetrawinfo64 MANGLE(nxigetrawinfo64) # define NXgetnextentry MANGLE(nxigetnextentry) # define NXgetdata MANGLE(nxigetdata) # define NXgetslab MANGLE(nxigetslab) +# define NXgetslab64 MANGLE(nxigetslab64) # define NXgetnextattr MANGLE(nxigetnextattr) # define NXgetattr MANGLE(nxigetattr) # define NXgetattrinfo MANGLE(nxigetattrinfo) @@ -169,9 +235,12 @@ typedef struct { # define NXinitattrdir MANGLE(nxiinitattrdir) # define NXsetnumberformat MANGLE(nxisetnumberformat) # define NXsetcache MANGLE(nxisetcache) -# define NXinquirefile MANGLE(nxiinquirefile) +# define NXinquirefile MANGLE(nxiinquirefile) # define NXisexternalgroup MANGLE(nxiisexternalgroup) +# define NXisexternaldataset MANGLE(nxiisexternaldataset) # define NXlinkexternal MANGLE(nxilinkexternal) +# define NXlinkexternaldataset MANGLE(nxilinkexternaldataset) +# define NXgetversion MANGLE(nxigetversion) /* * FORTRAN helpers - for NeXus internal use only @@ -183,7 +252,7 @@ typedef struct { # define NXfcompmakedata MANGLE(nxifcompmakedata) # define NXfcompress MANGLE(nxifcompress) # define NXfputattr MANGLE(nxifputattr) - +# define NXfgetpath MANGLE(nxifgetpath) /* * Standard interface @@ -196,167 +265,695 @@ typedef struct { #ifdef __cplusplus extern "C" { -#endif /* __cplusplus */ - extern NXstatus NXopen(CONSTCHAR * filename, NXaccess access_method, - NXhandle * pHandle); - extern NXstatus NXclose(NXhandle * pHandle); - extern NXstatus NXflush(NXhandle * pHandle); +#endif /* __cplusplus */ + /** + * Open a NeXus file. + * NXopen honours full path file names. But it also searches + * for files in all the paths given in the NX_LOAD_PATH environment variable. + * NX_LOAD_PATH is supposed to hold a list of path string separated by the platform + * specific path separator. For unix this is the : , for DOS the ; . Please note + * that crashing on an open NeXus file will result in corrupted data. Only after a NXclose + * or a NXflush will the data file be valid. + * \param filename The name of the file to open + * \param access_method The file access method. This can be: + * \li NXACC__READ read access + * \li NXACC_RDWR read write access + * \li NXACC_CREATE, NXACC_CREATE4 create a new HDF-4 NeXus file + * \li NXACC_CREATE5 create a new HDF-5 NeXus file + * \li NXACC_CREATEXML create an XML NeXus file. + * see #NXaccess_mode + * Support for HDF-4 is deprecated. + * \param pHandle A file handle which will be initialized upon successfull completeion of NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_init + */ +extern NXstatus NXopen(CONSTCHAR * filename, NXaccess access_method, NXhandle* pHandle); - extern NXstatus NXmakegroup(NXhandle handle, CONSTCHAR * name, - CONSTCHAR * NXclass); - extern NXstatus NXopengroup(NXhandle handle, CONSTCHAR * name, - CONSTCHAR * NXclass); - extern NXstatus NXopenpath(NXhandle handle, CONSTCHAR * path); - extern NXstatus NXopengrouppath(NXhandle handle, CONSTCHAR * path); + /** + * Opens an existing NeXus file a second time for e.g. access from another thread. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_init + */ +extern NXstatus NXreopen(NXhandle pOrigHandle, NXhandle* pNewHandle); - extern NXstatus NXclosegroup(NXhandle handle); + /** + * close a NeXus file + * \param pHandle A NeXus file handle as returned from NXopen. pHandle is invalid after this + * call. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_init + */ +extern NXstatus NXclose(NXhandle* pHandle); - extern NXstatus NXmakedata(NXhandle handle, CONSTCHAR * label, - int datatype, int rank, int dim[]); - extern NXstatus NXcompmakedata(NXhandle handle, CONSTCHAR * label, - int datatype, int rank, int dim[], - int comp_typ, int bufsize[]); - extern NXstatus NXcompress(NXhandle handle, int compr_type); - extern NXstatus NXopendata(NXhandle handle, CONSTCHAR * label); - extern NXstatus NXclosedata(NXhandle handle); - extern NXstatus NXputdata(NXhandle handle, void *data); + /** + * flush data to disk + * \param pHandle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXflush(NXhandle* pHandle); - extern NXstatus NXputattr(NXhandle handle, CONSTCHAR * name, void *data, - int iDataLen, int iType); - extern NXstatus NXputslab(NXhandle handle, void *data, int start[], - int size[]); + /** + * NeXus groups are NeXus way of structuring information into a hierarchy. + * This function creates a group but does not open it. + * \param handle A NeXus file handle as initialized NXopen. + * \param name The name of the group + * \param NXclass the class name of the group. Should start with the prefix NX + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_group + */ +extern NXstatus NXmakegroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); - extern NXstatus NXgetdataID(NXhandle handle, NXlink * pLink); - extern NXstatus NXmakelink(NXhandle handle, NXlink * pLink); - extern NXstatus NXmakenamedlink(NXhandle handle, CONSTCHAR * newname, - NXlink * pLink); - extern NXstatus NXopensourcegroup(NXhandle handle); + /** + * Step into a group. All further access will be within the opened group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the group + * \param NXclass the class name of the group. Should start with the prefix NX + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_group + */ +extern NXstatus NXopengroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); - extern NXstatus NXgetdata(NXhandle handle, void *data); - extern NXstatus NXgetinfo(NXhandle handle, int *rank, int dimension[], - int *datatype); - extern NXstatus NXgetnextentry(NXhandle handle, NXname name, - NXname nxclass, int *datatype); + /** + * Open the NeXus object with the path specified + * \param handle A NeXus file handle as returned from NXopen. + * \param path A unix like path string to a NeXus group or dataset. The path string + * is a list of group names and SDS names separated with / (slash). + * Example: /entry1/sample/name + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ +extern NXstatus NXopenpath (NXhandle handle, CONSTCHAR *path); - extern NXstatus NXgetslab(NXhandle handle, void *data, int start[], - int size[]); - extern NXstatus NXgetnextattr(NXhandle handle, NXname pName, - int *iLength, int *iType); - extern NXstatus NXgetattr(NXhandle handle, char *name, void *data, - int *iDataLen, int *iType); - extern NXstatus NXgetattrinfo(NXhandle handle, int *no_items); - extern NXstatus NXgetgroupID(NXhandle handle, NXlink * pLink); - extern NXstatus NXgetgroupinfo(NXhandle handle, int *no_items, - NXname name, NXname nxclass); - extern NXstatus NXsameID(NXhandle handle, NXlink * pFirstID, - NXlink * pSecondID); + /** + * Opens the group in which the NeXus object with the specified path exists + * \param handle A NeXus file handle as initialized by NXopen. + * \param path A unix like path string to a NeXus group or dataset. The path string + * is a list of group names and SDS names separated with / (slash). + * Example: /entry1/sample/name + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ +extern NXstatus NXopengrouppath (NXhandle handle, CONSTCHAR *path); - extern NXstatus NXinitgroupdir(NXhandle handle); - extern NXstatus NXinitattrdir(NXhandle handle); - extern NXstatus NXsetnumberformat(NXhandle handle, - int type, char *format); + /** + * Retrieve the current path in the NeXus file + * \param handle a NeXus file handle + * \param path A buffer to copy the path too + * \param pathlen The maximum number of characters to copy into path + * \return NX_OK or NX_ERROR + * \ingroup c_navigation + */ +extern NXstatus NXgetpath(NXhandle handle, char *path, int pathlen); - extern NXstatus NXinquirefile(NXhandle handle, char *filename, - int filenameBufferLength); - extern NXstatus NXisexternalgroup(NXhandle fid, CONSTCHAR * name, - CONSTCHAR * nxclass, char *url, - int urlLen); - extern NXstatus NXlinkexternal(NXhandle fid, CONSTCHAR * name, - CONSTCHAR * nxclass, CONSTCHAR * url); + /** + * Closes the currently open group and steps one step down in the NeXus file + * hierarchy. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_group + */ +extern NXstatus NXclosegroup(NXhandle handle); - extern NXstatus NXmalloc(void **data, int rank, int dimensions[], - int datatype); - extern NXstatus NXfree(void **data); + /** + * Create a multi dimensional data array or dataset. The dataset is NOT opened. + * \param handle A NeXus file handle as initialized by NXopen. + * \param label The name of the dataset + * \param datatype The data type of this data set. + * \param rank The number of dimensions this dataset is going to have + * \param dim An array of size rank holding the size of the dataset in each dimension. The first dimension + * can be NX_UNLIMITED. Data can be appended to such a dimension using NXputslab. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); + + + /** + * @copydoc NXmakedata() + */ +extern NXstatus NXmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]); + + +/** + * Create a compressed dataset. The dataset is NOT opened. Data from this set will automatically be compressed when + * writing and decompressed on reading. + * \param handle A NeXus file handle as initialized by NXopen. + * \param label The name of the dataset + * \param datatype The data type of this data set. + * \param rank The number of dimensions this dataset is going to have + * \param comp_typ The compression scheme to use. Possible values: + * \li NX_COMP_NONE no compression + * \li NX_COMP_LZW lossless Lempel Ziv Welch compression (recommended) + * \li NX_COMP_RLE run length encoding (only HDF-4) + * \li NX_COMP_HUF Huffmann encoding (only HDF-4) + * \param dim An array of size rank holding the size of the dataset in each dimension. The first dimension + * can be NX_UNLIMITED. Data can be appended to such a dimension using NXputslab. + * \param bufsize The dimensions of the subset of the data which usually be writen in one go. + * This is a parameter used by HDF for performance optimisations. If you write your data in one go, this + * should be the same as the data dimension. If you write it in slabs, this is your preferred slab size. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXcompmakedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]); + + +/** + * @copydoc NXcompmakedata() + */ +extern NXstatus NXcompmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t chunk_size[]); + + + /** + * Switch compression on. This routine is superseeded by NXcompmakedata and thus + * is deprecated. + * \param handle A NeXus file handle as initialized by NXopen. + * \param compr_type The compression scheme to use. Possible values: + * \li NX_COMP_NONE no compression + * \li NX_COMP_LZW lossless Lempel Ziv Welch compression (recommended) + * \li NX_COMP_RLE run length encoding (only HDF-4) + * \li NX_COMP_HUF Huffmann encoding (only HDF-4) + * \ingroup c_readwrite + */ +extern NXstatus NXcompress (NXhandle handle, int compr_type); + + /** + * Open access to a dataset. After this call it is possible to write and read data or + * attributes to and from the dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \param label The name of the dataset + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXopendata (NXhandle handle, CONSTCHAR* label); + + /** + * Close access to a dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXclosedata(NXhandle handle); + + /** + * Write data to a datset which has previouly been opened with NXopendata. + * This writes all the data in one go. Data should be a pointer to a memory + * area matching the datatype and dimensions of the dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \param data Pointer to data to write. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXputdata(NXhandle handle, const void* data); + + /** + * Write an attribute. The kind of attribute written depends on the + * poistion in the file: at root level, a global attribute is written, if + * agroup is open but no dataset, a group attribute is written, if a dataset is + * open, a dataset attribute is written. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the attribute. + * \param data A pointer to the data to write for the attribute. + * \param iDataLen The length of the data in data in bytes. + * \param iType The NeXus data type of the attribute. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXputattr(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType); + + /** + * Write a subset of a multi dimensional dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \param data A pointer to a memory area holding the data to write. + * \param start An array holding the start indices where to start the data subset. + * \param size An array holding the size of the data subset to write in each dimension. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXputslab(NXhandle handle, const void* data, const int start[], const int size[]); + + /** + * @copydoc NXputdata() + */ +extern NXstatus NXputslab64(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]); + + /** + * Retrieve link data for a dataset. This link data can later on be used to link this + * dataset into a different group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param pLink A link data structure which will be initialized with the required information + * for linking. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_linking + */ +extern NXstatus NXgetdataID(NXhandle handle, NXlink* pLink); + + /** + * Create a link to the group or dataset described by pLink in the currently open + * group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param pLink A link data structure describing the object to link. This must have been initialized + * by either a call to NXgetdataID or NXgetgroupID. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_linking + */ +extern NXstatus NXmakelink(NXhandle handle, NXlink* pLink); + + /** + * Create a link to the group or dataset described by pLink in the currently open + * group. But give the linked item a new name. + * \param handle A NeXus file handle as initialized by NXopen. + * \param newname The new name of the item in the currently open group. + * \param pLink A link data structure describing the object to link. This must have been initialized + * by either a call to NXgetdataID or NXgetgroupID. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_linking + */ +extern NXstatus NXmakenamedlink(NXhandle handle, CONSTCHAR* newname, NXlink* pLink); + + /** + * Open the source group of a linked group or dataset. Returns an error when the item is + * not a linked item. + * \param handle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ +extern NXstatus NXopensourcegroup(NXhandle handle); + + /** + * Read a complete dataset from the currently open dataset into memory. + * \param handle A NeXus file handle as initialized by NXopen. + * \param data A pointer to the memory area where to read the data, too. Data must point to a memory + * area large enough to accomodate the data read. Otherwise your program may behave in unexpected + * and unwelcome ways. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXgetdata(NXhandle handle, void* data); + + /** + * Retrieve information about the curretly open dataset. + * \param handle A NeXus file handle as initialized by NXopen. + * \param rank A pointer to an integer which will be filled with the rank of + * the dataset. + * \param dimension An array which will be initialized with the size of the dataset in any of its + * dimensions. The array must have at least the size of rank. + * \param datatype A pointer to an integer which be set to the NeXus data type code for this dataset. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ +extern NXstatus NXgetinfo(NXhandle handle, int* rank, int dimension[], int* datatype); + + /** + * @copydoc NXgetinfo() + */ +extern NXstatus NXgetinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype); + + /** + * Get the next entry in the currently open group. This is for retrieving infromation about the + * content of a NeXus group. In order to search a group #NXgetnextentry is called in a loop until + * #NXgetnextentry returns NX_EOD which indicates that there are no further items in the group. + * Reset search using #NXinitgroupdir + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the object + * \param nxclass The NeXus class name for a group or the string SDS for a dataset. + * \param datatype The NeXus data type if the item is a SDS. + * \return NX_OK on success, NX_ERROR in the case of an error, NX_EOD when there are no more items. + * \ingroup c_navigation + */ +extern NXstatus NXgetnextentry(NXhandle handle, NXname name, NXname nxclass, int* datatype); + + /** + * Read a subset of data from file into memory. + * \param handle A NeXus file handle as initialized by NXopen. + * \param data A pointer to the memory data where to copy the data too. The pointer must point + * to a memory area large enough to accomodate the size of the data read. + * \param start An array holding the start indices where to start reading the data subset. + * \param size An array holding the size of the data subset to read for each dimension. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXgetslab(NXhandle handle, void* data, int start[], int size[]); + + + /** + * @copydoc NXgetslab() + */ +extern NXstatus NXgetslab64(NXhandle handle, void* data, const int64_t start[], const int64_t size[]); + +/** + * Iterate over global, group or dataset attributes depending on the currently open group or + * dataset. In order to search attributes multiple calls to #NXgetnextattr are performed in a loop + * until #NXgetnextattr returns NX_EOD which indicates that there are no further attributes. + * reset search using #NXinitattrdir + * \param handle A NeXus file handle as initialized by NXopen. + * \param pName The name of the attribute + * \param iLength A pointer to an integer which be set to the length of the attribute data. + * \param iType A pointer to an integer which be set to the NeXus data type of the attribute. + * \return NX_OK on success, NX_ERROR in the case of an error, NX_EOD when there are no more items. + * \ingroup c_readwrite + */ +extern NXstatus NXgetnextattr(NXhandle handle, NXname pName, int *iLength, int *iType); + + /** + * Read an attribute. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the atrribute to read. + * \param data A pointer to a memory area large enough to hold the attributes value. + * \param iDataLen The length of data in bytes. + * \param iType A pointer to an integer which will had been set to the NeXus data type of the attribute. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXgetattr(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); + + /** + * Get the count of attributes in the currently open dataset, group or global attributes when at root level. + * \param handle A NeXus file handle as initialized by NXopen. + * \param no_items A pointer to an integer which be set to the number of attributes available. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ +extern NXstatus NXgetattrinfo(NXhandle handle, int* no_items); + + /** + * Retrieve link data for the currently open group. This link data can later on be used to link this + * group into a different group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param pLink A link data structure which will be initialized with the required information + * for linking. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_linking + */ +extern NXstatus NXgetgroupID(NXhandle handle, NXlink* pLink); + + /** + * Retrieve information about the currently open group. + * \param handle A NeXus file handle as initialized by NXopen. + * \param no_items A pointer to an integer which will be set to the count + * of group elements available. This is the count of other groups and + * data sets in this group. + * \param name The name of the group. + * \param nxclass The NeXus class name of the group. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ +extern NXstatus NXgetgroupinfo(NXhandle handle, int* no_items, NXname name, NXname nxclass); + + /** + * Tests if two link data structures describe the same item. + * \param handle A NeXus file handle as initialized by NXopen. + * \param pFirstID The first link data for the test. + * \param pSecondID The second link data structure. + * \return NX_OK when both link data structures describe the same item, NX_ERROR else. + * \ingroup c_linking + */ +extern NXstatus NXsameID(NXhandle handle, NXlink* pFirstID, NXlink* pSecondID); + + /** + * Resets a pending group search to the start again. To be called in a #NXgetnextentry loop when + * a group search has to be restarted. + * \param handle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ +extern NXstatus NXinitgroupdir(NXhandle handle); + + /** + * Resets a pending attribute search to the start again. To be called in a #NXgetnextattr loop when + * an attribute search has to be restarted. + * \param handle A NeXus file handle as initialized by NXopen. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_navigation + */ +extern NXstatus NXinitattrdir(NXhandle handle); + + /** + * Sets the format for number printing. This call has only an effect when using the XML physical file + * format. + * \param handle A NeXus file handle as initialized by NXopen. + * \param type The NeXus data type to set the format for. + * \param format The C-language format string to use for this data type. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_readwrite + */ +extern NXstatus NXsetnumberformat(NXhandle handle, int type, char *format); + + /** + * Inquire the filename of the currently open file. FilenameBufferLength of the file name + * will be copied into the filename buffer. + * \param handle A NeXus file handle as initialized by NXopen. + * \param filename The buffer to hold the filename. + * \param filenameBufferLength The length of the filename buffer. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ +extern NXstatus NXinquirefile(NXhandle handle, char *filename, int filenameBufferLength); + + /** + * Test if a group is actually pointing to an external file. If so, retrieve the URL of the + * external file. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the group to test. + * \param nxclass The class name of the group to test. + * \param url A buffer to copy the URL too. + * \param urlLen The length of the Url buffer. At maximum urlLen bytes will be copied to url. + * \return NX_OK when the group is pointing to an external file, NX_ERROR else. + * \ingroup c_external + */ +extern NXstatus NXisexternalgroup(NXhandle handle, CONSTCHAR *name, CONSTCHAR *nxclass, char *url, int urlLen); + + + /** + * Test if a dataset is actually pointing to an external file. If so, retrieve the URL of the + * external file. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the dataset to test. + * \param url A buffer to copy the URL too. + * \param urlLen The length of the Url buffer. At maximum urlLen bytes will be copied to url. + * \return NX_OK when the dataset is pointing to an external file, NX_ERROR else. + * \ingroup c_external + */ +extern NXstatus NXisexternaldataset(NXhandle handle, CONSTCHAR *name, char *url, int urlLen); + + /** + * Create a link to a group in an external file. This works by creating a NeXus group under the current level in + * the hierarchy which actually points to a group in another file. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the group which points to the external file. + * \param nxclass The class name of the group which points to the external file. + * \param url The URL of the external file. Currently only one URL format is supported: nxfile://path-tofile\#path-in-file. + * This consists of two parts: the first part is of course the path to the file. The second part, path-in-file, is the + * path to the group in the external file which appears in the first file. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_external + */ +extern NXstatus NXlinkexternal(NXhandle handle, CONSTCHAR *name, CONSTCHAR *nxclass, CONSTCHAR *url); + + + /** + * Create a link to a dataset in an external file. This works by creating a dataset under the current level in + * the hierarchy which actually points to a dataset in another file. + * \param handle A NeXus file handle as initialized by NXopen. + * \param name The name of the dataset which points to the external file. + * \param url The URL of the external file. Currently only one URL format is supported: nxfile://path-tofile\#path-in-file. + * This consists of two parts: the first part is of course the path to the file. The second part, path-in-file, is the + * path to the dataset in the external file which appears in the first file. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_external + */ +extern NXstatus NXlinkexternaldataset(NXhandle handle, CONSTCHAR *name, CONSTCHAR *url); + + /** + * Utility function which allocates a suitably sized memory area for the dataset characteristics specified. + * \param data A pointer to a pointer which will be initialized with a pointer to a suitably sized memory area. + * \param rank the rank of the data. + * \param dimensions An array holding the size of the data in each dimension. + * \param datatype The NeXus data type of the data. + * \return NX_OK when allocation succeeds, NX_ERROR in the case of an error. + * \ingroup c_memory + */ +extern NXstatus NXmalloc(void** data, int rank, int dimensions[], int datatype); + + /** + * @copydoc NXmalloc() + */ +extern NXstatus NXmalloc64(void** data, int rank, int64_t dimensions[], int datatype); + + + /** + * Utility function to return NeXus version + * \return pointer to string in static storage. Version in + * same format as NEXUS_VERSION string in napi.h i.e. "major.minor.patch" + * \ingroup c_metadata + */ +extern const char* NXgetversion(); + + /** + * Utility function to release the memory for data. + * \param data A pointer to a pointer to free. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_memory + */ +extern NXstatus NXfree(void** data); /*----------------------------------------------------------------------- NAPI internals ------------------------------------------------------------------------*/ - typedef void (*ErrFunc) (void *data, char *text); - extern void NXMSetError(void *pData, ErrFunc); - extern ErrFunc NXMGetError(); - extern void NXMDisableErrorReporting(); - extern void NXMEnableErrorReporting(); - extern void (*NXIReportError) (void *pData, char *text); - extern void *NXpData; - extern char *NXIformatNeXusTime(); - extern NXstatus NXIprintlink(NXhandle fid, NXlink * link); + /** + * Retrieve information about the currently open dataset. In contrast to the main function below, + * this function does not try to find out about the size of strings properly. + * \param handle A NeXus file handle as initialized by NXopen. + * \param rank A pointer to an integer which will be filled with the rank of + * the dataset. + * \param dimension An array which will be initialized with the size of the dataset in any of its + * dimensions. The array must have at least the size of rank. + * \param datatype A pointer to an integer which be set to the NeXus data type code for this dataset. + * \return NX_OK on success, NX_ERROR in the case of an error. + * \ingroup c_metadata + */ +extern NXstatus NXgetrawinfo(NXhandle handle, int* rank, int dimension[], int* datatype); -/* - another special function for setting the default cache size for HDF-5 -*/ - extern NXstatus NXsetcache(long newVal); + /** + * @copydoc NXgetrawinfo + */ +extern NXstatus NXgetrawinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype); + +/** \typedef void (*ErrFunc)(void *data, char *text) + * All NeXus error reporting happens through this special function, the + * ErrFunc. The NeXus-API allows to replace this error reporting function + * through a user defined implementation. The default error function prints to stderr. User + * defined ones may pop up dialog boxes or whatever. + * \param data A pointer to some user defined data structure + * \param text The text of the error message to display. + */ +typedef void (*ErrFunc)(void *data, char *text); + + /** + * Set a global error function. + * Not threadsafe. + * \param pData A pointer to a user defined data structure which be passed to + * the error display function. + * \param newErr The new error display function. + */ +extern void NXMSetError(void *pData, ErrFunc newErr); + + /** + * Set an error function for the current thread. + * When used this overrides anything set in NXMSetError (for the current thread). + * Use this method in threaded applications. + * \param pData A pointer to a user defined data structure which be passed to + * the error display function. + * \param newErr The new error display function. + */ +extern void NXMSetTError(void *pData, ErrFunc newErr); + + /** + * Retrieve the current error display function + * \return The current error display function. + */ +extern ErrFunc NXMGetError(); + + /** + * Suppress error reports from the NeXus-API + */ +extern void NXMDisableErrorReporting(); + + /** + * Enable error reports from the NeXus-API + */ +extern void NXMEnableErrorReporting(); + + /** + * Dispatches the error message to the error function defined by NXMSetTError + */ +extern void NXReportError(char *text); + + /** + * Do not use, first parameter should be set by NXMSetTError + */ +extern void NXIReportError(void *pData,char *text); +/* extern void *NXpData; */ +extern char *NXIformatNeXusTime(); +extern NXstatus NXIprintlink(NXhandle fid, NXlink* link); + +/** + * A function for setting the default cache size for HDF-5 + * \ingroup c_init + */ +extern NXstatus NXsetcache(long newVal); typedef struct { - NXhandle *pNexusData; - int stripFlag; - NXstatus(*nxclose) (NXhandle * pHandle); - NXstatus(*nxflush) (NXhandle * pHandle); - NXstatus(*nxmakegroup) (NXhandle handle, CONSTCHAR * name, - CONSTCHAR * NXclass); - NXstatus(*nxopengroup) (NXhandle handle, CONSTCHAR * name, - CONSTCHAR * NXclass); - NXstatus(*nxclosegroup) (NXhandle handle); - NXstatus(*nxmakedata) (NXhandle handle, CONSTCHAR * label, - int datatype, int rank, int dim[]); - NXstatus(*nxcompmakedata) (NXhandle handle, CONSTCHAR * label, - int datatype, int rank, int dim[], - int comp_typ, int bufsize[]); - NXstatus(*nxcompress) (NXhandle handle, int compr_type); - NXstatus(*nxopendata) (NXhandle handle, CONSTCHAR * label); - NXstatus(*nxclosedata) (NXhandle handle); - NXstatus(*nxputdata) (NXhandle handle, void *data); - NXstatus(*nxputattr) (NXhandle handle, CONSTCHAR * name, void *data, - int iDataLen, int iType); - NXstatus(*nxputslab) (NXhandle handle, void *data, int start[], - int size[]); - NXstatus(*nxgetdataID) (NXhandle handle, NXlink * pLink); - NXstatus(*nxmakelink) (NXhandle handle, NXlink * pLink); - NXstatus(*nxmakenamedlink) (NXhandle handle, CONSTCHAR * newname, - NXlink * pLink); - NXstatus(*nxgetdata) (NXhandle handle, void *data); - NXstatus(*nxgetinfo) (NXhandle handle, int *rank, int dimension[], - int *datatype); - NXstatus(*nxgetnextentry) (NXhandle handle, NXname name, - NXname nxclass, int *datatype); - NXstatus(*nxgetslab) (NXhandle handle, void *data, int start[], - int size[]); - NXstatus(*nxgetnextattr) (NXhandle handle, NXname pName, int *iLength, - int *iType); - NXstatus(*nxgetattr) (NXhandle handle, char *name, void *data, - int *iDataLen, int *iType); - NXstatus(*nxgetattrinfo) (NXhandle handle, int *no_items); - NXstatus(*nxgetgroupID) (NXhandle handle, NXlink * pLink); - NXstatus(*nxgetgroupinfo) (NXhandle handle, int *no_items, - NXname name, NXname nxclass); - NXstatus(*nxsameID) (NXhandle handle, NXlink * pFirstID, - NXlink * pSecondID); - NXstatus(*nxinitgroupdir) (NXhandle handle); - NXstatus(*nxinitattrdir) (NXhandle handle); - NXstatus(*nxsetnumberformat) (NXhandle handle, int type, - char *format); - NXstatus(*nxprintlink) (NXhandle handle, NXlink * link); + NXhandle pNexusData; + NXstatus ( *nxreopen)(NXhandle pOrigHandle, NXhandle* pNewHandle); + NXstatus ( *nxclose)(NXhandle* pHandle); + NXstatus ( *nxflush)(NXhandle* pHandle); + NXstatus ( *nxmakegroup) (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); + NXstatus ( *nxopengroup) (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); + NXstatus ( *nxclosegroup)(NXhandle handle); + NXstatus ( *nxmakedata64) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]); + NXstatus ( *nxcompmakedata64) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[]); + NXstatus ( *nxcompress) (NXhandle handle, int compr_type); + NXstatus ( *nxopendata) (NXhandle handle, CONSTCHAR* label); + NXstatus ( *nxclosedata)(NXhandle handle); + NXstatus ( *nxputdata)(NXhandle handle, const void* data); + NXstatus ( *nxputattr)(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType); + NXstatus ( *nxputslab64)(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]); + NXstatus ( *nxgetdataID)(NXhandle handle, NXlink* pLink); + NXstatus ( *nxmakelink)(NXhandle handle, NXlink* pLink); + NXstatus ( *nxmakenamedlink)(NXhandle handle, CONSTCHAR *newname, NXlink* pLink); + NXstatus ( *nxgetdata)(NXhandle handle, void* data); + NXstatus ( *nxgetinfo64)(NXhandle handle, int* rank, int64_t dimension[], int* datatype); + NXstatus ( *nxgetnextentry)(NXhandle handle, NXname name, NXname nxclass, int* datatype); + NXstatus ( *nxgetslab64)(NXhandle handle, void* data, const int64_t start[], const int64_t size[]); + NXstatus ( *nxgetnextattr)(NXhandle handle, NXname pName, int *iLength, int *iType); + NXstatus ( *nxgetattr)(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); + NXstatus ( *nxgetattrinfo)(NXhandle handle, int* no_items); + NXstatus ( *nxgetgroupID)(NXhandle handle, NXlink* pLink); + NXstatus ( *nxgetgroupinfo)(NXhandle handle, int* no_items, NXname name, NXname nxclass); + NXstatus ( *nxsameID)(NXhandle handle, NXlink* pFirstID, NXlink* pSecondID); + NXstatus ( *nxinitgroupdir)(NXhandle handle); + NXstatus ( *nxinitattrdir)(NXhandle handle); + NXstatus ( *nxsetnumberformat)(NXhandle handle, int type, char *format); + NXstatus ( *nxprintlink)(NXhandle handle, NXlink* link); + NXstatus ( *nxnativeexternallink)(NXhandle handle, CONSTCHAR* name, CONSTCHAR* externalfile, CONSTCHAR* remotetarget); + NXstatus ( *nxnativeinquirefile)(NXhandle handle, char* externalfile, const int filenamelength); + NXstatus ( *nxnativeisexternallink)(NXhandle handle, CONSTCHAR* name, char* url, int urllen); + int stripFlag; + int checkNameSyntax; } NexusFunction, *pNexusFunction; /*---------------------*/ extern long nx_cacheSize; /* FORTRAN internals */ - extern NXstatus NXfopen(char *filename, NXaccess * am, - NexusFunction * pHandle); - extern NXstatus NXfclose(NexusFunction * pHandle); - extern NXstatus NXfputattr(NXhandle fid, char *name, void *data, - int *pDatalen, int *pIType); - extern NXstatus NXfcompress(NXhandle fid, int *compr_type); - extern NXstatus NXfcompmakedata(NXhandle fid, char *name, - int *pDatatype, - int *pRank, int dimensions[], - int *compression_type, int chunk[]); - extern NXstatus NXfmakedata(NXhandle fid, char *name, int *pDatatype, - int *pRank, int dimensions[]); - extern NXstatus NXfflush(NexusFunction * pHandle); - + extern NXstatus NXfopen(char * filename, NXaccess* am, + NXhandle pHandle); + extern NXstatus NXfclose (NXhandle pHandle); + extern NXstatus NXfputattr(NXhandle fid, const char *name, const void *data, + int *pDatalen, int *pIType); + extern NXstatus NXfcompress(NXhandle fid, int *compr_type); + extern NXstatus NXfcompmakedata(NXhandle fid, char *name, + int *pDatatype, + int *pRank, int dimensions[], + int *compression_type, int chunk[]); + extern NXstatus NXfmakedata(NXhandle fid, char *name, int *pDatatype, + int *pRank, int dimensions[]); + extern NXstatus NXfflush(NXhandle pHandle); + extern NXstatus NXfgetpath(NXhandle fid, char *path, int *pathlen); #ifdef __cplusplus } -#endif /* __cplusplus */ +#endif /* __cplusplus */ + +/** + * Freddie Akeroyd 11/8/2009 + * Add NeXus schema support - this uses BASE.xsd as the initial file + */ +#define NEXUS_SCHEMA_VERSION "3.1" /**< version of NeXus definition schema */ +#define NEXUS_SCHEMA_ROOT "http://definition.nexusformat.org/schema/" /**< XML schema namespace specified by xmlns */ +#define NEXUS_SCHEMA_NAMESPACE NEXUS_SCHEMA_ROOT NEXUS_SCHEMA_VERSION /**< XML schema namespace specified by xmlns */ +#define NEXUS_SCHEMA_BASE "BASE" +#define NEXUS_SCHEMA_FILE NEXUS_SCHEMA_BASE ".xsd" /**< default schema file for namespace */ +#define NEXUS_SCHEMA_URL NEXUS_SCHEMA_NAMESPACE "/" NEXUS_SCHEMA_FILE /**< location of default schema file for namespace */ + #endif /*NEXUSAPI*/ diff --git a/napi4.c b/napi4.c index 289b8f3e..0545734d 100644 --- a/napi4.c +++ b/napi4.c @@ -19,11 +19,14 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see - $Id: napi4.c,v 1.10 2009/02/13 09:00:20 koennecke Exp $ + $Id: napi4.c,v 1.11 2012/03/29 08:41:06 koennecke Exp $ ----------------------------------------------------------------------------*/ + +#ifdef HDF4 + #include #include #include @@ -32,1834 +35,1949 @@ #include "napi.h" #include "napi4.h" -extern void *NXpData; +extern void *NXpData; -typedef struct __NexusFile { - struct iStack { - int32 *iRefDir; - int32 *iTagDir; - int32 iVref; - int32 __iStack_pad; - int iNDir; - int iCurDir; - } iStack[NXMAXSTACK]; - struct iStack iAtt; - int32 iVID; - int32 iSID; - int32 iCurrentVG; - int32 iCurrentSDS; - int iNXID; - int iStackPtr; - char iAccess[2]; -} NexusFile, *pNexusFile; - - /*--------------------------------------------------------------------*/ - -static pNexusFile NXIassert(NXhandle fid) -{ - pNexusFile pRes; - - assert(fid != NULL); - pRes = (pNexusFile) fid; - assert(pRes->iNXID == NXSIGNATURE); - return pRes; -} + typedef struct __NexusFile { + struct iStack { + int32 *iRefDir; + int32 *iTagDir; + int32 iVref; + int32 __iStack_pad; + int iNDir; + int iCurDir; + } iStack[NXMAXSTACK]; + struct iStack iAtt; + int32 iVID; + int32 iSID; + int32 iCurrentVG; + int32 iCurrentSDS; + int iNXID; + int iStackPtr; + char iAccess[2]; + } NexusFile, *pNexusFile; + /*-------------------------------------------------------------------*/ + static pNexusFile NXIassert(NXhandle fid) + { + pNexusFile pRes; + + assert(fid != NULL); + pRes = (pNexusFile)fid; + assert(pRes->iNXID == NXSIGNATURE); + return pRes; + } /*----------------------------------------------------------------------*/ static int findNapiClass(pNexusFile pFile, int groupRef, NXname nxclass) { NXname classText, linkClass; int32 tags[2], attID, linkID, groupID; - groupID = Vattach(pFile->iVID, groupRef, "r"); + groupID = Vattach(pFile->iVID,groupRef,"r"); Vgetclass(groupID, classText); - if (strcmp(classText, "NAPIlink") != 0) { + if(strcmp(classText,"NAPIlink") != 0) + { /* normal group */ - strcpy(nxclass, classText); + strcpy(nxclass,classText); Vdetach(groupID); return groupRef; - } else { + } + else + { /* code for linked renamed groups */ - attID = Vfindattr(groupID, "NAPIlink"); - if (attID >= 0) { - Vgetattr(groupID, attID, tags); - linkID = Vattach(pFile->iVID, tags[1], "r"); + attID = Vfindattr(groupID,"NAPIlink"); + if(attID >= 0) + { + Vgetattr(groupID,attID, tags); + linkID = Vattach(pFile->iVID,tags[1],"r"); Vgetclass(linkID, linkClass); Vdetach(groupID); Vdetach(linkID); - strcpy(nxclass, linkClass); + strcpy(nxclass,linkClass); return tags[1]; - } else { + } + else + { /* this allows for finding the NAPIlink group in NXmakenamedlink */ - strcpy(nxclass, classText); + strcpy(nxclass,classText); Vdetach(groupID); return groupRef; } - } + } } - /* --------------------------------------------------------------------- */ -static int32 NXIFindVgroup(pNexusFile pFile, CONSTCHAR * name, - CONSTCHAR * nxclass) -{ - int32 iNew, iRef, iTag; - int iN, i, status; - int32 *pArray = NULL; - NXname pText; - - assert(pFile != NULL); - - if (pFile->iCurrentVG == 0) { /* root level */ - /* get the number and ID's of all lone Vgroups in the file */ - iN = Vlone(pFile->iVID, NULL, 0); - if (iN == 0) { - return NX_EOD; - } - pArray = (int32 *) malloc(iN * sizeof(int32)); - if (!pArray) { - NXIReportError(NXpData, "ERROR: out of memory in NXIFindVgroup"); - return NX_EOD; - } - Vlone(pFile->iVID, pArray, iN); - - /* loop and check */ - for (i = 0; i < iN; i++) { - iNew = Vattach(pFile->iVID, pArray[i], "r"); - Vgetname(iNew, pText); - Vdetach(iNew); - if (strcmp(pText, name) == 0) { - pArray[i] = findNapiClass(pFile, pArray[i], pText); - if (strcmp(pText, nxclass) == 0) { - /* found ! */ - iNew = pArray[i]; - free(pArray); - return iNew; - } + static int32 NXIFindVgroup (pNexusFile pFile, CONSTCHAR *name, CONSTCHAR *nxclass) + { + int32 iNew, iRef, iTag; + int iN, i; + int32 *pArray = NULL; + NXname pText; + + assert (pFile != NULL); + + if (pFile->iCurrentVG == 0) { /* root level */ + /* get the number and ID's of all lone Vgroups in the file */ + iN = Vlone (pFile->iVID, NULL, 0); + if(iN == 0) { + return NX_EOD; } - } - /* nothing found */ - free(pArray); - return NX_EOD; - } else { /* case in Vgroup */ - iN = Vntagrefs(pFile->iCurrentVG); - for (i = 0; i < iN; i++) { - Vgettagref(pFile->iCurrentVG, i, &iTag, &iRef); - if (iTag == DFTAG_VG) { - iNew = Vattach(pFile->iVID, iRef, "r"); - Vgetname(iNew, pText); + pArray = (int32 *) malloc (iN * sizeof (int32)); + if (!pArray) { + NXReportError( "ERROR: out of memory in NXIFindVgroup"); + return NX_EOD; + } + Vlone (pFile->iVID, pArray, iN); + + /* loop and check */ + for (i = 0; i < iN; i++) { + iNew = Vattach (pFile->iVID, pArray[i], "r"); + Vgetname (iNew, pText); Vdetach(iNew); - if (strcmp(pText, name) == 0) { - iRef = findNapiClass(pFile, iRef, pText); - if (strcmp(pText, nxclass) == 0) { - return iRef; + if (strcmp (pText, name) == 0) { + pArray[i] = findNapiClass(pFile,pArray[i],pText); + if (strcmp (pText, nxclass) == 0) { + /* found ! */ + iNew = pArray[i]; + free (pArray); + return iNew; } } } - } /* end for */ - } /* end else */ - /* not found */ - return NX_EOD; -} - - /*----------------------------------------------------------------------*/ - -static int32 NXIFindSDS(NXhandle fid, CONSTCHAR * name) -{ - pNexusFile self; - int32 iNew, iRet, iTag, iRef; - int32 i, iN, iA, iD1, iD2; - NXname pNam; - int32 iDim[MAX_VAR_DIMS]; - - self = NXIassert(fid); - - /* root level search */ - if (self->iCurrentVG == 0) { - i = SDfileinfo(self->iSID, &iN, &iA); - if (i < 0) { - NXIReportError(NXpData, "ERROR: failure to read file information"); + /* nothing found */ + free (pArray); return NX_EOD; - } - for (i = 0; i < iN; i++) { - iNew = SDselect(self->iSID, i); - SDgetinfo(iNew, pNam, &iA, iDim, &iD1, &iD2); - if (strcmp(pNam, name) == 0) { - iRet = SDidtoref(iNew); - SDendaccess(iNew); - return iRet; - } else { - SDendaccess(iNew); - } - } + } else { /* case in Vgroup */ + iN = Vntagrefs (pFile->iCurrentVG); + for (i = 0; i < iN; i++) { + Vgettagref (pFile->iCurrentVG, i, &iTag, &iRef); + if (iTag == DFTAG_VG) { + iNew = Vattach (pFile->iVID, iRef, "r"); + Vgetname (iNew, pText); + Vdetach(iNew); + if (strcmp (pText, name) == 0) { + iRef = findNapiClass(pFile,iRef, pText); + if (strcmp (pText, nxclass) == 0) { + return iRef; + } + } + } + } /* end for */ + } /* end else */ /* not found */ return NX_EOD; } - /* end root level */ - else { /* search in a Vgroup */ - iN = Vntagrefs(self->iCurrentVG); - for (i = 0; i < iN; i++) { - Vgettagref(self->iCurrentVG, i, &iTag, &iRef); - /* we are now writing using DFTAG_NDG, but need others for backward compatability */ - if ((iTag == DFTAG_SDG) || (iTag == DFTAG_NDG) - || (iTag == DFTAG_SDS)) { - iNew = SDreftoindex(self->iSID, iRef); - iNew = SDselect(self->iSID, iNew); - SDgetinfo(iNew, pNam, &iA, iDim, &iD1, &iD2); - if (strcmp(pNam, name) == 0) { - SDendaccess(iNew); - return iRef; - } - SDendaccess(iNew); - } - } /* end for */ - } /* end Vgroup */ - /* we get here, only if nothing found */ - return NX_EOD; -} + + /*----------------------------------------------------------------------*/ + static int32 NXIFindSDS (NXhandle fid, CONSTCHAR *name) + { + pNexusFile self; + int32 iNew, iRet, iTag, iRef; + int32 i, iN, iA, iD1, iD2; + NXname pNam; + int32 iDim[H4_MAX_VAR_DIMS]; + + self = NXIassert (fid); + + /* root level search */ + if (self->iCurrentVG == 0) { + i = SDfileinfo (self->iSID, &iN, &iA); + if (i < 0) { + NXReportError( "ERROR: failure to read file information"); + return NX_EOD; + } + for (i = 0; i < iN; i++) { + iNew = SDselect (self->iSID, i); + SDgetinfo (iNew, pNam, &iA, iDim, &iD1, &iD2); + if (strcmp (pNam, name) == 0) { + iRet = SDidtoref (iNew); + SDendaccess (iNew); + return iRet; + } else { + SDendaccess (iNew); + } + } + /* not found */ + return NX_EOD; + } + /* end root level */ + else { /* search in a Vgroup */ + iN = Vntagrefs (self->iCurrentVG); + for (i = 0; i < iN; i++) { + Vgettagref (self->iCurrentVG, i, &iTag, &iRef); + /* we are now writing using DFTAG_NDG, but need others for backward compatability */ + if ((iTag == DFTAG_SDG) || (iTag == DFTAG_NDG) || (iTag == DFTAG_SDS)) { + iNew = SDreftoindex (self->iSID, iRef); + iNew = SDselect (self->iSID, iNew); + SDgetinfo (iNew, pNam, &iA, iDim, &iD1, &iD2); + if (strcmp (pNam, name) == 0) { + SDendaccess (iNew); + return iRef; + } + SDendaccess (iNew); + } + } /* end for */ + } /* end Vgroup */ + /* we get here, only if nothing found */ + return NX_EOD; + } + /*----------------------------------------------------------------------*/ -static int NXIInitDir(pNexusFile self) -{ - int i; - int32 iTag, iRef; - int iStackPtr; - + static int NXIInitDir (pNexusFile self) + { + int i; + int32 iTag, iRef; + int iStackPtr; + /* * Note: the +1 to various malloc() operations is to avoid a * malloc(0), which is an error on some operating systems */ - iStackPtr = self->iStackPtr; - if (self->iCurrentVG == 0 && self->iStack[iStackPtr].iRefDir == NULL) { /* root level */ - /* get the number and ID's of all lone Vgroups in the file */ - self->iStack[iStackPtr].iNDir = Vlone(self->iVID, NULL, 0); - self->iStack[iStackPtr].iRefDir = - (int32 *) malloc(self->iStack[iStackPtr].iNDir * sizeof(int32) + - 1); - if (!self->iStack[iStackPtr].iRefDir) { - NXIReportError(NXpData, "ERROR: out of memory in NXIInitDir"); - return NX_EOD; - } - Vlone(self->iVID, - self->iStack[self->iStackPtr].iRefDir, - self->iStack[self->iStackPtr].iNDir); - } else { - /* Vgroup level */ - self->iStack[iStackPtr].iNDir = Vntagrefs(self->iCurrentVG); - self->iStack[iStackPtr].iRefDir = - (int32 *) malloc(self->iStack[iStackPtr].iNDir * sizeof(int32) + - 1); - self->iStack[iStackPtr].iTagDir = - (int32 *) malloc(self->iStack[iStackPtr].iNDir * sizeof(int32) + - 1); - if ((!self->iStack[iStackPtr].iRefDir) - || (!self->iStack[iStackPtr].iTagDir)) { - NXIReportError(NXpData, "ERROR: out of memory in NXIInitDir"); - return NX_EOD; - } - for (i = 0; i < self->iStack[self->iStackPtr].iNDir; i++) { - Vgettagref(self->iCurrentVG, i, &iTag, &iRef); - self->iStack[iStackPtr].iRefDir[i] = iRef; - self->iStack[iStackPtr].iTagDir[i] = iTag; + iStackPtr = self->iStackPtr; + if (self->iCurrentVG == 0 && + self->iStack[iStackPtr].iRefDir == NULL) { /* root level */ + /* get the number and ID's of all lone Vgroups in the file */ + self->iStack[iStackPtr].iNDir = Vlone (self->iVID, NULL, 0); + self->iStack[iStackPtr].iRefDir = + (int32 *) malloc (self->iStack[iStackPtr].iNDir * sizeof (int32) + 1); + if (!self->iStack[iStackPtr].iRefDir) { + NXReportError( "ERROR: out of memory in NXIInitDir"); + return NX_EOD; + } + Vlone (self->iVID, + self->iStack[self->iStackPtr].iRefDir, + self->iStack[self->iStackPtr].iNDir); + } else { + /* Vgroup level */ + self->iStack[iStackPtr].iNDir = Vntagrefs (self->iCurrentVG); + self->iStack[iStackPtr].iRefDir = + (int32 *) malloc (self->iStack[iStackPtr].iNDir * sizeof (int32) + 1); + self->iStack[iStackPtr].iTagDir = + (int32 *) malloc (self->iStack[iStackPtr].iNDir * sizeof (int32) + 1); + if ((!self->iStack[iStackPtr].iRefDir) || + (!self->iStack[iStackPtr].iTagDir)) { + NXReportError( "ERROR: out of memory in NXIInitDir"); + return NX_EOD; + } + for (i = 0; i < self->iStack[self->iStackPtr].iNDir; i++) { + Vgettagref (self->iCurrentVG, i, &iTag, &iRef); + self->iStack[iStackPtr].iRefDir[i] = iRef; + self->iStack[iStackPtr].iTagDir[i] = iTag; + } } + self->iStack[iStackPtr].iCurDir = 0; + return 1; } - self->iStack[iStackPtr].iCurDir = 0; - return 1; -} /*----------------------------------------------------------------------*/ - -static void NXIKillDir(pNexusFile self) -{ - if (self->iStack[self->iStackPtr].iRefDir) { - free(self->iStack[self->iStackPtr].iRefDir); - self->iStack[self->iStackPtr].iRefDir = NULL; + + static void NXIKillDir (pNexusFile self) + { + if (self->iStack[self->iStackPtr].iRefDir) { + free (self->iStack[self->iStackPtr].iRefDir); + self->iStack[self->iStackPtr].iRefDir = NULL; + } + if (self->iStack[self->iStackPtr].iTagDir) { + free (self->iStack[self->iStackPtr].iTagDir); + self->iStack[self->iStackPtr].iTagDir = NULL; + } + self->iStack[self->iStackPtr].iCurDir = 0; + self->iStack[self->iStackPtr].iNDir = 0; } - if (self->iStack[self->iStackPtr].iTagDir) { - free(self->iStack[self->iStackPtr].iTagDir); - self->iStack[self->iStackPtr].iTagDir = NULL; - } - self->iStack[self->iStackPtr].iCurDir = 0; - self->iStack[self->iStackPtr].iNDir = 0; -} - + /*-------------------------------------------------------------------------*/ -static int NXIInitAttDir(pNexusFile pFile) -{ - int iRet; - int32 iData, iAtt, iRank, iType; - int32 iDim[MAX_VAR_DIMS]; - NXname pNam; - - pFile->iAtt.iCurDir = 0; - if (pFile->iCurrentSDS != 0) { /* SDS level */ - iRet = SDgetinfo(pFile->iCurrentSDS, pNam, &iRank, iDim, &iType, - &iAtt); - } else { - if (pFile->iCurrentVG == 0) { - /* global level */ - iRet = SDfileinfo(pFile->iSID, &iData, &iAtt); + static int NXIInitAttDir (pNexusFile pFile) + { + int iRet; + int32 iData, iAtt, iRank, iType; + int32 iDim[H4_MAX_VAR_DIMS]; + NXname pNam; + + pFile->iAtt.iCurDir = 0; + if (pFile->iCurrentSDS != 0) { /* SDS level */ + iRet = SDgetinfo (pFile->iCurrentSDS, pNam, &iRank, iDim, &iType, + &iAtt); } else { - /* group attribute */ - iRet = Vnattrs(pFile->iCurrentVG); - iAtt = iRet; + if(pFile->iCurrentVG == 0){ + /* global level */ + iRet = SDfileinfo (pFile->iSID, &iData, &iAtt); + } else { + /* group attribute */ + iRet = Vnattrs(pFile->iCurrentVG); + iAtt = iRet; + } } + if (iRet < 0) { + NXReportError( "ERROR: HDF cannot read attribute numbers"); + pFile->iAtt.iNDir = 0; + return NX_ERROR; + } + pFile->iAtt.iNDir = iAtt; + return NX_OK; } - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot read attribute numbers"); - pFile->iAtt.iNDir = 0; - return NX_ERROR; - } - pFile->iAtt.iNDir = iAtt; - return NX_OK; -} /* --------------------------------------------------------------------- */ -static void NXIKillAttDir(pNexusFile self) -{ - if (self->iAtt.iRefDir) { - free(self->iAtt.iRefDir); - self->iAtt.iRefDir = NULL; + static void NXIKillAttDir (pNexusFile self) + { + if (self->iAtt.iRefDir) { + free (self->iAtt.iRefDir); + self->iAtt.iRefDir = NULL; + } + if (self->iAtt.iTagDir) { + free (self->iAtt.iTagDir); + self->iAtt.iTagDir = NULL; + } + self->iAtt.iCurDir = 0; + self->iAtt.iNDir = 0; } - if (self->iAtt.iTagDir) { - free(self->iAtt.iTagDir); - self->iAtt.iTagDir = NULL; - } - self->iAtt.iCurDir = 0; - self->iAtt.iNDir = 0; -} - /*------------------------------------------------------------------*/ -static void NXIbuildPath(pNexusFile pFile, char *buffer, int bufLen) -{ - int i; - int32 groupID, iA, iD1, iD2, iDim[MAX_VAR_DIMS]; - NXname pText; - - buffer[0] = '\0'; - for (i = 0; i < pFile->iStackPtr; i++) { - strncat(buffer, "/", bufLen - strlen(buffer)); - groupID = Vattach(pFile->iVID, pFile->iStack[pFile->iStackPtr].iVref, - "r"); - Vgetname(groupID, pText); - strncat(buffer, pText, bufLen - strlen(buffer)); - Vdetach(groupID); - } - if (pFile->iCurrentSDS != 0) { - strncat(buffer, "/", bufLen - strlen(buffer)); - SDgetinfo(pFile->iCurrentSDS, pText, &iA, iDim, &iD1, &iD2); - strncat(buffer, pText, bufLen - strlen(buffer)); - } -} + static void NXIbuildPath(pNexusFile pFile, char *buffer, int bufLen) + { + int i; + int32 groupID, iA, iD1, iD2, iDim[H4_MAX_VAR_DIMS]; + NXname pText; + buffer[0] = '\0'; + for(i = 1; i <= pFile->iStackPtr; i++){ + strncat(buffer,"/",bufLen-strlen(buffer)); + groupID = Vattach(pFile->iVID,pFile->iStack[i].iVref, "r"); + if (groupID != -1) + { + if (Vgetname(groupID, pText) != -1) { + strncat(buffer,pText,bufLen-strlen(buffer)); + } else { + NXReportError( "ERROR: NXIbuildPath cannot get vgroup name"); + } + Vdetach(groupID); + } + else + { + NXReportError( "ERROR: NXIbuildPath cannot attach to vgroup"); + } + } + if(pFile->iCurrentSDS != 0){ + if (SDgetinfo(pFile->iCurrentSDS,pText,&iA,iDim,&iD1,&iD2) != -1) { + strncat(buffer,"/",bufLen-strlen(buffer)); + strncat(buffer,pText,bufLen-strlen(buffer)); + } + else + { + NXReportError( "ERROR: NXIbuildPath cannot read SDS"); + } + } + } /* ---------------------------------------------------------------------- + + Definition of NeXus API - Definition of NeXus API - - --------------------------------------------------------------------- */ + ---------------------------------------------------------------------*/ -NXstatus NX4open(CONSTCHAR * filename, NXaccess am, NXhandle * pHandle) -{ - pNexusFile pNew = NULL; - char pBuffer[512]; - char *time_puffer = NULL; - char HDF_VERSION[64]; - uint32 lmajor, lminor, lrelease; - int32 am1 = 0; - int32 file_id = 0, an_id = 0, ann_id = 0; + NXstatus NX4open(CONSTCHAR *filename, NXaccess am, + NXhandle* pHandle) + { + pNexusFile pNew = NULL; + char pBuffer[512]; + char *time_puffer = NULL; + char HDF_VERSION[64]; + uint32 lmajor, lminor, lrelease; + int32 am1=0; + + *pHandle = NULL; - *pHandle = NULL; - /* map Nexus NXaccess types to HDF4 types */ - if (am == NXACC_CREATE) { - am1 = DFACC_CREATE; - } else if (am == NXACC_CREATE4) { - am1 = DFACC_CREATE; - } else if (am == NXACC_READ) { - am1 = DFACC_READ; - } else if (am == NXACC_RDWR) { - am1 = DFACC_RDWR; - } - /* get memory */ - pNew = (pNexusFile) malloc(sizeof(NexusFile)); - if (!pNew) { - NXIReportError(NXpData, - "ERROR: no memory to create File datastructure"); - return NX_ERROR; - } - memset(pNew, 0, sizeof(NexusFile)); + /* mask off any options for now */ + am = (NXaccess)(am & NXACCMASK_REMOVEFLAGS); + /* map Nexus NXaccess types to HDF4 types */ + if (am == NXACC_CREATE) { + am1 = DFACC_CREATE; + } else if (am == NXACC_CREATE4) { + am1 = DFACC_CREATE; + } else if (am == NXACC_READ) { + am1 = DFACC_READ; + } else if (am == NXACC_RDWR) { + am1 = DFACC_RDWR; + } + /* get memory */ + pNew = (pNexusFile) malloc (sizeof (NexusFile)); + if (!pNew) { + NXReportError( "ERROR: no memory to create File datastructure"); + return NX_ERROR; + } + memset (pNew, 0, sizeof (NexusFile)); -#if WRITE_OLD_IDENT /* not used at moment */ +#if WRITE_OLD_IDENT /* not used at moment */ /* * write something that can be used by OLE */ + + if (am == NXACC_CREATE || am == NXACC_CREATE4) { + if ( (file_id = Hopen(filename, am1, 0)) == -1 ) { + sprintf (pBuffer, "ERROR: cannot open file_a: %s", filename); + NXReportError( pBuffer); + free (pNew); + return NX_ERROR; + } + an_id = ANstart(file_id); + ann_id = ANcreatef(an_id, AN_FILE_LABEL); /* AN_FILE_DESC */ + ANwriteann(ann_id, "NeXus", 5); + ANendaccess(ann_id); + ANend(an_id); + if (Hclose(file_id) == -1) { + sprintf (pBuffer, "ERROR: cannot close file: %s", filename); + NXReportError( pBuffer); + free (pNew); + return NX_ERROR; + } + am = NXACC_RDWR; + } +#endif /* WRITE_OLD_IDENT */ - if (am == NXACC_CREATE || am == NXACC_CREATE4) { - if ((file_id = Hopen(filename, am1, 0)) == -1) { - sprintf(pBuffer, "ERROR: cannot open file_a: %s", filename); - NXIReportError(NXpData, pBuffer); - free(pNew); + /* start SDS interface */ + pNew->iSID = SDstart (filename, am1); + if (pNew->iSID <= 0) { + sprintf (pBuffer, "ERROR: cannot open file_b: %s", filename); + NXReportError( pBuffer); + free (pNew); return NX_ERROR; } - an_id = ANstart(file_id); - ann_id = ANcreatef(an_id, AN_FILE_LABEL); /* AN_FILE_DESC */ - ANwriteann(ann_id, "NeXus", 5); - ANendaccess(ann_id); - ANend(an_id); - if (Hclose(file_id) == -1) { - sprintf(pBuffer, "ERROR: cannot close file: %s", filename); - NXIReportError(NXpData, pBuffer); - free(pNew); - return NX_ERROR; - } - am = NXACC_RDWR; - } -#endif /* WRITE_OLD_IDENT */ - - /* start SDS interface */ - pNew->iSID = SDstart(filename, am1); - if (pNew->iSID <= 0) { - sprintf(pBuffer, "ERROR: cannot open file_b: %s", filename); - NXIReportError(NXpData, pBuffer); - free(pNew); - return NX_ERROR; - } /* * need to create global attributes file_name file_time NeXus_version * at some point for new files */ - if (am != NXACC_READ) { - if (SDsetattr - (pNew->iSID, "NeXus_version", DFNT_CHAR8, strlen(NEXUS_VERSION), - NEXUS_VERSION) < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store NeXus_version attribute "); - return NX_ERROR; - } - Hgetlibversion(&lmajor, &lminor, &lrelease, HDF_VERSION); - if (SDsetattr - (pNew->iSID, "HDF_version", DFNT_CHAR8, strlen(HDF_VERSION), - HDF_VERSION) < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store HDF_version attribute "); - return NX_ERROR; - } - } - - time_puffer = NXIformatNeXusTime(); - if (am == NXACC_CREATE || am == NXACC_CREATE4) { - if (SDsetattr - (pNew->iSID, "file_name", DFNT_CHAR8, strlen(filename), - (char *) filename) < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store file_name attribute "); - return NX_ERROR; - } - if (time_puffer != NULL) { - if (SDsetattr(pNew->iSID, "file_time", DFNT_CHAR8, - strlen(time_puffer), time_puffer) < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store file_time attribute "); - free(time_puffer); - return NX_ERROR; + if (am != NXACC_READ) { + if (SDsetattr(pNew->iSID, "NeXus_version", DFNT_CHAR8, strlen(NEXUS_VERSION), NEXUS_VERSION) < 0) { + NXReportError( "ERROR: HDF failed to store NeXus_version attribute "); + return NX_ERROR; + } + Hgetlibversion(&lmajor, &lminor, &lrelease, HDF_VERSION); + if (SDsetattr(pNew->iSID, "HDF_version", DFNT_CHAR8, strlen(HDF_VERSION), HDF_VERSION) < 0) { + NXReportError( "ERROR: HDF failed to store HDF_version attribute "); + return NX_ERROR; } } - } - if (time_puffer != NULL) { - free(time_puffer); - } - /* - * Otherwise we try to create the file two times which makes HDF - * Throw up on us. - */ - if (am == NXACC_CREATE || am == NXACC_CREATE4) { - am = NXACC_RDWR; - am1 = DFACC_RDWR; + time_puffer = NXIformatNeXusTime(); + if (am == NXACC_CREATE || am == NXACC_CREATE4) { + if (SDsetattr(pNew->iSID, "file_name", DFNT_CHAR8, strlen(filename), (char*)filename) < 0) { + NXReportError( "ERROR: HDF failed to store file_name attribute "); + return NX_ERROR; + } + if(time_puffer != NULL){ + if (SDsetattr(pNew->iSID, "file_time", DFNT_CHAR8, + strlen(time_puffer), time_puffer) < 0) { + NXReportError( + "ERROR: HDF failed to store file_time attribute "); + free(time_puffer); + return NX_ERROR; + } + } + } + if (time_puffer != NULL) { + free(time_puffer); + } + + /* + * Otherwise we try to create the file two times which makes HDF + * Throw up on us. + */ + if (am == NXACC_CREATE || am == NXACC_CREATE4) { + am = NXACC_RDWR; + am1 = DFACC_RDWR; + } + + /* Set Vgroup access mode */ + if (am == NXACC_READ) { + strcpy(pNew->iAccess,"r"); + } else { + strcpy(pNew->iAccess,"w"); + } + + /* start Vgroup API */ + + pNew->iVID = Hopen(filename, am1, 100); + if (pNew->iVID <= 0) { + sprintf (pBuffer, "ERROR: cannot open file_c: %s", filename); + NXReportError( pBuffer); + free (pNew); + return NX_ERROR; + } + Vstart (pNew->iVID); + pNew->iNXID = NXSIGNATURE; + pNew->iStack[0].iVref = 0; /* root! */ + + *pHandle = (NXhandle)pNew; + return NX_OK; } - /* Set Vgroup access mode */ - if (am == NXACC_READ) { - strcpy(pNew->iAccess, "r"); - } else { - strcpy(pNew->iAccess, "w"); - } - - /* start Vgroup API */ - - pNew->iVID = Hopen(filename, am1, 100); - if (pNew->iVID <= 0) { - sprintf(pBuffer, "ERROR: cannot open file_c: %s", filename); - NXIReportError(NXpData, pBuffer); - free(pNew); - return NX_ERROR; - } - Vstart(pNew->iVID); - pNew->iNXID = NXSIGNATURE; - pNew->iStack[0].iVref = 0; /* root! */ - - *pHandle = (NXhandle) pNew; - return NX_OK; -} - /*-----------------------------------------------------------------------*/ - -NXstatus NX4close(NXhandle * fid) -{ - pNexusFile pFile = NULL; - int iRet; - - pFile = NXIassert(*fid); - iRet = 0; - /* close links into vGroups or SDS */ - if (pFile->iCurrentVG != 0) { - Vdetach(pFile->iCurrentVG); - } - if (pFile->iCurrentSDS != 0) { - iRet = SDendaccess(pFile->iCurrentSDS); - } - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: ending access to SDS"); - } - /* close the SDS and Vgroup API's */ - Vend(pFile->iVID); - iRet = SDend(pFile->iSID); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot close SDS interface"); - } - iRet = Hclose(pFile->iVID); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot close HDF file"); - } - /* release memory */ - NXIKillDir(pFile); - free(pFile); - *fid = NULL; - return NX_OK; -} + + NXstatus NX4close (NXhandle* fid) + { + pNexusFile pFile = NULL; + int iRet; + + pFile = NXIassert(*fid); + iRet = 0; + /* close links into vGroups or SDS */ + if (pFile->iCurrentVG != 0) { + Vdetach (pFile->iCurrentVG); + } + if (pFile->iCurrentSDS != 0) { + iRet = SDendaccess (pFile->iCurrentSDS); + } + if (iRet < 0) { + NXReportError( "ERROR: ending access to SDS"); + } + /* close the SDS and Vgroup API's */ + Vend (pFile->iVID); + iRet = SDend (pFile->iSID); + if (iRet < 0) { + NXReportError( "ERROR: HDF cannot close SDS interface"); + } + iRet = Hclose (pFile->iVID); + if (iRet < 0) { + NXReportError( "ERROR: HDF cannot close HDF file"); + } + /* release memory */ + NXIKillDir (pFile); + free (pFile); + *fid = NULL; + return NX_OK; + } -/*-----------------------------------------------------------------------*/ +/*-----------------------------------------------------------------------*/ - -NXstatus NX4makegroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass) -{ - pNexusFile pFile; - int32 iNew, iRet; - char pBuffer[256]; - - pFile = NXIassert(fid); - /* - * Make sure that a group with the same name and nxclass does not - * already exist. - */ - if ((iRet = NXIFindVgroup(pFile, (char *) name, nxclass)) >= 0) { - sprintf(pBuffer, "ERROR: Vgroup %s, class %s already exists", - name, nxclass); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; + + NXstatus NX4makegroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) + { + pNexusFile pFile; + int32 iNew, iRet; + char pBuffer[256]; + + pFile = NXIassert (fid); + /* + * Make sure that a group with the same name and nxclass does not + * already exist. + */ + if ((iRet = NXIFindVgroup (pFile, (char*)name, nxclass)) >= 0) { + sprintf (pBuffer, "ERROR: Vgroup %s, class %s already exists", + name, nxclass); + NXReportError( pBuffer); + return NX_ERROR; + } + + /* create and configure the group */ + iNew = Vattach (pFile->iVID, -1, "w"); + if (iNew < 0) { + NXReportError( "ERROR: HDF could not create Vgroup"); + return NX_ERROR; + } + Vsetname (iNew, name); + Vsetclass (iNew, nxclass); + + /* Insert it into the hierarchy, when appropriate */ + iRet = 0; + if (pFile->iCurrentVG != 0) { + iRet = Vinsert (pFile->iCurrentVG, iNew); + } + Vdetach (iNew); + if (iRet < 0) { + NXReportError( "ERROR: HDF failed to insert Vgroup"); + return NX_ERROR; + } + return NX_OK; } - /* create and configure the group */ - iNew = Vattach(pFile->iVID, -1, "w"); - if (iNew < 0) { - NXIReportError(NXpData, "ERROR: HDF could not create Vgroup"); - return NX_ERROR; - } - Vsetname(iNew, name); - Vsetclass(iNew, nxclass); - - /* Insert it into the hierarchy, when appropriate */ - iRet = 0; - if (pFile->iCurrentVG != 0) { - iRet = Vinsert(pFile->iCurrentVG, iNew); - } - Vdetach(iNew); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF failed to insert Vgroup"); - return NX_ERROR; - } - return NX_OK; -} - /*------------------------------------------------------------------------*/ -NXstatus NX4opengroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass) -{ - pNexusFile pFile; - int32 iRef; - char pBuffer[256]; - - pFile = NXIassert(fid); - - iRef = NXIFindVgroup(pFile, (char *) name, nxclass); - if (iRef < 0) { - sprintf(pBuffer, "ERROR: Vgroup %s, class %s NOT found", name, - nxclass); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; + NXstatus NX4opengroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) + { + pNexusFile pFile; + int32 iRef; + char pBuffer[256]; + + pFile = NXIassert (fid); + + iRef = NXIFindVgroup (pFile, (char*)name, nxclass); + if (iRef < 0) { + sprintf (pBuffer, "ERROR: Vgroup \"%s\", class \"%s\" NOT found", name, nxclass); + NXReportError( pBuffer); + return NX_ERROR; + } + /* are we at root level ? */ + if (pFile->iCurrentVG == 0) { + pFile->iCurrentVG = Vattach (pFile->iVID, iRef,pFile->iAccess); + pFile->iStackPtr++; + pFile->iStack[pFile->iStackPtr].iVref = iRef; + } else { + Vdetach (pFile->iCurrentVG); + pFile->iStackPtr++; + pFile->iStack[pFile->iStackPtr].iVref = iRef; + pFile->iCurrentVG = Vattach (pFile->iVID, + pFile->iStack[pFile->iStackPtr].iVref, + pFile->iAccess); + } + NXIKillDir (pFile); + return NX_OK; } - /* are we at root level ? */ - if (pFile->iCurrentVG == 0) { - pFile->iCurrentVG = Vattach(pFile->iVID, iRef, pFile->iAccess); - pFile->iStackPtr++; - pFile->iStack[pFile->iStackPtr].iVref = iRef; - } else { - Vdetach(pFile->iCurrentVG); - pFile->iStackPtr++; - pFile->iStack[pFile->iStackPtr].iVref = iRef; - pFile->iCurrentVG = Vattach(pFile->iVID, - pFile->iStack[pFile->iStackPtr].iVref, - pFile->iAccess); + /* ------------------------------------------------------------------- */ + + + NXstatus NX4closegroup (NXhandle fid) + { + pNexusFile pFile; + + pFile = NXIassert (fid); + + /* first catch the trivial case: we are at root and cannot get + deeper into a negative directory hierarchy (anti-directory) + */ + if (pFile->iCurrentVG == 0) { + NXIKillDir (pFile); + return NX_OK; + } else { /* Sighhh. Some work to do */ + /* close the current VG and decrement stack */ + Vdetach (pFile->iCurrentVG); + NXIKillDir (pFile); + pFile->iStackPtr--; + if (pFile->iStackPtr <= 0) { /* we hit root */ + pFile->iStackPtr = 0; + pFile->iCurrentVG = 0; + } else { + /* attach to the lower Vgroup */ + pFile->iCurrentVG = Vattach (pFile->iVID, + pFile->iStack[pFile->iStackPtr].iVref, + pFile->iAccess); + } + } + return NX_OK; } - NXIKillDir(pFile); - return NX_OK; -} + + + /* --------------------------------------------------------------------- */ + + NXstatus NX4makedata64 (NXhandle fid, CONSTCHAR *name, int datatype, int rank, + int64_t dimensions[]) + { + pNexusFile pFile; + int32 iNew; + char pBuffer[256]; + int i, iRet, type; + int32 myDim[H4_MAX_VAR_DIMS]; + + pFile = NXIassert (fid); + + if (dimensions[0] == NX_UNLIMITED) + { + dimensions[0] = SD_UNLIMITED; + } + + if ((iNew = NXIFindSDS (fid, name))>=0) { + sprintf (pBuffer, "ERROR: SDS %s already exists at this level", name); + NXReportError( pBuffer); + return NX_ERROR; + } + + if (datatype == NX_CHAR) + { + type=DFNT_CHAR8; + } + else if (datatype == NX_INT8) + { + type=DFNT_INT8; + } + else if (datatype == NX_UINT8) + { + type=DFNT_UINT8; + } + else if (datatype == NX_INT16) + { + type=DFNT_INT16; + } + else if (datatype == NX_UINT16) + { + type=DFNT_UINT16; + } + else if (datatype == NX_INT32) + { + type=DFNT_INT32; + } + else if (datatype == NX_UINT32) + { + type=DFNT_UINT32; + } + else if (datatype == NX_FLOAT32) + { + type=DFNT_FLOAT32; + } + else if (datatype == NX_FLOAT64) + { + type=DFNT_FLOAT64; + } + else + { + NXReportError( "ERROR: invalid type in NX4makedata"); + return NX_ERROR; + } + + if (rank <= 0) { + sprintf (pBuffer, "ERROR: invalid rank specified for SDS %s", + name); + NXReportError( pBuffer); + return NX_ERROR; + } + + /* + Check dimensions for consistency. The first dimension may be 0 + thus denoting an unlimited dimension. + */ + for (i = 1; i < rank; i++) { + if (dimensions[i] <= 0) { + sprintf (pBuffer, + "ERROR: invalid dimension %d, value %lld given for SDS %s", + i, (long long)dimensions[i], name); + NXReportError( pBuffer); + return NX_ERROR; + } + } + + /* cast the dimensions array properly for non 32-bit ints */ + for(i = 0; i < rank; i++) + { + myDim[i] = (int32)dimensions[i]; + } + + + /* behave nicely, if there is still an SDS open */ + if (pFile->iCurrentSDS != 0) { + SDendaccess (pFile->iCurrentSDS); + pFile->iCurrentSDS = 0; + } + + /* Do not allow creation of SDS's at the root level */ + if (pFile->iCurrentVG == 0) { + sprintf(pBuffer, "ERROR: SDS creation at root level is not permitted"); + NXReportError( pBuffer); + return NX_ERROR; + } + + /* dataset creation */ + iNew = SDcreate (pFile->iSID, (char*)name, (int32)type, + (int32)rank, myDim); + if (iNew < 0) { + sprintf (pBuffer, "ERROR: cannot create SDS %s, check arguments", + name); + NXReportError( pBuffer); + return NX_ERROR; + } + /* link into Vgroup, if in one */ + if (pFile->iCurrentVG != 0) { + iRet = Vaddtagref (pFile->iCurrentVG, DFTAG_NDG, SDidtoref (iNew)); + } + iRet = SDendaccess (iNew); + if (iRet < 0) { + NXReportError( "ERROR: HDF cannot end access to SDS"); + return NX_ERROR; + } + return NX_OK; + } + + + /* --------------------------------------------------------------------- */ + + + NXstatus NX4compmakedata64 (NXhandle fid, CONSTCHAR *name, int datatype, int rank, + int64_t dimensions[],int compress_type, int64_t chunk_size[]) + { + pNexusFile pFile; + int32 iNew, iRet, type; + char pBuffer[256]; + int i, compress_level; + int32 myDim[H4_MAX_VAR_DIMS]; + comp_info compstruct; + + pFile = NXIassert (fid); + + if (dimensions[0] == NX_UNLIMITED) + { + dimensions[0] = SD_UNLIMITED; + } + + if ((iNew = NXIFindSDS (fid, name))>=0) { + sprintf (pBuffer, "ERROR: SDS %s already exists at this level", name); + NXReportError( pBuffer); + return NX_ERROR; + } + + if (datatype == NX_CHAR) + { + type=DFNT_CHAR8; + } + else if (datatype == NX_INT8) + { + type=DFNT_INT8; + } + else if (datatype == NX_UINT8) + { + type=DFNT_UINT8; + } + else if (datatype == NX_INT16) + { + type=DFNT_INT16; + } + else if (datatype == NX_UINT16) + { + type=DFNT_UINT16; + } + else if (datatype == NX_INT32) + { + type=DFNT_INT32; + } + else if (datatype == NX_UINT32) + { + type=DFNT_UINT32; + } + else if (datatype == NX_FLOAT32) + { + type=DFNT_FLOAT32; + } + else if (datatype == NX_FLOAT64) + { + type=DFNT_FLOAT64; + } + else + { + NXReportError( "ERROR: invalid datatype in NX4compmakedata"); + return NX_ERROR; + } + + if (rank <= 0) { + sprintf (pBuffer, "ERROR: invalid rank specified for SDS %s", + name); + NXReportError( pBuffer); + return NX_ERROR; + } + + /* + Check dimensions for consistency. The first dimension may be 0 + thus denoting an unlimited dimension. + */ + for (i = 1; i < rank; i++) { + if (dimensions[i] <= 0) { + sprintf (pBuffer, + "ERROR: invalid dimension %d, value %lld given for SDS %s", + i, (long long)dimensions[i], name); + NXReportError( pBuffer); + return NX_ERROR; + } + } + + /* cast the dimensions array properly for non 32-bit ints */ + for(i = 0; i < rank; i++) + { + myDim[i] = (int32)dimensions[i]; + } + + + /* behave nicely, if there is still an SDS open */ + if (pFile->iCurrentSDS != 0) { + SDendaccess (pFile->iCurrentSDS); + pFile->iCurrentSDS = 0; + } + + /* Do not allow creation of SDS's at the root level */ + if (pFile->iCurrentVG == 0) { + sprintf(pBuffer, "ERROR: SDS creation at root level is not permitted"); + NXReportError( pBuffer); + return NX_ERROR; + } + + /* dataset creation */ + iNew = SDcreate (pFile->iSID, (char*)name, (int32)type, + (int32)rank, myDim); + if (iNew < 0) { + sprintf (pBuffer, "ERROR: cannot create SDS %s, check arguments", + name); + NXReportError( pBuffer); + return NX_ERROR; + } + + /* compress SD data set */ + compress_level = 6; + if( (compress_type / 100) == NX_COMP_LZW ) + { + compress_level = compress_type % 100; + compress_type = NX_COMP_LZW; + } + + if(compress_type == NX_COMP_LZW) + { + compstruct.deflate.level = compress_level; + iRet = SDsetcompress(iNew, COMP_CODE_DEFLATE, &compstruct); + if (iRet < 0) + { + NXReportError( "LZW-Compression failure!"); + return NX_ERROR; + } + } + else if (compress_type == NX_COMP_RLE) + { + iRet = SDsetcompress(iNew, COMP_CODE_RLE, &compstruct); + if (iRet < 0) + { + NXReportError( "RLE-Compression failure!"); + return NX_ERROR; + } + } + else if (compress_type == NX_COMP_HUF) + { + compstruct.skphuff.skp_size = DFKNTsize(type); + iRet = SDsetcompress(iNew, COMP_CODE_SKPHUFF, &compstruct); + if (iRet < 0) + { + NXReportError( "HUF-Compression failure!"); + return NX_ERROR; + } + } + else if (compress_type == NX_COMP_NONE) + { + /* */ + } + else + { + NXReportError( "Unknown compression method!"); + return NX_ERROR; + } + /* link into Vgroup, if in one */ + if (pFile->iCurrentVG != 0) { + iRet = Vaddtagref (pFile->iCurrentVG, DFTAG_NDG, SDidtoref (iNew)); + } + iRet = SDendaccess (iNew); + if (iRet < 0) { + NXReportError( "ERROR: HDF cannot end access to SDS"); + return NX_ERROR; + } + + return NX_OK; + } + + /* --------------------------------------------------------------------- */ + + + NXstatus NX4compress (NXhandle fid, int compress_type) + { + pNexusFile pFile; + int32 iRank, iAtt, iType, iRet; + int32 iSize[H4_MAX_VAR_DIMS]; + comp_coder_t compress_typei = COMP_CODE_NONE; + NXname pBuffer; + char pError[512]; + comp_info compstruct; + int compress_level = 6; + + pFile = NXIassert (fid); + + /* check if there is an SDS open */ + if (pFile->iCurrentSDS == 0) { + NXReportError( "ERROR: no SDS open"); + return NX_ERROR; + } + + if (compress_type == NX_COMP_NONE) + { + compress_typei = COMP_CODE_NONE; + } + else if (compress_type == NX_COMP_LZW) + { + compress_typei = COMP_CODE_DEFLATE; + } + else if ( (compress_type / 100) == NX_COMP_LZW ) + { + compress_typei = COMP_CODE_DEFLATE; + compress_level = compress_type % 100; + compress_type = NX_COMP_LZW; + } + else if (compress_type == NX_COMP_RLE) + { + compress_typei = COMP_CODE_RLE; + } + else if + (compress_type == NX_COMP_HUF) + { + compress_typei = COMP_CODE_SKPHUFF; + } + + /* first read dimension information */ + SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); + + /* + according to compression type initialize compression + information + */ + if(compress_type == NX_COMP_LZW) + { + compstruct.deflate.level = compress_level; + } + else if(compress_type == NX_COMP_HUF) + { + compstruct.skphuff.skp_size = DFKNTsize(iType); + } + + iRet = SDsetcompress(pFile->iCurrentSDS, compress_typei, &compstruct); + if (iRet < 0) { + sprintf (pError, "ERROR: failure to compress data to %s", pBuffer); + NXReportError( pError); + return NX_ERROR; + } + return NX_OK; + } + + /* --------------------------------------------------------------------- */ + + + NXstatus NX4opendata (NXhandle fid, CONSTCHAR *name) + { + pNexusFile pFile; + int32 iNew, attID, tags[2]; + char pBuffer[256]; + int iRet; + + pFile = NXIassert (fid); + + /* First find the reference number of the SDS */ + iNew = NXIFindSDS (fid, name); + if (iNew < 0) { + sprintf (pBuffer, "ERROR: SDS \"%s\" not found at this level", name); + NXReportError( pBuffer); + return NX_ERROR; + } + /* Be nice: properly close the old open SDS silently if there is + * still an SDS open. + */ + if (pFile->iCurrentSDS) { + iRet = SDendaccess (pFile->iCurrentSDS); + if (iRet < 0) { + NXReportError( "ERROR: HDF cannot end access to SDS"); + } + } + /* clear pending attribute directories first */ + NXIKillAttDir (pFile); + + /* open the SDS, thereby watching for linked SDS under a different name */ + iNew = SDreftoindex (pFile->iSID, iNew); + pFile->iCurrentSDS = SDselect (pFile->iSID, iNew); + attID = SDfindattr(pFile->iCurrentSDS,"NAPIlink"); + if(attID >= 0) + { + SDreadattr(pFile->iCurrentSDS,attID, tags); + SDendaccess(pFile->iCurrentSDS); + iNew = SDreftoindex (pFile->iSID, tags[1]); + pFile->iCurrentSDS = SDselect (pFile->iSID, iNew); + } + + if (pFile->iCurrentSDS < 0) { + NXReportError( "ERROR: HDF error opening SDS"); + pFile->iCurrentSDS = 0; + return NX_ERROR; + } + return NX_OK; + } + + /* ----------------------------------------------------------------- */ + + + NXstatus NX4closedata (NXhandle fid) + { + pNexusFile pFile; + int iRet; + + pFile = NXIassert (fid); + + if (pFile->iCurrentSDS != 0) { + iRet = SDendaccess (pFile->iCurrentSDS); + pFile->iCurrentSDS = 0; + if (iRet < 0) { + NXReportError( "ERROR: HDF cannot end access to SDS"); + return NX_ERROR; + } + } else { + NXReportError( "ERROR: no SDS open --> nothing to do"); + return NX_ERROR; + } + NXIKillAttDir (pFile); /* for attribute data */ + return NX_OK; + } + + + /* ------------------------------------------------------------------- */ + + NXstatus NX4putdata (NXhandle fid, const void *data) + { + pNexusFile pFile; + int32 iStart[H4_MAX_VAR_DIMS], iSize[H4_MAX_VAR_DIMS], iStride[H4_MAX_VAR_DIMS]; + NXname pBuffer; + int32 iRank, iAtt, iType, iRet, i; + char pError[512]; + + pFile = NXIassert (fid); + + /* check if there is an SDS open */ + if (pFile->iCurrentSDS == 0) { + NXReportError( "ERROR: no SDS open"); + return NX_ERROR; + } + /* first read dimension information */ + memset (iStart, 0, H4_MAX_VAR_DIMS * sizeof (int32)); + SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); + + /* initialise stride to 1 */ + for (i = 0; i < iRank; i++) { + iStride[i] = 1; + } + + /* actually write */ + iRet = SDwritedata (pFile->iCurrentSDS, iStart, iStride, iSize, (void*)data); + if (iRet < 0) { + /* HEprint(stdout,0); */ + sprintf (pError, "ERROR: failure to write data to %s", pBuffer); + NXReportError( pError); + return NX_ERROR; + } + return NX_OK; + } + + /* ------------------------------------------------------------------- */ + + NXstatus + NX4putattr (NXhandle fid, CONSTCHAR *name, const void *data, int datalen, int iType) + { + pNexusFile pFile; + int iRet, type; + + pFile = NXIassert (fid); + if (iType == NX_CHAR) + { + type=DFNT_CHAR8; + } + else if (iType == NX_INT8) + { + type=DFNT_INT8; + } + else if (iType == NX_UINT8) + { + type=DFNT_UINT8; + } + else if (iType == NX_INT16) + { + type=DFNT_INT16; + } + else if (iType == NX_UINT16) + { + type=DFNT_UINT16; + } + else if (iType == NX_INT32) + { + type=DFNT_INT32; + } + else if (iType == NX_UINT32) + { + type=DFNT_UINT32; + } + else if (iType == NX_FLOAT32) + { + type=DFNT_FLOAT32; + } + else if (iType == NX_FLOAT64) + { + type=DFNT_FLOAT64; + } + else + { + NXReportError( "ERROR: Invalid data type for HDF attribute"); + return NX_ERROR; + } + if (pFile->iCurrentSDS != 0) { + /* SDS attribute */ + iRet = SDsetattr (pFile->iCurrentSDS, (char*)name, (int32)type, + (int32)datalen, data); + } else { + if(pFile->iCurrentVG == 0){ + /* global attribute */ + iRet = SDsetattr (pFile->iSID, (char*)name, (int32)type, + (int32)datalen, data); + } else { + /* group attribute */ + iRet = Vsetattr(pFile->iCurrentVG, (char *)name, (int32) type, + (int32)datalen,data); + } + } + iType = type; + if (iRet < 0) { + NXReportError( "ERROR: HDF failed to store attribute "); + return NX_ERROR; + } + return NX_OK; + } + + /* ------------------------------------------------------------------- */ + + + NXstatus NX4putslab64 (NXhandle fid, const void *data, const int64_t iStart[], const int64_t iSize[]) + { + pNexusFile pFile; + int iRet; + int32 iStride[H4_MAX_VAR_DIMS]; + int32 myStart[H4_MAX_VAR_DIMS], mySize[H4_MAX_VAR_DIMS]; + int32 i, iRank, iType, iAtt; + NXname pBuffer; + + + pFile = NXIassert (fid); + + /* check if there is an SDS open */ + if (pFile->iCurrentSDS == 0) { + NXReportError( "ERROR: no SDS open"); + return NX_ERROR; + } + /* initialise stride to 1 */ + for (i = 0; i < H4_MAX_VAR_DIMS; i++) { + iStride[i] = 1; + } + + SDgetinfo (pFile->iCurrentSDS, pBuffer, + &iRank, myStart, &iType, &iAtt); + for(i = 0; i < iRank; i++) + { + myStart[i] = (int32)iStart[i]; + mySize[i] = (int32)iSize[i]; + } + /* finally write */ + iRet = SDwritedata (pFile->iCurrentSDS, myStart, + iStride, mySize, (void*)data); + + + /* deal with HDF errors */ + if (iRet < 0) { + NXReportError( "ERROR: writing slab failed"); + return NX_ERROR; + } + return NX_OK; + } + + + /* ------------------------------------------------------------------- */ + + NXstatus NX4getdataID (NXhandle fid, NXlink* sRes) + { + pNexusFile pFile; + int datalen, type = NX_CHAR; + + pFile = NXIassert (fid); + + if (pFile->iCurrentSDS == 0) { + sRes->iTag = NX_ERROR; + return NX_ERROR; + } else { + sRes->iTag = DFTAG_NDG; + sRes->iRef = SDidtoref (pFile->iCurrentSDS); + NXMDisableErrorReporting(); + datalen = 1024; + memset(&sRes->targetPath,0,1024); + if(NX4getattr(fid,"target",&sRes->targetPath,&datalen,&type) != NX_OK) + { + NXIbuildPath(pFile,sRes->targetPath,1024); + } + NXMEnableErrorReporting(); + return NX_OK; + } + sRes->iTag = NX_ERROR; + return NX_ERROR; /* not reached */ + } + /* ------------------------------------------------------------------- */ - -NXstatus NX4closegroup(NXhandle fid) -{ - pNexusFile pFile; - - pFile = NXIassert(fid); - - /* first catch the trivial case: we are at root and cannot get - deeper into a negative directory hierarchy (anti-directory) - */ - if (pFile->iCurrentVG == 0) { - NXIKillDir(pFile); + + NXstatus NX4makelink (NXhandle fid, NXlink* sLink) + { + pNexusFile pFile; + int32 dataID, type = DFNT_CHAR8, length; + char name[] = "target"; + + pFile = NXIassert (fid); + + if (pFile->iCurrentVG == 0) { /* root level, can not link here */ + return NX_ERROR; + } + Vaddtagref(pFile->iCurrentVG, sLink->iTag, sLink->iRef); + length = strlen(sLink->targetPath); + if(sLink->iTag == DFTAG_SDG || sLink->iTag == DFTAG_NDG || + sLink->iTag == DFTAG_SDS) + { + dataID = SDreftoindex(pFile->iSID,sLink->iRef); + dataID = SDselect(pFile->iSID,dataID); + SDsetattr(dataID,name,type,length,sLink->targetPath); + SDendaccess(dataID); + } + else + { + dataID = Vattach(pFile->iVID,sLink->iRef,"w"); + Vsetattr(dataID, (char *)name, type, (int32) length, sLink->targetPath); + Vdetach(dataID); + } return NX_OK; - } else { /* Sighhh. Some work to do */ - /* close the current VG and decrement stack */ - Vdetach(pFile->iCurrentVG); - NXIKillDir(pFile); - pFile->iStackPtr--; - if (pFile->iStackPtr <= 0) { /* we hit root */ - pFile->iStackPtr = 0; - pFile->iCurrentVG = 0; + } + /* ------------------------------------------------------------------- */ + + + NXstatus NX4makenamedlink (NXhandle fid, CONSTCHAR* newname, NXlink* sLink) + { + pNexusFile pFile; + int32 dataID, type = DFNT_CHAR8, length, dataType = NX_CHAR, + rank = 1, attType = NX_INT32; + int64_t iDim[1]; + char name[] = "target"; + int tags[2]; + + pFile = NXIassert (fid); + + if (pFile->iCurrentVG == 0) { /* root level, can not link here */ + return NX_ERROR; + } + + tags[0] = sLink->iTag; + tags[1] = sLink->iRef; + + length = strlen(sLink->targetPath); + if(sLink->iTag == DFTAG_SDG || sLink->iTag == DFTAG_NDG || + sLink->iTag == DFTAG_SDS) + { + iDim[0] = 1; + NX4makedata64(fid,newname, dataType,rank,iDim); + NX4opendata(fid,newname); + NX4putattr(fid,"NAPIlink",tags, 2, attType); + NX4closedata(fid); + dataID = SDreftoindex(pFile->iSID,sLink->iRef); + dataID = SDselect(pFile->iSID,dataID); + SDsetattr(dataID,name,type,length,sLink->targetPath); + SDendaccess(dataID); } else { - /* attach to the lower Vgroup */ + NX4makegroup(fid,newname,"NAPIlink"); + NX4opengroup(fid,newname,"NAPIlink"); + NX4putattr(fid,"NAPIlink",tags, 2, attType); + NX4closegroup(fid); + dataID = Vattach(pFile->iVID,sLink->iRef,"w"); + Vsetattr(dataID, (char *)name, type, (int32) length, sLink->targetPath); + Vdetach(dataID); + } + return NX_OK; + } + + /*----------------------------------------------------------------------*/ + + NXstatus NX4printlink (NXhandle fid, NXlink* sLink) + { + NXIassert (fid); + printf("HDF4 link: iTag = %ld, iRef = %ld, target=\"%s\"\n", sLink->iTag, sLink->iRef, sLink->targetPath); + return NX_OK; + } + + /*----------------------------------------------------------------------*/ + + NXstatus NX4flush(NXhandle *pHandle) + { + char *pFileName, *pCopy = NULL; + int access, dummy, iRet, i, iStack; + pNexusFile pFile = NULL; + NXaccess ac; + int *iRefs = NULL; + + pFile = NXIassert(*pHandle); + + /* + The HDF4-API does not support a flush. We help ourselves with + inquiring the name and access type of the file, closing it and + opening it again. This is also the reason why this needs a pointer + to the handle structure as the handle changes. The other thing we + do is to store the refs of all open vGroups in a temporary array + in order to recover the position in the vGroup hierarchy before the + flush. + */ + iRet = Hfidinquire(pFile->iVID,&pFileName,&access,&dummy); + if (iRet < 0) { + NXReportError( + "ERROR: Failed to inquire file name for HDF file"); + return NX_ERROR; + } + if(pFile->iAccess[0] == 'r') { + ac = NXACC_READ; + }else if(pFile->iAccess[0] == 'w') { + ac = NXACC_RDWR; + } else { + NXReportError( + "ERROR: NX4flush failed to determine file access mode"); + return NX_ERROR; + } + pCopy = (char *)malloc((strlen(pFileName)+10)*sizeof(char)); + if(!pCopy) { + NXReportError( + "ERROR: Failed to allocate data for filename copy"); + return NX_ERROR; + } + memset(pCopy,0,strlen(pFileName)+10); + strcpy(pCopy,pFileName); + + /* get refs for recovering vGroup position */ + iStack = 0; + if(pFile->iStackPtr > 0) { + iStack = pFile->iStackPtr + 1; + iRefs = (int *)malloc(iStack*sizeof(int)); + if(!iRefs){ + NXReportError( + "ERROR: Failed to allocate data for hierarchy copy"); + return NX_ERROR; + } + for(i = 0; i < iStack; i++){ + iRefs[i] = pFile->iStack[i].iVref; + } + } + + iRet = NX4close(pHandle); + if(iRet != NX_OK) { + return iRet; + } + + iRet = NX4open(pCopy, ac, pHandle); + free(pCopy); + + /* return to position in vGroup hierarchy */ + pFile = NXIassert(*pHandle); + if(iStack > 0){ + pFile->iStackPtr = iStack - 1; + for(i = 0; i < iStack; i++){ + pFile->iStack[i].iVref = iRefs[i]; + } + free(iRefs); pFile->iCurrentVG = Vattach(pFile->iVID, pFile->iStack[pFile->iStackPtr].iVref, pFile->iAccess); } - } - return NX_OK; -} - - - /* --------------------------------------------------------------------- */ - -NXstatus NX4makedata(NXhandle fid, CONSTCHAR * name, int datatype, - int rank, int dimensions[]) -{ - pNexusFile pFile; - int32 iNew; - char pBuffer[256]; - int i, iRet, type; - int32 myDim[MAX_VAR_DIMS]; - - pFile = NXIassert(fid); - - if (dimensions[0] == NX_UNLIMITED) { - dimensions[0] = SD_UNLIMITED; - } - - if ((iNew = NXIFindSDS(fid, name)) >= 0) { - sprintf(pBuffer, "ERROR: SDS %s already exists at this level", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - - if (datatype == NX_CHAR) { - type = DFNT_CHAR8; - } else if (datatype == NX_INT8) { - type = DFNT_INT8; - } else if (datatype == NX_UINT8) { - type = DFNT_UINT8; - } else if (datatype == NX_INT16) { - type = DFNT_INT16; - } else if (datatype == NX_UINT16) { - type = DFNT_UINT16; - } else if (datatype == NX_INT32) { - type = DFNT_INT32; - } else if (datatype == NX_UINT32) { - type = DFNT_UINT32; - } else if (datatype == NX_FLOAT32) { - type = DFNT_FLOAT32; - } else if (datatype == NX_FLOAT64) { - type = DFNT_FLOAT64; - } else { - NXIReportError(NXpData, "ERROR: invalid type in NX4makedata"); - return NX_ERROR; - } - - if (rank <= 0) { - sprintf(pBuffer, "ERROR: invalid rank specified for SDS %s", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - - /* - Check dimensions for consistency. The first dimension may be 0 - thus denoting an unlimited dimension. - */ - for (i = 1; i < rank; i++) { - if (dimensions[i] <= 0) { - sprintf(pBuffer, - "ERROR: invalid dimension %d, value %d given for SDS %s", - i, dimensions[i], name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - } - - /* cast the dimensions array properly for non 32-bit ints */ - for (i = 0; i < rank; i++) { - myDim[i] = (int32) dimensions[i]; - } - - - /* behave nicely, if there is still an SDS open */ - if (pFile->iCurrentSDS != 0) { - SDendaccess(pFile->iCurrentSDS); - pFile->iCurrentSDS = 0; - } - - /* Do not allow creation of SDS's at the root level */ - if (pFile->iCurrentVG == 0) { - sprintf(pBuffer, "ERROR: SDS creation at root level is not permitted"); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - - /* dataset creation */ - iNew = SDcreate(pFile->iSID, (char *) name, (int32) type, - (int32) rank, myDim); - if (iNew < 0) { - sprintf(pBuffer, "ERROR: cannot create SDS %s, check arguments", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - /* link into Vgroup, if in one */ - if (pFile->iCurrentVG != 0) { - iRet = Vaddtagref(pFile->iCurrentVG, DFTAG_NDG, SDidtoref(iNew)); - } - iRet = SDendaccess(iNew); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot end access to SDS"); - return NX_ERROR; - } - return NX_OK; -} - - - /* --------------------------------------------------------------------- */ - - -NXstatus NX4compmakedata(NXhandle fid, CONSTCHAR * name, int datatype, - int rank, int dimensions[], int compress_type, - int chunk_size[]) -{ - pNexusFile pFile; - int32 iNew, iRet, type; - char pBuffer[256]; - int i; - int32 myDim[MAX_VAR_DIMS]; - comp_info compstruct; - - pFile = NXIassert(fid); - - if (dimensions[0] == NX_UNLIMITED) { - dimensions[0] = SD_UNLIMITED; - } - - if ((iNew = NXIFindSDS(fid, name)) >= 0) { - sprintf(pBuffer, "ERROR: SDS %s already exists at this level", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - - if (datatype == NX_CHAR) { - type = DFNT_CHAR8; - } else if (datatype == NX_INT8) { - type = DFNT_INT8; - } else if (datatype == NX_UINT8) { - type = DFNT_UINT8; - } else if (datatype == NX_INT16) { - type = DFNT_INT16; - } else if (datatype == NX_UINT16) { - type = DFNT_UINT16; - } else if (datatype == NX_INT32) { - type = DFNT_INT32; - } else if (datatype == NX_UINT32) { - type = DFNT_UINT32; - } else if (datatype == NX_FLOAT32) { - type = DFNT_FLOAT32; - } else if (datatype == NX_FLOAT64) { - type = DFNT_FLOAT64; - } else { - NXIReportError(NXpData, "ERROR: invalid datatype in NX4compmakedata"); - return NX_ERROR; - } - - if (rank <= 0) { - sprintf(pBuffer, "ERROR: invalid rank specified for SDS %s", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - - /* - Check dimensions for consistency. The first dimension may be 0 - thus denoting an unlimited dimension. - */ - for (i = 1; i < rank; i++) { - if (dimensions[i] <= 0) { - sprintf(pBuffer, - "ERROR: invalid dimension %d, value %d given for SDS %s", - i, dimensions[i], name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - } - - /* cast the dimensions array properly for non 32-bit ints */ - for (i = 0; i < rank; i++) { - myDim[i] = (int32) dimensions[i]; - } - - - /* behave nicely, if there is still an SDS open */ - if (pFile->iCurrentSDS != 0) { - SDendaccess(pFile->iCurrentSDS); - pFile->iCurrentSDS = 0; - } - - /* Do not allow creation of SDS's at the root level */ - if (pFile->iCurrentVG == 0) { - sprintf(pBuffer, "ERROR: SDS creation at root level is not permitted"); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - - /* dataset creation */ - iNew = SDcreate(pFile->iSID, (char *) name, (int32) type, - (int32) rank, myDim); - if (iNew < 0) { - sprintf(pBuffer, "ERROR: cannot create SDS %s, check arguments", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - - /* compress SD data set */ - - if (compress_type == NX_COMP_LZW) { - compstruct.deflate.level = 6; - iRet = SDsetcompress(iNew, COMP_CODE_DEFLATE, &compstruct); - if (iRet < 0) { - NXIReportError(NXpData, "LZW-Compression failure!"); - return NX_ERROR; - } - } else if (compress_type == NX_COMP_RLE) { - iRet = SDsetcompress(iNew, COMP_CODE_RLE, &compstruct); - if (iRet < 0) { - NXIReportError(NXpData, "RLE-Compression failure!"); - return NX_ERROR; - } - } else if (compress_type == NX_COMP_HUF) { - compstruct.skphuff.skp_size = DFKNTsize(type); - iRet = SDsetcompress(iNew, COMP_CODE_SKPHUFF, &compstruct); - if (iRet < 0) { - NXIReportError(NXpData, "HUF-Compression failure!"); - return NX_ERROR; - } - } else if (compress_type == NX_COMP_NONE) { - /* */ - } else { - NXIReportError(NXpData, "Unknown compression method!"); - return NX_ERROR; - } - /* link into Vgroup, if in one */ - if (pFile->iCurrentVG != 0) { - iRet = Vaddtagref(pFile->iCurrentVG, DFTAG_NDG, SDidtoref(iNew)); - } - iRet = SDendaccess(iNew); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot end access to SDS"); - return NX_ERROR; - } - - return NX_OK; -} - - /* --------------------------------------------------------------------- */ - - -NXstatus NX4compress(NXhandle fid, int compress_type) -{ - pNexusFile pFile; - int32 iRank, iAtt, iType, iRet; - int32 iSize[MAX_VAR_DIMS]; - int compress_typei = COMP_CODE_NONE; - NXname pBuffer; - char pError[512]; - comp_info compstruct; - - pFile = NXIassert(fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError(NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - - if (compress_type == NX_COMP_NONE) { - compress_typei = COMP_CODE_NONE; - } else if (compress_type == NX_COMP_LZW) { - compress_typei = COMP_CODE_DEFLATE; - } else if (compress_type == NX_COMP_RLE) { - compress_typei = COMP_CODE_RLE; - } else if (compress_type == NX_COMP_HUF) { - compress_typei = COMP_CODE_SKPHUFF; - } - - /* first read dimension information */ - SDgetinfo(pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); - - /* - according to compression type initialize compression - information - */ - if (compress_type == NX_COMP_LZW) { - compstruct.deflate.level = 6; - } else if (compress_type == NX_COMP_HUF) { - compstruct.skphuff.skp_size = DFKNTsize(iType); - } - - iRet = SDsetcompress(pFile->iCurrentSDS, compress_typei, &compstruct); - if (iRet < 0) { - sprintf(pError, "ERROR: failure to compress data to %s", pBuffer); - NXIReportError(NXpData, pError); - return NX_ERROR; - } - return NX_OK; -} - - /* --------------------------------------------------------------------- */ - - -NXstatus NX4opendata(NXhandle fid, CONSTCHAR * name) -{ - pNexusFile pFile; - int32 iNew, attID, tags[2]; - char pBuffer[256]; - int iRet; - - pFile = NXIassert(fid); - - /* First find the reference number of the SDS */ - iNew = NXIFindSDS(fid, name); - if (iNew < 0) { - sprintf(pBuffer, "ERROR: SDS %s not found at this level", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - /* Be nice: properly close the old open SDS silently if there is - * still an SDS open. - */ - if (pFile->iCurrentSDS) { - iRet = SDendaccess(pFile->iCurrentSDS); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot end access to SDS"); - } - } - /* clear pending attribute directories first */ - NXIKillAttDir(pFile); - - /* open the SDS, thereby watching for linked SDS under a different name */ - iNew = SDreftoindex(pFile->iSID, iNew); - pFile->iCurrentSDS = SDselect(pFile->iSID, iNew); - attID = SDfindattr(pFile->iCurrentSDS, "NAPIlink"); - if (attID >= 0) { - SDreadattr(pFile->iCurrentSDS, attID, tags); - SDendaccess(pFile->iCurrentSDS); - iNew = SDreftoindex(pFile->iSID, tags[1]); - pFile->iCurrentSDS = SDselect(pFile->iSID, iNew); - } - - if (pFile->iCurrentSDS < 0) { - NXIReportError(NXpData, "ERROR: HDF error opening SDS"); - pFile->iCurrentSDS = 0; - return NX_ERROR; - } - return NX_OK; -} - - /* ----------------------------------------------------------------- */ - - -NXstatus NX4closedata(NXhandle fid) -{ - pNexusFile pFile; - int iRet; - - pFile = NXIassert(fid); - - if (pFile->iCurrentSDS != 0) { - iRet = SDendaccess(pFile->iCurrentSDS); - pFile->iCurrentSDS = 0; - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot end access to SDS"); - return NX_ERROR; - } - } else { - NXIReportError(NXpData, "ERROR: no SDS open --> nothing to do"); - return NX_ERROR; - } - NXIKillAttDir(pFile); /* for attribute data */ - return NX_OK; -} - - - /* ------------------------------------------------------------------- */ - -NXstatus NX4putdata(NXhandle fid, void *data) -{ - pNexusFile pFile; - int32 iStart[MAX_VAR_DIMS], iSize[MAX_VAR_DIMS], iStride[MAX_VAR_DIMS]; - NXname pBuffer; - int32 iRank, iAtt, iType, iRet, i; - char pError[512]; - - pFile = NXIassert(fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError(NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - /* first read dimension information */ - memset(iStart, 0, MAX_VAR_DIMS * sizeof(int32)); - SDgetinfo(pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); - - /* initialise stride to 1 */ - for (i = 0; i < iRank; i++) { - iStride[i] = 1; - } - - /* actually write */ - iRet = SDwritedata(pFile->iCurrentSDS, iStart, iStride, iSize, data); - if (iRet < 0) { - sprintf(pError, "ERROR: failure to write data to %s", pBuffer); - NXIReportError(NXpData, pError); - return NX_ERROR; - } - return NX_OK; -} - - /* ------------------------------------------------------------------- */ - -NXstatus -NX4putattr(NXhandle fid, CONSTCHAR * name, void *data, int datalen, - int iType) -{ - pNexusFile pFile; - int iRet, type; - - pFile = NXIassert(fid); - if (iType == NX_CHAR) { - type = DFNT_CHAR8; - } else if (iType == NX_INT8) { - type = DFNT_INT8; - } else if (iType == NX_UINT8) { - type = DFNT_UINT8; - } else if (iType == NX_INT16) { - type = DFNT_INT16; - } else if (iType == NX_UINT16) { - type = DFNT_UINT16; - } else if (iType == NX_INT32) { - type = DFNT_INT32; - } else if (iType == NX_UINT32) { - type = DFNT_UINT32; - } else if (iType == NX_FLOAT32) { - type = DFNT_FLOAT32; - } else if (iType == NX_FLOAT64) { - type = DFNT_FLOAT64; - } else { - NXIReportError(NXpData, "ERROR: Invalid data type for HDF attribute"); - return NX_ERROR; - } - if (pFile->iCurrentSDS != 0) { - /* SDS attribute */ - iRet = SDsetattr(pFile->iCurrentSDS, (char *) name, (int32) type, - (int32) datalen, data); - } else { - if (pFile->iCurrentVG == 0) { - /* global attribute */ - iRet = SDsetattr(pFile->iSID, (char *) name, (int32) type, - (int32) datalen, data); - } else { - /* group attribute */ - iRet = Vsetattr(pFile->iCurrentVG, (char *) name, (int32) type, - (int32) datalen, data); - } - } - iType = type; - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF failed to store attribute "); - return NX_ERROR; - } - return NX_OK; -} - - /* ------------------------------------------------------------------- */ - - -NXstatus NX4putslab(NXhandle fid, void *data, int iStart[], int iSize[]) -{ - pNexusFile pFile; - int iRet; - int32 iStride[MAX_VAR_DIMS]; - int32 myStart[MAX_VAR_DIMS], mySize[MAX_VAR_DIMS]; - int32 i, iRank, iType, iAtt; - NXname pBuffer; - - - pFile = NXIassert(fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError(NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - /* initialise stride to 1 */ - for (i = 0; i < MAX_VAR_DIMS; i++) { - iStride[i] = 1; - } - - /* if an int is not 32-bit we have to cast them properly in order - to kill a bug. - */ - if (sizeof(int) != 4) { - SDgetinfo(pFile->iCurrentSDS, pBuffer, &iRank, myStart, &iType, &iAtt); - for (i = 0; i < iRank; i++) { - myStart[i] = (int32) iStart[i]; - mySize[i] = (int32) iSize[i]; - } - /* finally write */ - iRet = SDwritedata(pFile->iCurrentSDS, myStart, iStride, mySize, data); - - } else { - /* write directly */ - - iRet = - SDwritedata(pFile->iCurrentSDS, (int32 *) iStart, iStride, - (int32 *) iSize, data); - } - - /* deal with HDF errors */ - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: writing slab failed"); - return NX_ERROR; - } - return NX_OK; -} - - - /* ------------------------------------------------------------------- */ - -NXstatus NX4getdataID(NXhandle fid, NXlink * sRes) -{ - pNexusFile pFile; - - pFile = NXIassert(fid); - - if (pFile->iCurrentSDS == 0) { - sRes->iTag = NX_ERROR; - return NX_ERROR; - } else { - sRes->iTag = DFTAG_NDG; - sRes->iRef = SDidtoref(pFile->iCurrentSDS); - NXIbuildPath(pFile, sRes->targetPath, 1024); - return NX_OK; - } - sRes->iTag = NX_ERROR; - return NX_ERROR; /* not reached */ -} - - - /* ------------------------------------------------------------------- */ - - -NXstatus NX4makelink(NXhandle fid, NXlink * sLink) -{ - pNexusFile pFile; - int32 iVG, iRet, dataID, type = DFNT_CHAR8, length; - char name[] = "target"; - - pFile = NXIassert(fid); - - if (pFile->iCurrentVG == 0) { /* root level, can not link here */ - return NX_ERROR; - } - Vaddtagref(pFile->iCurrentVG, sLink->iTag, sLink->iRef); - length = strlen(sLink->targetPath); - if (sLink->iTag == DFTAG_SDG || sLink->iTag == DFTAG_NDG || - sLink->iTag == DFTAG_SDS) { - dataID = SDreftoindex(pFile->iSID, sLink->iRef); - dataID = SDselect(pFile->iSID, dataID); - SDsetattr(dataID, name, type, length, sLink->targetPath); - SDendaccess(dataID); - } else { - dataID = Vattach(pFile->iVID, sLink->iRef, "w"); - Vsetattr(dataID, (char *) name, type, (int32) length, - sLink->targetPath); - Vdetach(dataID); - } - return NX_OK; -} - - /* ------------------------------------------------------------------- */ - - -NXstatus NX4makenamedlink(NXhandle fid, CONSTCHAR * newname, - NXlink * sLink) -{ - pNexusFile pFile; - int32 iVG, iRet, dataID, type = DFNT_CHAR8, length, dataType = NX_CHAR, - rank = 1, attType = NX_INT32; - int iDim[1]; - char name[] = "target"; - int tags[2]; - - pFile = NXIassert(fid); - - if (pFile->iCurrentVG == 0) { /* root level, can not link here */ - return NX_ERROR; - } - - tags[0] = sLink->iTag; - tags[1] = sLink->iRef; - - length = strlen(sLink->targetPath); - if (sLink->iTag == DFTAG_SDG || sLink->iTag == DFTAG_NDG || - sLink->iTag == DFTAG_SDS) { - iDim[0] = 1; - NX4makedata(fid, newname, dataType, rank, iDim); - NX4opendata(fid, newname); - NX4putattr(fid, "NAPIlink", tags, 2, attType); - NX4closedata(fid); - dataID = SDreftoindex(pFile->iSID, sLink->iRef); - dataID = SDselect(pFile->iSID, dataID); - SDsetattr(dataID, name, type, length, sLink->targetPath); - SDendaccess(dataID); - } else { - NX4makegroup(fid, newname, "NAPIlink"); - NX4opengroup(fid, newname, "NAPIlink"); - NX4putattr(fid, "NAPIlink", tags, 2, attType); - NX4closegroup(fid); - dataID = Vattach(pFile->iVID, sLink->iRef, "w"); - Vsetattr(dataID, (char *) name, type, (int32) length, - sLink->targetPath); - Vdetach(dataID); - } - return NX_OK; -} - - /*----------------------------------------------------------------------*/ - -NXstatus NX4printlink(NXhandle fid, NXlink * sLink) -{ - pNexusFile pFile; - pFile = NXIassert(fid); - printf("HDF4 link: iTag = %ld, iRef = %ld, target=\"%s\"\n", sLink->iTag, - sLink->iRef, sLink->targetPath); - return NX_OK; -} - - /*----------------------------------------------------------------------*/ - -NXstatus NX4flush(NXhandle * pHandle) -{ - char *pFileName, *pCopy = NULL; - int access, dummy, iRet, i, iStack; - pNexusFile pFile = NULL; - NXaccess ac; - int *iRefs = NULL; - - pFile = NXIassert(*pHandle); - - /* - The HDF4-API does not support a flush. We help ourselves with - inquiring the name and access type of the file, closing it and - opening it again. This is also the reason why this needs a pointer - to the handle structure as the handle changes. The other thing we - do is to store the refs of all open vGroups in a temporary array - in order to recover the position in the vGroup hierarchy before the - flush. - */ - iRet = Hfidinquire(pFile->iVID, &pFileName, &access, &dummy); - if (iRet < 0) { - NXIReportError(NXpData, - "ERROR: Failed to inquire file name for HDF file"); - return NX_ERROR; - } - if (pFile->iAccess[0] == 'r') { - ac = NXACC_READ; - } else if (pFile->iAccess[0] == 'w') { - ac = NXACC_RDWR; - } else { - NXIReportError(NXpData, - "ERROR: NX4flush failed to determine file access mode"); - return NX_ERROR; - } - pCopy = (char *) malloc((strlen(pFileName) + 10) * sizeof(char)); - if (!pCopy) { - NXIReportError(NXpData, - "ERROR: Failed to allocate data for filename copy"); - return NX_ERROR; - } - memset(pCopy, 0, strlen(pFileName) + 10); - strcpy(pCopy, pFileName); - - /* get refs for recovering vGroup position */ - iStack = 0; - if (pFile->iStackPtr > 0) { - iStack = pFile->iStackPtr + 1; - iRefs = (int *) malloc(iStack * sizeof(int)); - if (!iRefs) { - NXIReportError(NXpData, - "ERROR: Failed to allocate data for hierarchy copy"); - return NX_ERROR; - } - for (i = 0; i < iStack; i++) { - iRefs[i] = pFile->iStack[i].iVref; - } - } - - iRet = NX4close(pHandle); - if (iRet != NX_OK) { + return iRet; - } - - iRet = NX4open(pCopy, ac, pHandle); - free(pCopy); - - /* return to position in vGroup hierarchy */ - pFile = NXIassert(*pHandle); - if (iStack > 0) { - pFile->iStackPtr = iStack - 1; - for (i = 0; i < iStack; i++) { - pFile->iStack[i].iVref = iRefs[i]; - } - free(iRefs); - pFile->iCurrentVG = Vattach(pFile->iVID, - pFile->iStack[pFile->iStackPtr].iVref, - pFile->iAccess); - } - - return iRet; -} + } /*-------------------------------------------------------------------------*/ + + NXstatus NX4getnextentry (NXhandle fid, NXname name, NXname nxclass, int *datatype) + { + pNexusFile pFile; + int iRet, iStackPtr, iCurDir; + int32 iTemp, iD1, iD2, iA; + int32 iDim[H4_MAX_VAR_DIMS]; + + pFile = NXIassert (fid); + + iStackPtr = pFile->iStackPtr; + iCurDir = pFile->iStack[pFile->iStackPtr].iCurDir; + + /* first case to check for: no directory entry */ + if (pFile->iStack[pFile->iStackPtr].iRefDir == NULL) { + iRet = NXIInitDir (pFile); + if (iRet < 0) { + NXReportError( + "ERROR: no memory to store directory info"); + return NX_EOD; + } + } -NXstatus NX4getnextentry(NXhandle fid, NXname name, NXname nxclass, - int *datatype) -{ - pNexusFile pFile; - int iRet, iStackPtr, iCurDir; - int32 iTemp, iD1, iD2, iA; - int32 iDim[MAX_VAR_DIMS]; - - pFile = NXIassert(fid); - - iStackPtr = pFile->iStackPtr; - iCurDir = pFile->iStack[pFile->iStackPtr].iCurDir; - - /* first case to check for: no directory entry */ - if (pFile->iStack[pFile->iStackPtr].iRefDir == NULL) { - iRet = NXIInitDir(pFile); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: no memory to store directory info"); + /* Next case: end of directory */ + if (iCurDir >= pFile->iStack[pFile->iStackPtr].iNDir) { + NXIKillDir (pFile); return NX_EOD; } - } - /* Next case: end of directory */ - if (iCurDir >= pFile->iStack[pFile->iStackPtr].iNDir) { - NXIKillDir(pFile); - return NX_EOD; - } - - /* Next case: we have data! supply it and increment counter */ - if (pFile->iCurrentVG == 0) { /* root level */ - iTemp = Vattach(pFile->iVID, - pFile->iStack[iStackPtr].iRefDir[iCurDir], "r"); - if (iTemp < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot attach to Vgroup"); - return NX_ERROR; - } - Vgetname(iTemp, name); - Vdetach(iTemp); - findNapiClass(pFile, pFile->iStack[pFile->iStackPtr].iRefDir[iCurDir], - nxclass); - *datatype = DFTAG_VG; - pFile->iStack[pFile->iStackPtr].iCurDir++; - return NX_OK; - } else { /* in Vgroup */ - if (pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_VG) { /* Vgroup */ - iTemp = Vattach(pFile->iVID, - pFile->iStack[iStackPtr].iRefDir[iCurDir], "r"); + /* Next case: we have data! supply it and increment counter */ + if (pFile->iCurrentVG == 0) { /* root level */ + iTemp = Vattach (pFile->iVID, + pFile->iStack[iStackPtr].iRefDir[iCurDir], "r"); if (iTemp < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot attach to Vgroup"); + NXReportError( "ERROR: HDF cannot attach to Vgroup"); return NX_ERROR; } - Vgetname(iTemp, name); - Vdetach(iTemp); - findNapiClass(pFile, - pFile->iStack[pFile->iStackPtr].iRefDir[iCurDir], - nxclass); + Vgetname (iTemp, name); + Vdetach (iTemp); + findNapiClass(pFile, pFile->iStack[pFile->iStackPtr].iRefDir[iCurDir], nxclass); *datatype = DFTAG_VG; pFile->iStack[pFile->iStackPtr].iCurDir++; - Vdetach(iTemp); - return NX_OK; - /* we are now writing using DFTAG_NDG, but need others for backward compatability */ - } else if ((pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_SDG) || - (pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_NDG) || - (pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_SDS)) { - iTemp = SDreftoindex(pFile->iSID, - pFile->iStack[iStackPtr].iRefDir[iCurDir]); - iTemp = SDselect(pFile->iSID, iTemp); - SDgetinfo(iTemp, name, &iA, iDim, &iD1, &iD2); - strcpy(nxclass, "SDS"); - *datatype = iD1; - SDendaccess(iTemp); - pFile->iStack[pFile->iStackPtr].iCurDir++; - return NX_OK; - } else { /* unidentified */ - strcpy(name, "UNKNOWN"); - strcpy(nxclass, "UNKNOWN"); - *datatype = pFile->iStack[iStackPtr].iTagDir[iCurDir]; - pFile->iStack[pFile->iStackPtr].iCurDir++; return NX_OK; + } else { /* in Vgroup */ + if (pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_VG) {/* Vgroup */ + iTemp = Vattach (pFile->iVID, + pFile->iStack[iStackPtr].iRefDir[iCurDir], "r"); + if (iTemp < 0) { + NXReportError( "ERROR: HDF cannot attach to Vgroup"); + return NX_ERROR; + } + Vgetname (iTemp, name); + Vdetach(iTemp); + findNapiClass(pFile, pFile->iStack[pFile->iStackPtr].iRefDir[iCurDir], nxclass); + *datatype = DFTAG_VG; + pFile->iStack[pFile->iStackPtr].iCurDir++; + Vdetach (iTemp); + return NX_OK; + /* we are now writing using DFTAG_NDG, but need others for backward compatability */ + } else if ((pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_SDG) || + (pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_NDG) || + (pFile->iStack[iStackPtr].iTagDir[iCurDir] == DFTAG_SDS)) { + iTemp = SDreftoindex (pFile->iSID, + pFile->iStack[iStackPtr].iRefDir[iCurDir]); + iTemp = SDselect (pFile->iSID, iTemp); + SDgetinfo (iTemp, name, &iA, iDim, &iD1, &iD2); + strcpy (nxclass, "SDS"); + *datatype = iD1; + SDendaccess (iTemp); + pFile->iStack[pFile->iStackPtr].iCurDir++; + return NX_OK; + } else { /* unidentified */ + strcpy (name, "UNKNOWN"); + strcpy (nxclass, "UNKNOWN"); + *datatype = pFile->iStack[iStackPtr].iTagDir[iCurDir]; + pFile->iStack[pFile->iStackPtr].iCurDir++; + return NX_OK; + } } + return NX_ERROR; /* not reached */ } - return NX_ERROR; /* not reached */ -} /*-------------------------------------------------------------------------*/ - -NXstatus NX4getdata(NXhandle fid, void *data) -{ - pNexusFile pFile; - int32 iStart[MAX_VAR_DIMS], iSize[MAX_VAR_DIMS]; - NXname pBuffer; - int32 iRank, iAtt, iType; - - pFile = NXIassert(fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError(NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - /* first read dimension information */ - memset(iStart, 0, MAX_VAR_DIMS * sizeof(int32)); - SDgetinfo(pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); - /* actually read */ - SDreaddata(pFile->iCurrentSDS, iStart, NULL, iSize, data); - return NX_OK; -} - - /*-------------------------------------------------------------------------*/ - -NXstatus NX4getinfo(NXhandle fid, int *rank, int dimension[], int *iType) -{ - pNexusFile pFile; - NXname pBuffer; - int32 iAtt, myDim[MAX_VAR_DIMS], i, iRank, mType; - - pFile = NXIassert(fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError(NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - /* read information */ - SDgetinfo(pFile->iCurrentSDS, pBuffer, &iRank, myDim, &mType, &iAtt); - - /* conversion to proper ints for the platform */ - *iType = (int) mType; - *rank = (int) iRank; - for (i = 0; i < iRank; i++) { - dimension[i] = (int) myDim[i]; - } - return NX_OK; -} - - - /*-------------------------------------------------------------------------*/ - - -NXstatus NX4getslab(NXhandle fid, void *data, int iStart[], int iSize[]) -{ - pNexusFile pFile; - int32 myStart[MAX_VAR_DIMS], mySize[MAX_VAR_DIMS]; - int32 i, iRank, iType, iAtt; - NXname pBuffer; - - pFile = NXIassert(fid); - - /* check if there is an SDS open */ - if (pFile->iCurrentSDS == 0) { - NXIReportError(NXpData, "ERROR: no SDS open"); - return NX_ERROR; - } - - /* if an int is not 32-bit we have to cast them properly in order - to kill a bug. - */ - if (sizeof(int) != 4) { - SDgetinfo(pFile->iCurrentSDS, pBuffer, &iRank, myStart, &iType, &iAtt); - for (i = 0; i < iRank; i++) { - myStart[i] = (int32) iStart[i]; - mySize[i] = (int32) iSize[i]; - } - /* finally read */ - SDreaddata(pFile->iCurrentSDS, myStart, NULL, mySize, data); - return NX_OK; - } else { - /* read directly */ - SDreaddata(pFile->iCurrentSDS, (int32 *) iStart, NULL, - (int32 *) iSize, data); - return NX_OK; - } -} - - /*-------------------------------------------------------------------------*/ - -NXstatus NX4getnextattr(NXhandle fileid, NXname pName, - int *iLength, int *iType) -{ - pNexusFile pFile; - int iRet; - int32 iPType, iCount, count; - - pFile = NXIassert(fileid); - - /* first check if we have to start a new attribute search */ - if (pFile->iAtt.iNDir == 0) { - iRet = NXIInitAttDir(pFile); - if (iRet == NX_ERROR) { + + NXstatus NX4getdata (NXhandle fid, void *data) + { + pNexusFile pFile; + int32 iStart[H4_MAX_VAR_DIMS], iSize[H4_MAX_VAR_DIMS]; + NXname pBuffer; + int32 iRank, iAtt, iType; + + pFile = NXIassert (fid); + + /* check if there is an SDS open */ + if (pFile->iCurrentSDS == 0) { + NXReportError( "ERROR: no SDS open"); return NX_ERROR; } - } - /* are we done ? */ - if (pFile->iAtt.iCurDir >= pFile->iAtt.iNDir) { - NXIKillAttDir(pFile); - return NX_EOD; - } - /* well, there must be data to copy */ - if (pFile->iCurrentSDS == 0) { - if (pFile->iCurrentVG == 0) { - /* global attribute */ - iRet = SDattrinfo(pFile->iSID, pFile->iAtt.iCurDir, - pName, &iPType, &iCount); - } else { - /* group attribute */ - iRet = Vattrinfo(pFile->iCurrentVG, pFile->iAtt.iCurDir, - pName, &iPType, &iCount, &count); - } - } else { - iRet = SDattrinfo(pFile->iCurrentSDS, pFile->iAtt.iCurDir, - pName, &iPType, &iCount); - } - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot read attribute info"); - return NX_ERROR; - } - *iLength = iCount; - *iType = iPType; - pFile->iAtt.iCurDir++; - return NX_OK; -} - - + /* first read dimension information */ + memset (iStart, 0, H4_MAX_VAR_DIMS * sizeof (int32)); + SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, iSize, &iType, &iAtt); + /* actually read */ + SDreaddata (pFile->iCurrentSDS, iStart, NULL, iSize, data); + return NX_OK; + } + /*-------------------------------------------------------------------------*/ - -NXstatus NX4getattr(NXhandle fid, char *name, void *data, int *datalen, - int *iType) -{ - pNexusFile pFile; - int32 iNew, iType32, count; - void *pData = NULL; - int32 iLen, iRet; - int type; - char pBuffer[256]; - NXname pNam; - - type = *iType; - if (type == NX_CHAR) { - type = DFNT_CHAR8; - } else if (type == NX_INT8) { - type = DFNT_INT8; - } else if (type == NX_UINT8) { - type = DFNT_UINT8; - } else if (type == NX_INT16) { - type = DFNT_INT16; - } else if (type == NX_UINT16) { - type = DFNT_UINT16; - } else if (type == NX_INT32) { - type = DFNT_INT32; - } else if (type == NX_UINT32) { - type = DFNT_UINT32; - } else if (type == NX_FLOAT32) { - type = DFNT_FLOAT32; - } else if (type == NX_FLOAT64) { - type = DFNT_FLOAT64; - } - *datalen = (*datalen) * DFKNTsize(type); - pFile = NXIassert(fid); - - /* find attribute */ - if (pFile->iCurrentSDS != 0) { - /* SDS attribute */ - iNew = SDfindattr(pFile->iCurrentSDS, name); - } else { - if (pFile->iCurrentVG == 0) { - /* global attribute */ - iNew = SDfindattr(pFile->iSID, name); - } else { - /* group attribute */ - iNew = Vfindattr(pFile->iCurrentVG, name); + NXstatus + NX4getinfo64 (NXhandle fid, int *rank, int64_t dimension[], + int *iType) + { + pNexusFile pFile; + NXname pBuffer; + int32 iAtt, myDim[H4_MAX_VAR_DIMS], i, iRank, mType; + + pFile = NXIassert (fid); + + /* check if there is an SDS open */ + if (pFile->iCurrentSDS == 0) { + NXReportError( "ERROR: no SDS open"); + return NX_ERROR; } - } - if (iNew < 0) { - sprintf(pBuffer, "ERROR: attribute %s not found", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - /* get more info, allocate temporary data space */ - iType32 = (int32) type; - if (pFile->iCurrentSDS != 0) { - iRet = SDattrinfo(pFile->iCurrentSDS, iNew, pNam, &iType32, &iLen); - } else { - if (pFile->iCurrentVG == 0) { - iRet = SDattrinfo(pFile->iSID, iNew, pNam, &iType32, &iLen); - } else { - iRet = Vattrinfo(pFile->iCurrentVG, iNew, pNam, &iType32, &count, - &iLen); + /* read information */ + SDgetinfo (pFile->iCurrentSDS, pBuffer, &iRank, myDim, + &mType, &iAtt); + + /* conversion to proper ints for the platform */ + *iType = (int)mType; + *rank = (int)iRank; + for(i = 0; i < iRank; i++) + { + dimension[i] = (int)myDim[i]; } - } - if (iRet < 0) { - sprintf(pBuffer, "ERROR: HDF could not read attribute info"); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - *iType = (int) iType32; - iLen = iLen * DFKNTsize(*iType); - pData = (void *) malloc(iLen); - if (!pData) { - NXIReportError(NXpData, "ERROR: allocating memory in NXgetattr"); - return NX_ERROR; - } - memset(pData, 0, iLen); - - /* finally read the data */ - if (pFile->iCurrentSDS != 0) { - iRet = SDreadattr(pFile->iCurrentSDS, iNew, pData); - } else { - if (pFile->iCurrentVG == 0) { - iRet = SDreadattr(pFile->iSID, iNew, pData); - } else { - iRet = Vgetattr(pFile->iCurrentVG, iNew, pData); - } - } - if (iRet < 0) { - sprintf(pBuffer, "ERROR: HDF could not read attribute data"); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - /* copy data to caller */ - memset(data, 0, *datalen); - if ((*datalen <= iLen) && - (*iType == DFNT_UINT8 || *iType == DFNT_CHAR8 - || *iType == DFNT_UCHAR8)) { - iLen = *datalen - 1; - } - memcpy(data, pData, iLen); - *datalen = iLen / DFKNTsize(*iType); - free(pData); - return NX_OK; -} - - /*-------------------------------------------------------------------------*/ - - -NXstatus NX4getattrinfo(NXhandle fid, int *iN) -{ - pNexusFile pFile; - int iRet; - int32 iData, iAtt, iRank, iType; - int32 iDim[MAX_VAR_DIMS]; - NXname pNam; - - pFile = NXIassert(fid); - if (pFile->iCurrentSDS != 0) { /* SDS level */ - iRet = SDgetinfo(pFile->iCurrentSDS, pNam, &iRank, iDim, &iType, - &iAtt); - } else { - if (pFile->iCurrentVG == 0) { - /* global level */ - iRet = SDfileinfo(pFile->iSID, &iData, &iAtt); - } else { - iRet = Vnattrs(pFile->iCurrentVG); - iAtt = iRet; - } - } - if (iRet < 0) { - NXIReportError(NXpData, "NX_ERROR: HDF cannot read attribute numbers"); - *iN = 0; - return NX_ERROR; - } - *iN = iAtt; - return NX_OK; -} - - /*-------------------------------------------------------------------------*/ - -NXstatus NX4getgroupID(NXhandle fileid, NXlink * sRes) -{ - pNexusFile pFile; - - pFile = NXIassert(fileid); - - if (pFile->iCurrentVG == 0) { - sRes->iTag = NX_ERROR; - return NX_ERROR; - } else { - sRes->iTag = DFTAG_VG; - sRes->iRef = VQueryref(pFile->iCurrentVG); - NXIbuildPath(pFile, sRes->targetPath, 1024); return NX_OK; } - /* not reached */ - sRes->iTag = NX_ERROR; - return NX_ERROR; -} + + + /*-------------------------------------------------------------------------*/ + + + NXstatus NX4getslab64 (NXhandle fid, void *data, const int64_t iStart[], const int64_t iSize[]) + { + pNexusFile pFile; + int32 myStart[H4_MAX_VAR_DIMS], mySize[H4_MAX_VAR_DIMS]; + int32 i, iRank, iType, iAtt; + NXname pBuffer; + + pFile = NXIassert (fid); + + /* check if there is an SDS open */ + if (pFile->iCurrentSDS == 0) { + NXReportError( "ERROR: no SDS open"); + return NX_ERROR; + } + + SDgetinfo (pFile->iCurrentSDS, pBuffer, + &iRank, myStart, &iType, &iAtt); + for(i = 0; i < iRank; i++) + { + myStart[i] = (int32)iStart[i]; + mySize[i] = (int32)iSize[i]; + } + /* finally read */ + SDreaddata (pFile->iCurrentSDS, myStart, NULL, + mySize, data); + return NX_OK; + } + + /*-------------------------------------------------------------------------*/ + + NXstatus NX4getnextattr (NXhandle fileid, NXname pName, + int *iLength, int *iType) + { + pNexusFile pFile; + int iRet; + int32 iPType, iCount, count; + + pFile = NXIassert (fileid); + + /* first check if we have to start a new attribute search */ + if (pFile->iAtt.iNDir == 0) { + iRet = NXIInitAttDir (pFile); + if (iRet == NX_ERROR) { + return NX_ERROR; + } + } + /* are we done ? */ + if (pFile->iAtt.iCurDir >= pFile->iAtt.iNDir) { + NXIKillAttDir (pFile); + return NX_EOD; + } + /* well, there must be data to copy */ + if (pFile->iCurrentSDS == 0) { + if(pFile->iCurrentVG == 0) { + /* global attribute */ + iRet = SDattrinfo (pFile->iSID, pFile->iAtt.iCurDir, + pName, &iPType, &iCount); + }else { + /* group attribute */ + iRet = Vattrinfo(pFile->iCurrentVG, pFile->iAtt.iCurDir, + pName, &iPType, &iCount, &count); + } + } else { + iRet = SDattrinfo (pFile->iCurrentSDS, pFile->iAtt.iCurDir, + pName, &iPType, &iCount); + } + if (iRet < 0) { + NXReportError( "ERROR: HDF cannot read attribute info"); + return NX_ERROR; + } + *iLength = iCount; + *iType = iPType; + pFile->iAtt.iCurDir++; + return NX_OK; + } + + + /*-------------------------------------------------------------------------*/ + + + NXstatus NX4getattr (NXhandle fid, char *name, void *data, int* datalen, int* iType) + { + pNexusFile pFile; + int32 iNew, iType32, count; + void *pData = NULL; + int32 iLen, iRet; + int type; + char pBuffer[256]; + NXname pNam; + + type = *iType; + if (type == NX_CHAR) + { + type=DFNT_CHAR8; + } + else if (type == NX_INT8) + { + type=DFNT_INT8; + } + else if (type == NX_UINT8) + { + type=DFNT_UINT8; + } + else if (type == NX_INT16) + { + type=DFNT_INT16; + } + else if (type == NX_UINT16) + { + type=DFNT_UINT16; + } + else if (type == NX_INT32) + { + type=DFNT_INT32; + } + else if (type == NX_UINT32) + { + type=DFNT_UINT32; + } + else if (type == NX_FLOAT32) + { + type=DFNT_FLOAT32; + } + else if (type == NX_FLOAT64) + { + type=DFNT_FLOAT64; + } + *datalen = (*datalen) * DFKNTsize(type); + pFile = NXIassert (fid); + + /* find attribute */ + if (pFile->iCurrentSDS != 0) { + /* SDS attribute */ + iNew = SDfindattr (pFile->iCurrentSDS, name); + } else { + if(pFile->iCurrentVG == 0){ + /* global attribute */ + iNew = SDfindattr (pFile->iSID, name); + } else { + /* group attribute */ + iNew = Vfindattr(pFile->iCurrentVG, name); + } + } + if (iNew < 0) { + sprintf (pBuffer, "ERROR: attribute \"%s\" not found", name); + NXReportError( pBuffer); + return NX_ERROR; + } + /* get more info, allocate temporary data space */ + iType32 = (int32)type; + if (pFile->iCurrentSDS != 0) { + iRet = SDattrinfo (pFile->iCurrentSDS, iNew, pNam, &iType32, &iLen); + } else { + if(pFile->iCurrentVG == 0){ + iRet = SDattrinfo (pFile->iSID, iNew, pNam, &iType32, &iLen); + } else { + iRet = Vattrinfo(pFile->iCurrentVG,iNew,pNam,&iType32,&count, + &iLen); + } + } + if (iRet < 0) { + sprintf (pBuffer, "ERROR: HDF could not read attribute info"); + NXReportError( pBuffer); + return NX_ERROR; + } + *iType = (int)iType32; + iLen = iLen * DFKNTsize (*iType); + if(*iType == NX_CHAR){ + iLen += 1; + } + pData = (void *) malloc (iLen); + if (!pData) { + NXReportError( "ERROR: allocating memory in NXgetattr"); + return NX_ERROR; + } + memset (pData, 0, iLen); + + /* finally read the data */ + if (pFile->iCurrentSDS != 0) { + iRet = SDreadattr (pFile->iCurrentSDS, iNew, pData); + } else { + if(pFile->iCurrentVG == 0){ + iRet = SDreadattr (pFile->iSID, iNew, pData); + } else { + iRet = Vgetattr(pFile->iCurrentVG, iNew, pData); + } + } + if (iRet < 0) { + sprintf (pBuffer, "ERROR: HDF could not read attribute data"); + NXReportError( pBuffer); + return NX_ERROR; + } + /* copy data to caller */ + memset (data, 0, *datalen); + if ((*datalen <= iLen) && + (*iType == DFNT_UINT8 || *iType == DFNT_CHAR8 || *iType == DFNT_UCHAR8)) { + iLen = *datalen - 1; /* this enforces NULL termination regardless of size of datalen */ + } + memcpy (data, pData, iLen); + *datalen = iLen / DFKNTsize(*iType); + free (pData); + return NX_OK; + } + + /*-------------------------------------------------------------------------*/ + + + NXstatus NX4getattrinfo (NXhandle fid, int *iN) + { + pNexusFile pFile; + int iRet; + int32 iData, iAtt, iRank, iType; + int32 iDim[H4_MAX_VAR_DIMS]; + NXname pNam; + + pFile = NXIassert (fid); + if (pFile->iCurrentSDS != 0) { /* SDS level */ + iRet = SDgetinfo (pFile->iCurrentSDS, pNam, &iRank, iDim, &iType, + &iAtt); + } else { + if(pFile->iCurrentVG == 0){ + /* global level */ + iRet = SDfileinfo (pFile->iSID, &iData, &iAtt); + } else { + iRet = Vnattrs(pFile->iCurrentVG); + iAtt = iRet; + } + } + if (iRet < 0) { + NXReportError( "NX_ERROR: HDF cannot read attribute numbers"); + *iN = 0; + return NX_ERROR; + } + *iN = iAtt; + return NX_OK; + } + + /*-------------------------------------------------------------------------*/ + + NXstatus NX4getgroupID (NXhandle fileid, NXlink* sRes) + { + pNexusFile pFile; + + pFile = NXIassert (fileid); + + if (pFile->iCurrentVG == 0) { + sRes->iTag = NX_ERROR; + return NX_ERROR; + } else { + sRes->iTag = DFTAG_VG; + sRes->iRef = VQueryref(pFile->iCurrentVG); + NXIbuildPath(pFile,sRes->targetPath,1024); + return NX_OK; + } + /* not reached */ + sRes->iTag = NX_ERROR; + return NX_ERROR; + } /*-------------------------------------------------------------------------*/ -NXstatus -NX4getgroupinfo(NXhandle fid, int *iN, NXname pName, NXname pClass) -{ - pNexusFile pFile; - - pFile = NXIassert(fid); - /* check if there is a group open */ - if (pFile->iCurrentVG == 0) { - *iN = Vlone(pFile->iVID, NULL, 0); - strcpy(pName, "root"); - strcpy(pClass, "NXroot"); - } else { - *iN = Vntagrefs(pFile->iCurrentVG); - Vgetname(pFile->iCurrentVG, pName); - Vgetclass(pFile->iCurrentVG, pClass); + NXstatus + NX4getgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass) + { + pNexusFile pFile; + + pFile = NXIassert (fid); + /* check if there is a group open */ + if (pFile->iCurrentVG == 0) { + *iN = Vlone (pFile->iVID, NULL, 0); + strcpy (pName, "root"); + strcpy (pClass, "NXroot"); + } + else { + *iN = Vntagrefs (pFile->iCurrentVG); + Vgetname (pFile->iCurrentVG, pName); + Vgetclass (pFile->iCurrentVG, pClass); + } + return NX_OK; } - return NX_OK; -} - + /* ------------------------------------------------------------------- */ -NXstatus NX4sameID(NXhandle fileid, NXlink * pFirstID, NXlink * pSecondID) -{ - pNexusFile pFile; + NXstatus NX4sameID (NXhandle fileid, NXlink* pFirstID, NXlink* pSecondID) + { + NXIassert (fileid); + if ((pFirstID->iTag == pSecondID->iTag) & (pFirstID->iRef == pSecondID->iRef)) { + return NX_OK; + } else { + return NX_ERROR; + } + } - pFile = NXIassert(fileid); - if ((pFirstID->iTag == pSecondID->iTag) & (pFirstID->iRef == - pSecondID->iRef)) { + /*-------------------------------------------------------------------------*/ + + + NXstatus NX4initattrdir (NXhandle fid) + { + pNexusFile pFile; + int iRet; + + pFile = NXIassert (fid); + NXIKillAttDir (pFile); + iRet = NXIInitAttDir (pFile); + if (iRet == NX_ERROR) + return NX_ERROR; return NX_OK; - } else { - return NX_ERROR; } -} - + + /*-------------------------------------------------------------------------*/ - - -NXstatus NX4initattrdir(NXhandle fid) -{ - pNexusFile pFile; - int iRet; - - pFile = NXIassert(fid); - NXIKillAttDir(fid); - iRet = NXIInitAttDir(pFile); - if (iRet == NX_ERROR) - return NX_ERROR; - return NX_OK; -} - - - /*-------------------------------------------------------------------------*/ - - -NXstatus NX4initgroupdir(NXhandle fid) -{ - pNexusFile pFile; - int iRet; - - pFile = NXIassert(fid); - NXIKillDir(fid); - iRet = NXIInitDir(pFile); - if (iRet < 0) { - NXIReportError(NXpData, "NX_ERROR: no memory to store directory info"); - return NX_EOD; + + + NXstatus NX4initgroupdir (NXhandle fid) + { + pNexusFile pFile; + int iRet; + + pFile = NXIassert (fid); + NXIKillDir (pFile); + iRet = NXIInitDir (pFile); + if (iRet < 0) { + NXReportError("NX_ERROR: no memory to store directory info"); + return NX_EOD; + } + return NX_OK; } - return NX_OK; -} - + /*--------------------------------------------------------------------*/ void NX4assignFunctions(pNexusFunction fHandle) { - fHandle->nxclose = NX4close; - fHandle->nxflush = NX4flush; - fHandle->nxmakegroup = NX4makegroup; - fHandle->nxopengroup = NX4opengroup; - fHandle->nxclosegroup = NX4closegroup; - fHandle->nxmakedata = NX4makedata; - fHandle->nxcompmakedata = NX4compmakedata; - fHandle->nxcompress = NX4compress; - fHandle->nxopendata = NX4opendata; - fHandle->nxclosedata = NX4closedata; - fHandle->nxputdata = NX4putdata; - fHandle->nxputattr = NX4putattr; - fHandle->nxputslab = NX4putslab; - fHandle->nxgetdataID = NX4getdataID; - fHandle->nxmakelink = NX4makelink; - fHandle->nxmakenamedlink = NX4makenamedlink; - fHandle->nxgetdata = NX4getdata; - fHandle->nxgetinfo = NX4getinfo; - fHandle->nxgetnextentry = NX4getnextentry; - fHandle->nxgetslab = NX4getslab; - fHandle->nxgetnextattr = NX4getnextattr; - fHandle->nxgetattr = NX4getattr; - fHandle->nxgetattrinfo = NX4getattrinfo; - fHandle->nxgetgroupID = NX4getgroupID; - fHandle->nxgetgroupinfo = NX4getgroupinfo; - fHandle->nxsameID = NX4sameID; - fHandle->nxinitgroupdir = NX4initgroupdir; - fHandle->nxinitattrdir = NX4initattrdir; - fHandle->nxprintlink = NX4printlink; + fHandle->nxclose=NX4close; + fHandle->nxreopen=NULL; + fHandle->nxflush=NX4flush; + fHandle->nxmakegroup=NX4makegroup; + fHandle->nxopengroup=NX4opengroup; + fHandle->nxclosegroup=NX4closegroup; + fHandle->nxmakedata64=NX4makedata64; + fHandle->nxcompmakedata64=NX4compmakedata64; + fHandle->nxcompress=NX4compress; + fHandle->nxopendata=NX4opendata; + fHandle->nxclosedata=NX4closedata; + fHandle->nxputdata=NX4putdata; + fHandle->nxputattr=NX4putattr; + fHandle->nxputslab64=NX4putslab64; + fHandle->nxgetdataID=NX4getdataID; + fHandle->nxmakelink=NX4makelink; + fHandle->nxmakenamedlink=NX4makenamedlink; + fHandle->nxgetdata=NX4getdata; + fHandle->nxgetinfo64=NX4getinfo64; + fHandle->nxgetnextentry=NX4getnextentry; + fHandle->nxgetslab64=NX4getslab64; + fHandle->nxgetnextattr=NX4getnextattr; + fHandle->nxgetattr=NX4getattr; + fHandle->nxgetattrinfo=NX4getattrinfo; + fHandle->nxgetgroupID=NX4getgroupID; + fHandle->nxgetgroupinfo=NX4getgroupinfo; + fHandle->nxsameID=NX4sameID; + fHandle->nxinitgroupdir=NX4initgroupdir; + fHandle->nxinitattrdir=NX4initattrdir; + fHandle->nxprintlink=NX4printlink; + fHandle->nxnativeexternallink=NULL; } + +#endif /*HDF4*/ diff --git a/napi4.h b/napi4.h index 3be8aac4..af354a57 100644 --- a/napi4.h +++ b/napi4.h @@ -1,3 +1,6 @@ +#ifndef NAPI4_H +#define NAPI4_H + #define NXSIGNATURE 959697 #include "mfhdf.h" @@ -7,54 +10,51 @@ * HDF4 interface */ -extern NXstatus NX4open(CONSTCHAR * filename, NXaccess access_method, - NXhandle * pHandle); -extern NXstatus NX4close(NXhandle * pHandle); -extern NXstatus NX4flush(NXhandle * pHandle); +extern NXstatus NX4open(CONSTCHAR *filename, NXaccess access_method, NXhandle* pHandle); +extern NXstatus NX4close(NXhandle* pHandle); +extern NXstatus NX4flush(NXhandle* pHandle); + +extern NXstatus NX4makegroup (NXhandle handle, CONSTCHAR* Vgroup, CONSTCHAR* NXclass); +extern NXstatus NX4opengroup (NXhandle handle, CONSTCHAR* Vgroup, CONSTCHAR* NXclass); +extern NXstatus NX4closegroup(NXhandle handle); + +extern NXstatus NX4makedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]); +extern NXstatus NX4compmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[]); +extern NXstatus NX4compress (NXhandle handle, int compr_type); +extern NXstatus NX4opendata (NXhandle handle, CONSTCHAR* label); -extern NXstatus NX4makegroup(NXhandle handle, CONSTCHAR * Vgroup, - CONSTCHAR * NXclass); -extern NXstatus NX4opengroup(NXhandle handle, CONSTCHAR * Vgroup, - CONSTCHAR * NXclass); -extern NXstatus NX4closegroup(NXhandle handle); - -extern NXstatus NX4makedata(NXhandle handle, CONSTCHAR * label, - int datatype, int rank, int dim[]); -extern NXstatus NX4compmakedata(NXhandle handle, CONSTCHAR * label, - int datatype, int rank, int dim[], - int comp_typ, int bufsize[]); -extern NXstatus NX4compress(NXhandle handle, int compr_type); -extern NXstatus NX4opendata(NXhandle handle, CONSTCHAR * label); - -extern NXstatus NX4closedata(NXhandle handle); - -extern NXstatus NX4getdata(NXhandle handle, void *data); -extern NXstatus NX4getslab(NXhandle handle, void *data, int start[], - int size[]); -extern NXstatus NX4getattr(NXhandle handle, char *name, void *data, - int *iDataLen, int *iType); - -extern NXstatus NX4putdata(NXhandle handle, void *data); -extern NXstatus NX4putslab(NXhandle handle, void *data, int start[], - int size[]); -extern NXstatus NX4putattr(NXhandle handle, CONSTCHAR * name, void *data, - int iDataLen, int iType); - -extern NXstatus NX4getinfo(NXhandle handle, int *rank, int dimension[], - int *datatype); -extern NXstatus NX4getgroupinfo(NXhandle handle, int *no_items, - NXname name, NXname nxclass); -extern NXstatus NX4initgroupdir(NXhandle handle); -extern NXstatus NX4getnextentry(NXhandle handle, NXname name, - NXname nxclass, int *datatype); -extern NXstatus NX4getattrinfo(NXhandle handle, int *no_items); -extern NXstatus NX4initattrdir(NXhandle handle); -extern NXstatus NX4getnextattr(NXhandle handle, NXname pName, int *iLength, - int *iType); - -extern NXstatus NX4getgroupID(NXhandle handle, NXlink * pLink); -extern NXstatus NX4getdataID(NXhandle handle, NXlink * pLink); -extern NXstatus NX4makelink(NXhandle handle, NXlink * pLink); -extern NXstatus NX4printlink(NXhandle handle, NXlink * pLink); +extern NXstatus NX4closedata(NXhandle handle); + +extern NXstatus NX4getdata(NXhandle handle, void* data); +extern NXstatus NX4getslab64(NXhandle handle, void* data, const int64_t start[], const int64_t size[]); +extern NXstatus NX4getattr(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); + +extern NXstatus NX4putdata(NXhandle handle, const void* data); +extern NXstatus NX4putslab64(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]); +extern NXstatus NX4putattr(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType); + +extern NXstatus NX4getinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype); +extern NXstatus NX4getgroupinfo(NXhandle handle, int* no_items, NXname name, NXname nxclass); +extern NXstatus NX4initgroupdir(NXhandle handle); +extern NXstatus NX4getnextentry(NXhandle handle, NXname name, NXname nxclass, int* datatype); +extern NXstatus NX4getattrinfo(NXhandle handle, int* no_items); +extern NXstatus NX4initattrdir(NXhandle handle); +extern NXstatus NX4getnextattr(NXhandle handle, NXname pName, int *iLength, int *iType); + +extern NXstatus NX4getgroupID(NXhandle handle, NXlink* pLink); +extern NXstatus NX4getdataID(NXhandle handle, NXlink* pLink); +extern NXstatus NX4makelink(NXhandle handle, NXlink* pLink); +extern NXstatus NX4printlink(NXhandle handle, NXlink* pLink); void NX4assignFunctions(pNexusFunction fHandle); + + +/* + * HDF changed from MAX_VAR_DIMS to H4_MAX_VAR_DIMS aronud 9/5/2007 + * to avoid potential conflicts with NetCDF-3 library + */ +#ifndef H4_MAX_VAR_DIMS +#define H4_MAX_VAR_DIMS MAX_VAR_DIMS +#endif + +#endif /* NAPI4_H */ diff --git a/napi5.c b/napi5.c index ad745414..810e1113 100644 --- a/napi5.c +++ b/napi5.c @@ -3,7 +3,7 @@ Application Program Interface (HDF5) Routines - Copyright (C) 1997-2006 Mark Koennecke, Przemek Klosowski + Copyright (C) 1997-2011 Mark Koennecke, Przemek Klosowski This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -19,9 +19,12 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see ----------------------------------------------------------------------------*/ + +#ifdef HDF5 + #include #include #include @@ -30,1900 +33,2269 @@ #include "napi.h" #include "napi5.h" -#define NX_UNKNOWN_GROUP "" /* for when no NX_class attr */ +#ifdef H5_VERSION_GE +#if !H5_VERSION_GE(1,8,0) +#error HDF5 Version must be 1.8.0 or higher +#endif +#endif -extern void *NXpData; +#ifdef _MSC_VER +#define snprintf _snprintf +#endif /* _MSC_VER */ -typedef struct __NexusFile5 { - struct iStack5 { - char irefn[1024]; - int iVref; - int iCurrentIDX; - } iStack5[NXMAXSTACK]; - struct iStack5 iAtt5; - int iFID; - int iCurrentG; - int iCurrentD; - int iCurrentS; - int iCurrentT; - int iCurrentA; - int iNX; - int iNXID; - int iStackPtr; - char *iCurrentLGG; - char *iCurrentLD; - char name_ref[1024]; - char name_tmp[1024]; - char iAccess[2]; -} NexusFile5, *pNexusFile5; +#define NX_UNKNOWN_GROUP "" /* for when no NX_class attr */ + +extern void *NXpData; + + typedef struct __NexusFile5 { + struct iStack5 { + char irefn[1024]; + int iVref; + hsize_t iCurrentIDX; + } iStack5[NXMAXSTACK]; + struct iStack5 iAtt5; + int iFID; + int iCurrentG; + int iCurrentD; + int iCurrentS; + int iCurrentT; + int iCurrentA; + int iNX; + int iNXID; + int iStackPtr; + char *iCurrentLGG; + char *iCurrentLD; + char name_ref[1024]; + char name_tmp[1024]; + char iAccess[2]; + } NexusFile5, *pNexusFile5; /* forward declaration of NX5closegroup in order to get rid of a nasty warning */ -NXstatus NX5closegroup(NXhandle fid); +NXstatus NX5closegroup (NXhandle fid); /*-------------------------------------------------------------------*/ -static void ignoreError(void *data, char *text) -{ -} + static pNexusFile5 NXI5assert(NXhandle fid) + { + pNexusFile5 pRes; + + assert(fid != NULL); + pRes = (pNexusFile5)fid; + assert(pRes->iNXID == NX5SIGNATURE); + return pRes; + } + /*--------------------------------------------------------------------*/ -static pNexusFile5 NXI5assert(NXhandle fid) -{ - pNexusFile5 pRes; - - assert(fid != NULL); - pRes = (pNexusFile5) fid; - assert(pRes->iNXID == NX5SIGNATURE); - return pRes; -} - + static void NXI5KillDir (pNexusFile5 self) + { + self->iStack5[self->iStackPtr].iCurrentIDX = 0; + } + /*--------------------------------------------------------------------*/ -static void NXI5KillDir(pNexusFile5 self) -{ - self->iStack5[self->iStackPtr].iCurrentIDX = 0; -} - - /*--------------------------------------------------------------------*/ - -static void NXI5KillAttDir(pNexusFile5 self) -{ - self->iAtt5.iCurrentIDX = 0; -} - + static void NXI5KillAttDir (pNexusFile5 self) + { + self->iAtt5.iCurrentIDX = 0; + } /*---------------------------------------------------------------------*/ -static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, - int pathBufferLen) -{ - int length; +static void buildCurrentPath(pNexusFile5 self, char *pathBuffer, + int pathBufferLen){ - memset(pathBuffer, 0, pathBufferLen); - if (self->iCurrentG != 0) { - strcpy(pathBuffer, "/"); - if (strlen(self->name_ref) + 1 < pathBufferLen) { + memset(pathBuffer,0,pathBufferLen); + if(self->iCurrentG != 0) { + strcpy(pathBuffer,"/"); + if(strlen(self->name_ref) + 1 < pathBufferLen){ strcat(pathBuffer, self->name_ref); } } - if (self->iCurrentD != 0) { - strcat(pathBuffer, "/"); - if (strlen(self->iCurrentLD) + strlen(pathBuffer) < pathBufferLen) { - strcat(pathBuffer, self->iCurrentLD); + if(self->iCurrentD != 0){ + strcat(pathBuffer,"/"); + if(strlen(self->iCurrentLD) + strlen(pathBuffer) < pathBufferLen){ + strcat(pathBuffer,self->iCurrentLD); } } } - /* ---------------------------------------------------------------------- + + Definition of NeXus API - Definition of NeXus API + ---------------------------------------------------------------------*/ - --------------------------------------------------------------------- */ - -NXstatus NX5open(CONSTCHAR * filename, NXaccess am, NXhandle * pHandle) + NXstatus NX5reopen(NXhandle pOrigHandle, NXhandle* pNewHandle) { - hid_t attr1, aid1, aid2, iVID; + pNexusFile5 pNew = NULL, pOrig = NULL; + *pNewHandle = NULL; + pOrig = (pNexusFile5)pOrigHandle; + pNew = (pNexusFile5) malloc (sizeof (NexusFile5)); + if (!pNew) { + NXReportError ("ERROR: no memory to create File datastructure"); + return NX_ERROR; + } + memset (pNew, 0, sizeof (NexusFile5)); + pNew->iFID = H5Freopen (pOrig->iFID); + if (pNew->iFID <= 0) { + NXReportError ("cannot clone file"); + free (pNew); + return NX_ERROR; + } + strcpy(pNew->iAccess, pOrig->iAccess); + pNew->iNXID = NX5SIGNATURE; + pNew->iStack5[0].iVref = 0; /* root! */ + *pNewHandle = (NXhandle)pNew; + return NX_OK; +} + +NXstatus NX5open(CONSTCHAR *filename, NXaccess am, + NXhandle* pHandle) + { + hid_t attr1,aid1, aid2, iVID; pNexusFile5 pNew = NULL; char pBuffer[512]; char *time_buffer = NULL; char version_nr[10]; - int iRet; - unsigned int vers_major, vers_minor, vers_release, am1; - hid_t fapl = -1; + unsigned int vers_major, vers_minor, vers_release, am1 ; + hid_t fapl = -1; int mdc_nelmts; -#ifdef H5_WANT_H5_V1_4_COMPAT - int rdcc_nelmts; -#else size_t rdcc_nelmts; -#endif size_t rdcc_nbytes; double rdcc_w0; - - /* turn off the automatic HDF error handling */ - H5Eset_auto(NULL, NULL); -#ifdef USE_FTIME - struct timeb timeb_struct; -#endif + unsigned hdf5_majnum, hdf5_minnum, hdf5_relnum; *pHandle = NULL; - pNew = (pNexusFile5) malloc(sizeof(NexusFile5)); - if (!pNew) { - NXIReportError(NXpData, - "ERROR: no memory to create File datastructure"); - return NX_ERROR; + if (H5get_libversion(&hdf5_majnum, &hdf5_minnum, &hdf5_relnum) < 0) + { + NXReportError("ERROR: cannot determine HDF5 library version"); + return NX_ERROR; } - memset(pNew, 0, sizeof(NexusFile5)); + if (hdf5_majnum == 1 && hdf5_minnum < 8) + { + NXReportError("ERROR: HDF5 library 1.8.0 or higher required"); + return NX_ERROR; + } + + /* mask of any options for now */ + am = (NXaccess)(am & NXACCMASK_REMOVEFLAGS); + + /* turn off the automatic HDF error handling */ + H5Eset_auto(H5E_DEFAULT, NULL, NULL); +#ifdef USE_FTIME + struct timeb timeb_struct; +#endif - /* start HDF5 interface */ - if (am == NXACC_CREATE5) { - fapl = H5Pcreate(H5P_FILE_ACCESS); - iRet = - H5Pget_cache(fapl, &mdc_nelmts, &rdcc_nelmts, &rdcc_nbytes, - &rdcc_w0); - rdcc_nbytes = (size_t) nx_cacheSize; - iRet = - H5Pset_cache(fapl, mdc_nelmts, rdcc_nelmts, rdcc_nbytes, rdcc_w0); - /* - setting the close degree is absolutely necessary in HDF5 - versions > 1.6. If you use a lessere version and the compiler - complains, comment it out but keep this in mind. - */ - H5Pset_fclose_degree(fapl, H5F_CLOSE_STRONG); - am1 = H5F_ACC_TRUNC; - pNew->iFID = H5Fcreate(filename, am1, H5P_DEFAULT, fapl); - } else { - if (am == NXACC_READ) { - am1 = H5F_ACC_RDONLY; - } else { - am1 = H5F_ACC_RDWR; + pNew = (pNexusFile5) malloc (sizeof (NexusFile5)); + if (!pNew) { + NXReportError("ERROR: not enough memory to create file structure"); + return NX_ERROR; + } + memset (pNew, 0, sizeof (NexusFile5)); + + + /* start HDF5 interface */ + if (am == NXACC_CREATE5) { + fapl = H5Pcreate(H5P_FILE_ACCESS); + H5Pget_cache(fapl,&mdc_nelmts,&rdcc_nelmts,&rdcc_nbytes,&rdcc_w0); + rdcc_nbytes=(size_t)nx_cacheSize; + H5Pset_cache(fapl,mdc_nelmts,rdcc_nelmts,rdcc_nbytes,rdcc_w0); + H5Pset_fclose_degree(fapl,H5F_CLOSE_STRONG); + am1 = H5F_ACC_TRUNC; + pNew->iFID = H5Fcreate (filename, am1, H5P_DEFAULT, fapl); + } else { + if (am == NXACC_READ) { + am1 = H5F_ACC_RDONLY; + } else { + am1 = H5F_ACC_RDWR; + } + fapl = H5Pcreate(H5P_FILE_ACCESS); + H5Pset_fclose_degree(fapl,H5F_CLOSE_STRONG); + pNew->iFID = H5Fopen (filename, am1, fapl); + } + if(fapl != -1) { + H5Pclose(fapl); + } + if (pNew->iFID <= 0) { + sprintf (pBuffer, "ERROR: cannot open file: %s", filename); + NXReportError( pBuffer); + free (pNew); + return NX_ERROR; } - fapl = H5Pcreate(H5P_FILE_ACCESS); - H5Pset_fclose_degree(fapl, H5F_CLOSE_STRONG); - pNew->iFID = H5Fopen(filename, am1, fapl); - } - if (pNew->iFID <= 0) { - sprintf(pBuffer, "ERROR: cannot open file: %s", filename); - NXIReportError(NXpData, pBuffer); - free(pNew); - return NX_ERROR; - } - if (fapl != -1) { - H5Pclose(fapl); - } /* * need to create global attributes file_name file_time NeXus_version * at some point for new files */ - if (am1 != H5F_ACC_RDONLY) { - iVID = H5Gopen(pNew->iFID, "/"); - aid2 = H5Screate(H5S_SCALAR); - aid1 = H5Tcopy(H5T_C_S1); - H5Tset_size(aid1, strlen(NEXUS_VERSION)); - if (am1 == H5F_ACC_RDWR) { - H5Adelete(iVID, "NeXus_version"); + if (am1 != H5F_ACC_RDONLY) + { + iVID = H5Gopen(pNew->iFID,"/", H5P_DEFAULT); + aid2 = H5Screate(H5S_SCALAR); + aid1 = H5Tcopy(H5T_C_S1); + H5Tset_size(aid1, strlen(NEXUS_VERSION)); + if (am1 == H5F_ACC_RDWR) + { + H5Adelete(iVID, "NeXus_version"); + } + attr1= H5Acreate(iVID, "NeXus_version", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); + if (attr1<0) + { + NXReportError( + "ERROR: failed to store NeXus_version attribute "); + return NX_ERROR; + } + if (H5Awrite(attr1, aid1,NEXUS_VERSION)<0) + { + NXReportError( + "ERROR: failed to store NeXus_version attribute "); + return NX_ERROR; + } + /* Close attribute dataspace */ + H5Tclose(aid1); + H5Sclose(aid2); + /* Close attribute */ + H5Aclose(attr1); + H5Gclose(iVID); } - attr1 = H5Acreate(iVID, "NeXus_version", aid1, aid2, H5P_DEFAULT); - if (attr1 < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store NeXus_version attribute "); - return NX_ERROR; + if (am1 == H5F_ACC_TRUNC) + { + iVID = H5Gopen(pNew->iFID,"/", H5P_DEFAULT); + aid2 = H5Screate(H5S_SCALAR); + aid1 = H5Tcopy(H5T_C_S1); + H5Tset_size(aid1, strlen(filename)); + attr1= H5Acreate(iVID, "file_name", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); + if (attr1 < 0) + { + NXReportError( + "ERROR: failed to store file_name attribute "); + return NX_ERROR; + } + if (H5Awrite(attr1, aid1, (char*)filename) < 0) + { + NXReportError( + "ERROR: failed to store file_name attribute "); + return NX_ERROR; + } + H5Tclose(aid1); + H5Sclose(aid2); + H5Aclose(attr1); + /* ------- library version ------*/ + H5get_libversion(&vers_major, &vers_minor, &vers_release); + sprintf (version_nr, "%d.%d.%d", vers_major,vers_minor,vers_release); + aid2=H5Screate(H5S_SCALAR); + aid1 = H5Tcopy(H5T_C_S1); + H5Tset_size(aid1, strlen(version_nr)); + attr1= H5Acreate(iVID, "HDF5_Version", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); + if (attr1 < 0) + { + NXReportError( + "ERROR: failed to store file_name attribute "); + return NX_ERROR; + } + if (H5Awrite(attr1, aid1, (char*)version_nr) < 0) + { + NXReportError( + "ERROR: failed to store file_name attribute "); + return NX_ERROR; + } + H5Tclose(aid1); + H5Sclose(aid2); + H5Aclose(attr1); + /*----------- file time */ + time_buffer = NXIformatNeXusTime(); + if(time_buffer != NULL){ + aid2=H5Screate(H5S_SCALAR); + aid1 = H5Tcopy(H5T_C_S1); + H5Tset_size(aid1, strlen(time_buffer)); + attr1=H5Acreate(iVID, "file_time", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); + if (attr1 < 0) + { + NXReportError( + "ERROR: failed to store file_time attribute "); + free(time_buffer); + return NX_ERROR; + } + if (H5Awrite(attr1, aid1, time_buffer) < 0) + { + NXReportError( + "ERROR: failed to store file_time attribute "); + free(time_buffer); + return NX_ERROR; + } + /* Close attribute dataspace */ + H5Tclose(aid1); + H5Sclose(aid2); + /* Close attribute */ + H5Aclose(attr1); + free(time_buffer); + } + H5Gclose(iVID); } - if (H5Awrite(attr1, aid1, NEXUS_VERSION) < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store NeXus_version attribute "); - return NX_ERROR; + /* Set HDFgroup access mode */ + if (am1 == H5F_ACC_RDONLY) { + strcpy(pNew->iAccess,"r"); + } else { + strcpy(pNew->iAccess,"w"); } - /* Close attribute dataspace */ - iRet = H5Tclose(aid1); - iRet = H5Sclose(aid2); - /* Close attribute */ - iRet = H5Aclose(attr1); - H5Gclose(iVID); + pNew->iNXID = NX5SIGNATURE; + pNew->iStack5[0].iVref = 0; /* root! */ + *pHandle = (NXhandle)pNew; + return NX_OK; } - if (am1 == H5F_ACC_TRUNC) { - iVID = H5Gopen(pNew->iFID, "/"); - aid2 = H5Screate(H5S_SCALAR); - aid1 = H5Tcopy(H5T_C_S1); - H5Tset_size(aid1, strlen(filename)); - attr1 = H5Acreate(iVID, "file_name", aid1, aid2, H5P_DEFAULT); - if (attr1 < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store file_name attribute "); - return NX_ERROR; - } - if (H5Awrite(attr1, aid1, (char *) filename) < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store file_name attribute "); - return NX_ERROR; - } - iRet = H5Tclose(aid1); - iRet = H5Sclose(aid2); - iRet = H5Aclose(attr1); - /* ------- library version ------ */ - H5get_libversion(&vers_major, &vers_minor, &vers_release); - sprintf(version_nr, "%d.%d.%d", vers_major, vers_minor, vers_release); - aid2 = H5Screate(H5S_SCALAR); - aid1 = H5Tcopy(H5T_C_S1); - H5Tset_size(aid1, strlen(version_nr)); - attr1 = H5Acreate(iVID, "HDF5_Version", aid1, aid2, H5P_DEFAULT); - if (attr1 < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store file_name attribute "); - return NX_ERROR; - } - if (H5Awrite(attr1, aid1, (char *) version_nr) < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store file_name attribute "); - return NX_ERROR; - } - iRet = H5Tclose(aid1); - iRet = H5Sclose(aid2); - iRet = H5Aclose(attr1); - /*----------- file time */ - time_buffer = NXIformatNeXusTime(); - if (time_buffer != NULL) { - aid2 = H5Screate(H5S_SCALAR); - aid1 = H5Tcopy(H5T_C_S1); - H5Tset_size(aid1, strlen(time_buffer)); - attr1 = H5Acreate(iVID, "file_time", aid1, aid2, H5P_DEFAULT); - if (attr1 < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store file_time attribute "); - free(time_buffer); - return NX_ERROR; - } - if (H5Awrite(attr1, aid1, time_buffer) < 0) { - NXIReportError(NXpData, - "ERROR: HDF failed to store file_time attribute "); - free(time_buffer); - return NX_ERROR; - } - /* Close attribute dataspace */ - iRet = H5Tclose(aid1); - iRet = H5Sclose(aid2); - /* Close attribute */ - iRet = H5Aclose(attr1); - free(time_buffer); - } - H5Gclose(iVID); - } - /* Set HDFgroup access mode */ - if (am1 == H5F_ACC_RDONLY) { - strcpy(pNew->iAccess, "r"); - } else { - strcpy(pNew->iAccess, "w"); - } - pNew->iNXID = NX5SIGNATURE; - pNew->iStack5[0].iVref = 0; /* root! */ - *pHandle = (NXhandle) pNew; - return NX_OK; -} - + /* ------------------------------------------------------------------------- */ -NXstatus NX5close(NXhandle * fid) -{ - pNexusFile5 pFile = NULL; - int iRet; + NXstatus NX5close (NXhandle* fid) + { + pNexusFile5 pFile = NULL; + herr_t iRet; + + pFile=NXI5assert(*fid); - pFile = NXI5assert(*fid); + iRet=0; + /* + printf("HDF5 object count before close: %d\n", + H5Fget_obj_count(pFile->iFID,H5F_OBJ_ALL)); + */ + iRet = H5Fclose(pFile->iFID); - iRet = 0; - /* - printf("HDF5 object count before close: %d\n", - H5Fget_obj_count(pFile->iFID,H5F_OBJ_ALL)); - */ - iRet = H5Fclose(pFile->iFID); + /* + leave this here: it helps in debugging leakage problems + printf("HDF5 object count after close: %d\n", + H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_ALL)); + printf("HDF5 dataset count after close: %d\n", + H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_DATASET)); + printf("HDF5 group count after close: %d\n", + H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_GROUP)); + printf("HDF5 datatype count after close: %d\n", + H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_DATATYPE)); + printf("HDF5 attribute count after close: %d\n", + H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_ATTR)); + */ - /* - leave this here: it helps in debugging leakage problems - printf("HDF5 object count after close: %d\n", - H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_ALL)); - printf("HDF5 dataset count after close: %d\n", - H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_DATASET)); - printf("HDF5 group count after close: %d\n", - H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_GROUP)); - printf("HDF5 datatype count after close: %d\n", - H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_DATATYPE)); - printf("HDF5 attribute count after close: %d\n", - H5Fget_obj_count(H5F_OBJ_ALL,H5F_OBJ_ATTR)); - */ - - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot close HDF file"); - } - /* release memory */ - NXI5KillDir(pFile); - if (pFile->iCurrentLGG != NULL) { - free(pFile->iCurrentLGG); - } - if (pFile->iCurrentLD != NULL) { - free(pFile->iCurrentLD); - } - free(pFile); - *fid = NULL; - H5garbage_collect(); - return NX_OK; -} - - /*-----------------------------------------------------------------------*/ - -NXstatus NX5makegroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass) -{ - pNexusFile5 pFile; - hid_t iRet, iVID; - hid_t attr1, aid1, aid2; - char pBuffer[1024] = ""; - - pFile = NXI5assert(fid); - /* create and configure the group */ - if (pFile->iCurrentG == 0) { - iRet = H5Gcreate(pFile->iFID, (const char *) name, 0); - snprintf(pBuffer, 1023, "/%s", name); - } else { - snprintf(pBuffer, 1023, "/%s/%s", pFile->name_ref, name); - iRet = H5Gcreate(pFile->iFID, (const char *) pBuffer, 0); - } - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF could not create Group"); - return NX_ERROR; - } - iVID = iRet; - strncpy(pFile->name_ref, pBuffer, 1023); - aid2 = H5Screate(H5S_SCALAR); - aid1 = H5Tcopy(H5T_C_S1); - H5Tset_size(aid1, strlen(nxclass)); - attr1 = H5Acreate(iVID, "NX_class", aid1, aid2, H5P_DEFAULT); - if (attr1 < 0) { - NXIReportError(NXpData, "ERROR: HDF failed to store class name!"); - return NX_ERROR; - } - if (H5Awrite(attr1, aid1, (char *) nxclass) < 0) { - NXIReportError(NXpData, "ERROR: HDF failed to store class name!"); - return NX_ERROR; - } - /* close group */ - iRet = H5Sclose(aid2); - iRet = H5Tclose(aid1); - iRet = H5Aclose(attr1); - iRet = H5Gclose(iVID); - return NX_OK; -} - - /*------------------------------------------------------------------------*/ - -herr_t attr_check(hid_t loc_id, const char *member_name, void *opdata) -{ - char attr_name[8 + 1]; /* need to leave space for \0 as well */ - - strcpy(attr_name, "NX_class"); - return strstr(member_name, attr_name) ? 1 : 0; -} - - /*------------------------------------------------------------------------*/ -NXstatus NX5opengroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass) -{ - - pNexusFile5 pFile; - hid_t iRet, attr1, atype; - char pBuffer[1024]; - char data[128]; - - pFile = NXI5assert(fid); - if (pFile->iCurrentG == 0) { - strcpy(pBuffer, name); - } else { - sprintf(pBuffer, "%s/%s", pFile->name_tmp, name); - } - iRet = H5Gopen(pFile->iFID, (const char *) pBuffer); - if (iRet < 0) { - sprintf(pBuffer, "ERROR: Group %s does not exist!", pFile->name_tmp); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - pFile->iCurrentG = iRet; - strcpy(pFile->name_tmp, pBuffer); - strcpy(pFile->name_ref, pBuffer); - - if ((nxclass != NULL) && (strcmp(nxclass, NX_UNKNOWN_GROUP) != 0)) { - /* check group attribute */ - iRet = H5Aiterate(pFile->iCurrentG, NULL, attr_check, NULL); if (iRet < 0) { - NXIReportError(NXpData, "ERROR iterating through group!"); - return NX_ERROR; - } else if (iRet == 1) { - /* group attribute was found */ - } else { - /* no group attribute available */ - NXIReportError(NXpData, "No group attribute available"); - return NX_ERROR; + NXReportError( "ERROR: cannot close HDF file"); } - /* check contents of group attribute */ - attr1 = H5Aopen_name(pFile->iCurrentG, "NX_class"); - if (attr1 < 0) { - NXIReportError(NXpData, "Error opening NX_class group attribute!"); - return NX_ERROR; + /* release memory */ + NXI5KillDir (pFile); + if(pFile->iCurrentLGG != NULL){ + free(pFile->iCurrentLGG); } - atype = H5Tcopy(H5T_C_S1); - H5Tset_size(atype, 128); - iRet = H5Aread(attr1, atype, data); - if (strcmp(data, nxclass) == 0) { - /* test OK */ - } else { - NXIReportError(NXpData, "Group class is not identical!"); - iRet = H5Tclose(atype); - iRet = H5Aclose(attr1); - return NX_ERROR; + if(pFile->iCurrentLD != NULL){ + free(pFile->iCurrentLD); } - iRet = H5Tclose(atype); - iRet = H5Aclose(attr1); + free (pFile); + *fid = NULL; + H5garbage_collect(); + return NX_OK; } - /* maintain stack */ - pFile->iStackPtr++; - pFile->iStack5[pFile->iStackPtr].iVref = pFile->iCurrentG; - strcpy(pFile->iStack5[pFile->iStackPtr].irefn, name); - pFile->iAtt5.iCurrentIDX = 0; - pFile->iCurrentD = 0; - if (pFile->iCurrentLGG != NULL) { - free(pFile->iCurrentLGG); + /*-----------------------------------------------------------------------*/ + + NXstatus NX5makegroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) + { + pNexusFile5 pFile; + herr_t iRet; + hid_t iVID; + hid_t attr1,aid1, aid2; + char pBuffer[1024] = ""; + + pFile = NXI5assert (fid); + /* create and configure the group */ + if (pFile->iCurrentG==0) { + snprintf(pBuffer,1023,"/%s",name); + } else { + snprintf(pBuffer,1023,"/%s/%s",pFile->name_ref,name); + } + iRet = H5Gcreate(pFile->iFID,(const char*)pBuffer, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + if (iRet < 0) { + NXReportError( "ERROR: could not create Group"); + return NX_ERROR; + } + iVID = iRet; + aid2 = H5Screate(H5S_SCALAR); + aid1 = H5Tcopy(H5T_C_S1); + H5Tset_size(aid1, strlen(nxclass)); + attr1= H5Acreate(iVID, "NX_class", aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); + if (attr1 < 0) { + NXReportError( "ERROR: failed to store class name"); + return NX_ERROR; + } + if (H5Awrite(attr1, aid1, (char*)nxclass) < 0) { + NXReportError( "ERROR: failed to store class name"); + return NX_ERROR; + } + /* close group */ + iRet=H5Sclose(aid2); + iRet=H5Tclose(aid1); + iRet=H5Aclose(attr1); + iRet=H5Gclose(iVID); + return NX_OK; + } + + /*------------------------------------------------------------------------*/ + + herr_t attr_check (hid_t loc_id, const char *member_name, const H5A_info_t *unused, void *opdata) + { + char attr_name[8+1]; /* need to leave space for \0 as well */ + + strcpy(attr_name,"NX_class"); + return strstr(member_name, attr_name) ? 1 : 0; + } + /*------------------------------------------------------------------------*/ + NXstatus NX5opengroup(NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) + { + + pNexusFile5 pFile; + hid_t attr1, atype; + herr_t iRet; + char pBuffer[1024]; + char data[128]; + + pFile = NXI5assert (fid); + if (pFile->iCurrentG == 0) { + strcpy(pBuffer,name); + } else { + sprintf(pBuffer,"%s/%s",pFile->name_tmp,name); + } + iRet = H5Gopen(pFile->iFID, (const char *)pBuffer, H5P_DEFAULT); + if (iRet < 0) { + sprintf (pBuffer, "ERROR: group %s does not exist", pFile->name_tmp); + NXReportError( pBuffer); + return NX_ERROR; + } + pFile->iCurrentG = iRet; + strcpy(pFile->name_tmp,pBuffer); + strcpy(pFile->name_ref,pBuffer); + + if ((nxclass != NULL) && (strcmp(nxclass, NX_UNKNOWN_GROUP) != 0)) { + /* check group attribute */ + iRet=H5Aiterate(pFile->iCurrentG,H5_INDEX_CRT_ORDER,H5_ITER_INC,0,attr_check,NULL); + if (iRet < 0) { + NXReportError( "ERROR: iterating through attribute list"); + return NX_ERROR; + } else if (iRet == 1) { + /* group attribute was found */ + } else { + /* no group attribute available */ + NXReportError( "ERROR: no group attribute available"); + return NX_ERROR; + } + /* check contents of group attribute */ + attr1 = H5Aopen_by_name(pFile->iCurrentG, ".", "NX_class", H5P_DEFAULT, H5P_DEFAULT); + if (attr1 < 0) { + NXReportError( "ERROR: opening NX_class group attribute"); + return NX_ERROR; + } + atype=H5Tcopy(H5T_C_S1); + H5Tset_size(atype,sizeof(data)); + iRet = H5Aread(attr1, atype, data); + if (strcmp(data, nxclass) == 0) { + /* test OK */ + } else { + NXReportError( "ERROR: group class is not identical"); + iRet = H5Tclose(atype); + iRet = H5Aclose(attr1); + return NX_ERROR; + } + iRet = H5Tclose(atype); + iRet = H5Aclose(attr1); + } + + /* maintain stack */ + pFile->iStackPtr++; + pFile->iStack5[pFile->iStackPtr].iVref=pFile->iCurrentG; + strcpy(pFile->iStack5[pFile->iStackPtr].irefn,name); + pFile->iAtt5.iCurrentIDX=0; + pFile->iCurrentD = 0; + if(pFile->iCurrentLGG != NULL){ + free(pFile->iCurrentLGG); + } + pFile->iCurrentLGG = strdup(name); + NXI5KillDir (pFile); + return NX_OK; } - pFile->iCurrentLGG = strdup(name); - NXI5KillDir(pFile); - return NX_OK; -} /* ------------------------------------------------------------------- */ -NXstatus NX5closegroup(NXhandle fid) -{ - pNexusFile5 pFile; - int i, ii; - char *uname = NULL; - char *u1name = NULL; - - pFile = NXI5assert(fid); - /* first catch the trivial case: we are at root and cannot get - deeper into a negative directory hierarchy (anti-directory) - */ - if (pFile->iCurrentG == 0) { - NXI5KillDir(pFile); - return NX_OK; - } else { - /* close the current group and decrement name_ref */ - H5Gclose(pFile->iCurrentG); - i = 0; - i = strlen(pFile->iStack5[pFile->iStackPtr].irefn); - ii = strlen(pFile->name_ref); - if (pFile->iStackPtr > 1) { - ii = ii - i - 1; - } else { - ii = ii - i; - } - if (ii > 0) { - uname = strdup(pFile->name_ref); - u1name = (char *) malloc((ii + 1) * sizeof(char)); - memset(u1name, 0, ii); - for (i = 0; i < ii; i++) { - *(u1name + i) = *(uname + i); + NXstatus NX5closegroup (NXhandle fid) + { + pNexusFile5 pFile; + int i,ii; + char *uname = NULL; + char *u1name = NULL; + + pFile = NXI5assert (fid); + /* first catch the trivial case: we are at root and cannot get + deeper into a negative directory hierarchy (anti-directory) + */ + if (pFile->iCurrentG == 0) { + NXI5KillDir (pFile); + return NX_OK; + } else { + /* close the current group and decrement name_ref */ + H5Gclose (pFile->iCurrentG); + i = 0; + i = strlen(pFile->iStack5[pFile->iStackPtr].irefn); + ii = strlen(pFile->name_ref); + if (pFile->iStackPtr>1) { + ii=ii-i-1; + } else { + ii=ii-i; + } + if (ii>0) { + uname = strdup(pFile->name_ref); + u1name = (char*) malloc((ii+1)*sizeof(char)); + memset(u1name,0,ii); + for (i=0; iname_ref,u1name); + strcpy(pFile->name_tmp,u1name); + free(uname); + free(u1name); + } else { + strcpy(pFile->name_ref,""); + strcpy(pFile->name_tmp,""); + } + NXI5KillDir (pFile); + pFile->iStackPtr--; + if (pFile->iStackPtr>0) { + pFile->iCurrentG=pFile->iStack5[pFile->iStackPtr].iVref; + } else { + pFile->iCurrentG=0; } - *(u1name + i) = '\0'; - /* - strncpy(u1name, uname, ii); - */ - strcpy(pFile->name_ref, u1name); - strcpy(pFile->name_tmp, u1name); - free(uname); - free(u1name); - } else { - strcpy(pFile->name_ref, ""); - strcpy(pFile->name_tmp, ""); - } - NXI5KillDir(pFile); - pFile->iStackPtr--; - if (pFile->iStackPtr > 0) { - pFile->iCurrentG = pFile->iStack5[pFile->iStackPtr].iVref; - } else { - pFile->iCurrentG = 0; } + return NX_OK; } - return NX_OK; -} - /*-----------------------------------------------------------------------*/ -static int nxToHDF5Type(int datatype) +static hid_t nxToHDF5Type(int datatype) { - int type; - if (datatype == NX_CHAR) { - type = H5T_C_S1; - } else if (datatype == NX_INT8) { - type = H5T_NATIVE_CHAR; - } else if (datatype == NX_UINT8) { - type = H5T_NATIVE_UCHAR; - } else if (datatype == NX_INT16) { - type = H5T_NATIVE_SHORT; - } else if (datatype == NX_UINT16) { - type = H5T_NATIVE_USHORT; - } else if (datatype == NX_INT32) { - type = H5T_NATIVE_INT; - } else if (datatype == NX_UINT32) { - type = H5T_NATIVE_UINT; - } else if (datatype == NX_INT64) { - type = H5T_NATIVE_INT64; - } else if (datatype == NX_UINT64) { - type = H5T_NATIVE_UINT64; - } else if (datatype == NX_FLOAT32) { - type = H5T_NATIVE_FLOAT; - } else if (datatype == NX_FLOAT64) { - type = H5T_NATIVE_DOUBLE; - } else { - NXIReportError(NXpData, "ERROR: nxToHDF5Type: unknown type"); - type = -1; - } - return type; + hid_t type; + if (datatype == NX_CHAR) { + type=H5T_C_S1; + } else if (datatype == NX_INT8) { + type=H5T_NATIVE_CHAR; + } else if (datatype == NX_UINT8) { + type=H5T_NATIVE_UCHAR; + } else if (datatype == NX_INT16) { + type=H5T_NATIVE_SHORT; + } else if (datatype == NX_UINT16) { + type=H5T_NATIVE_USHORT; + } else if (datatype == NX_INT32) { + type=H5T_NATIVE_INT; + } else if (datatype == NX_UINT32) { + type=H5T_NATIVE_UINT; + } else if (datatype == NX_INT64) { + type = H5T_NATIVE_INT64; + } else if (datatype == NX_UINT64) { + type = H5T_NATIVE_UINT64; + } else if (datatype == NX_FLOAT32) { + type=H5T_NATIVE_FLOAT; + } else if (datatype == NX_FLOAT64) { + type=H5T_NATIVE_DOUBLE; + } else { + NXReportError( "ERROR: nxToHDF5Type: unknown type"); + type = -1; + } + return type; } - + /* --------------------------------------------------------------------- */ -NXstatus NX5compmakedata(NXhandle fid, CONSTCHAR * name, - int datatype, - int rank, int dimensions[], - int compress_type, int chunk_size[]) -{ - hid_t datatype1, dataspace, iNew, iRet; - hid_t type, cparms = -1; - pNexusFile5 pFile; - char pBuffer[256]; - int i, byte_zahl = 0; - hsize_t chunkdims[H5S_MAX_RANK]; - hsize_t mydim[H5S_MAX_RANK], mydim1[H5S_MAX_RANK]; - hsize_t size[H5S_MAX_RANK]; - hsize_t maxdims[H5S_MAX_RANK]; + NXstatus NX5compmakedata64 (NXhandle fid, CONSTCHAR *name, + int datatype, + int rank, int64_t dimensions[], + int compress_type, int64_t chunk_size[]) + { + hid_t datatype1, dataspace, iNew; + herr_t iRet; + hid_t type, cparms = -1; + pNexusFile5 pFile; + char pBuffer[256]; + int i, byte_zahl = 0; + hsize_t chunkdims[H5S_MAX_RANK]; + hsize_t mydim[H5S_MAX_RANK], mydim1[H5S_MAX_RANK]; + hsize_t size[H5S_MAX_RANK]; + hsize_t maxdims[H5S_MAX_RANK]; + int compress_level; + int unlimiteddim = 0; - pFile = NXI5assert(fid); - - for (i = 0; i < rank; i++) { - chunkdims[i] = chunk_size[i]; - mydim[i] = dimensions[i]; - maxdims[i] = dimensions[i]; - size[i] = dimensions[i]; - } - - type = nxToHDF5Type(datatype); - - if (rank <= 0) { - sprintf(pBuffer, "ERROR: invalid rank specified %s", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - /* - Check dimensions for consistency. The first dimension may be -1 - thus denoting an unlimited dimension. - */ - for (i = 1; i < rank; i++) { - if (dimensions[i] <= 0) { - sprintf(pBuffer, - "ERROR: invalid dimension %d, value %d given for Dataset %s", - i, dimensions[i], name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - } - if (datatype == NX_CHAR) { -/* - * This assumes string lenght is in the last dimensions and - * the logic must be the same as used in NX5getslab and NX5getinfo - * - * search for tests on H5T_STRING - */ - byte_zahl = dimensions[rank - 1]; - for (i = 0; i < rank; i++) { - mydim1[i] = dimensions[i]; - } - mydim1[rank - 1] = 1; - if (dimensions[rank - 1] > 1) { - mydim[rank - 1] = maxdims[rank - 1] = size[rank - 1] = 1; - } - if (chunkdims[rank - 1] > 1) { - chunkdims[rank - 1] = 1; - } - if (dimensions[0] == NX_UNLIMITED) { - mydim1[0] = 1; - maxdims[0] = H5S_UNLIMITED; - } - dataspace = H5Screate_simple(rank, mydim1, maxdims); - } else { - if (dimensions[0] == NX_UNLIMITED) { - mydim[0] = 1; - maxdims[0] = H5S_UNLIMITED; - dataspace = H5Screate_simple(rank, mydim, maxdims); - } else { - /* dataset creation */ - dataspace = H5Screate_simple(rank, mydim, NULL); - } - } - datatype1 = H5Tcopy(type); - if (datatype == NX_CHAR) { - H5Tset_size(datatype1, byte_zahl); -/* H5Tset_strpad(H5T_STR_SPACEPAD); */ - } - if (compress_type == NX_COMP_LZW) { - cparms = H5Pcreate(H5P_DATASET_CREATE); - iNew = H5Pset_chunk(cparms, rank, chunkdims); - if (iNew < 0) { - NXIReportError(NXpData, "ERROR: Size of chunks could not be set!"); - return NX_ERROR; - } - H5Pset_deflate(cparms, 6); - iRet = H5Dcreate(pFile->iCurrentG, (char *) name, datatype1, - dataspace, cparms); - } else if (compress_type == NX_COMP_NONE) { - if (dimensions[0] == NX_UNLIMITED) { - cparms = H5Pcreate(H5P_DATASET_CREATE); - iNew = H5Pset_chunk(cparms, rank, chunkdims); - if (iNew < 0) { - NXIReportError(NXpData, "ERROR: Size of chunks could not be set!"); - return NX_ERROR; + pFile = NXI5assert (fid); + if (pFile->iCurrentG <= 0) { + sprintf(pBuffer, "ERROR: no group open for makedata on %s", name); + NXReportError( pBuffer); + return NX_ERROR; } - iRet = H5Dcreate(pFile->iCurrentG, (char *) name, datatype1, - dataspace, cparms); - } else { - iRet = H5Dcreate(pFile->iCurrentG, (char *) name, datatype1, - dataspace, H5P_DEFAULT); - } - } else { - NXIReportError(NXpData, - "HDF5 doesn't support selected compression method! Dataset was saved without compression"); - iRet = H5Dcreate(pFile->iCurrentG, (char *) name, datatype1, - dataspace, H5P_DEFAULT); + + if (rank <= 0) { + sprintf (pBuffer, "ERROR: invalid rank specified %s", name); + NXReportError( pBuffer); + return NX_ERROR; + } + + type = nxToHDF5Type(datatype); + + /* + Check dimensions for consistency. Dimension may be -1 + thus denoting an unlimited dimension. + */ + for (i = 0; i < rank; i++) + { + chunkdims[i] = chunk_size[i]; + mydim[i] = dimensions[i]; + maxdims[i] = dimensions[i]; + size[i] = dimensions[i]; + if (dimensions[i] <= 0) + { + mydim[i] = 1; + maxdims[i] = H5S_UNLIMITED; + size[i] = 1; + unlimiteddim = 1; + } else { + mydim[i] = dimensions[i]; + maxdims[i] = dimensions[i]; + size[i] = dimensions[i]; + } + } + + if (datatype == NX_CHAR) + { + /* + * This assumes string lenght is in the last dimensions and + * the logic must be the same as used in NX5getslab and NX5getinfo + * + * search for tests on H5T_STRING + */ + byte_zahl=mydim[rank-1]; + for(i = 0; i < rank; i++) + { + mydim1[i] = mydim[i]; + if (dimensions[i] <= 0) + { + mydim1[0] = 1; + maxdims[0] = H5S_UNLIMITED; + } + + } + mydim1[rank-1] = 1; + if (mydim[rank-1] > 1) + { + mydim[rank-1] = maxdims[rank-1] = size[rank-1] = 1; + } + if (chunkdims[rank-1] > 1) + { + chunkdims[rank-1] = 1; + } + dataspace=H5Screate_simple(rank,mydim1,maxdims); + } + else + { + if (unlimiteddim) + { + dataspace=H5Screate_simple(rank, mydim, maxdims); + } + else + { + /* dataset creation */ + dataspace=H5Screate_simple(rank, mydim, NULL); + } + } + datatype1=H5Tcopy(type); + if (datatype == NX_CHAR) + { + H5Tset_size(datatype1, byte_zahl); + /* H5Tset_strpad(H5T_STR_SPACEPAD); */ + } + compress_level = 6; + if ( (compress_type / 100) == NX_COMP_LZW ) + { + compress_level = compress_type % 100; + compress_type = NX_COMP_LZW; + } + if(compress_type == NX_COMP_LZW) + { + cparms = H5Pcreate(H5P_DATASET_CREATE); + iNew = H5Pset_chunk(cparms,rank,chunkdims); + if (iNew < 0) + { + NXReportError( "ERROR: size of chunks could not be set"); + return NX_ERROR; + } + H5Pset_deflate(cparms,compress_level); + iRet = H5Dcreate(pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT); + } + else if (compress_type == NX_COMP_NONE) + { + if (unlimiteddim) + { + cparms = H5Pcreate(H5P_DATASET_CREATE); + iNew = H5Pset_chunk(cparms,rank,chunkdims); + if (iNew < 0) + { + NXReportError( "ERROR: size of chunks could not be set"); + return NX_ERROR; + } + iRet = H5Dcreate(pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT); + } + else + { + iRet = H5Dcreate(pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + } + } + else if (compress_type == NX_CHUNK) + { + cparms = H5Pcreate(H5P_DATASET_CREATE); + iNew = H5Pset_chunk(cparms,rank,chunkdims); + if (iNew < 0) + { + NXReportError("ERROR: size of chunks could not be set"); + return NX_ERROR; + } + iRet = H5Dcreate(pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, cparms, H5P_DEFAULT); + + } + else + { + NXReportError( + "HDF5 doesn't support selected compression method! Dataset was saved without compression"); + iRet = H5Dcreate (pFile->iCurrentG, (char*)name, datatype1, dataspace, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); + } + if (iRet < 0) + { + NXReportError( "ERROR: creating chunked dataset failed"); + return NX_ERROR; + } + else + { + pFile->iCurrentD = iRet; + } + if (unlimiteddim) + { + iNew = H5Dset_extent (pFile->iCurrentD, size); + if (iNew < 0) + { + sprintf (pBuffer, "ERROR: cannot create dataset %s", + name); + NXReportError( pBuffer); + return NX_ERROR; + } + } + if (cparms != -1) + { + iRet = H5Pclose(cparms); + } + iRet = H5Sclose(dataspace); + iRet = H5Tclose(datatype1); + iRet = H5Dclose(pFile->iCurrentD); + pFile->iCurrentD = 0; + if (iRet < 0) + { + NXReportError( "ERROR: HDF cannot close dataset"); + return NX_ERROR; + } + return NX_OK; } - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: Creating chunked dataset failed!"); + + + /* --------------------------------------------------------------------- */ + + NXstatus NX5makedata64 (NXhandle fid, CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[]) + { + int64_t chunk_size[H5S_MAX_RANK]; + int i; + + NXI5assert(fid); + + memset(chunk_size,0,H5S_MAX_RANK*sizeof(int64_t)); + memcpy(chunk_size,dimensions,rank*sizeof(int64_t)); + for(i = 0; i< rank; i++) { + if (dimensions[i] == NX_UNLIMITED || dimensions[i] <= 0){ + chunk_size[i]= 1; + } + } + return NX5compmakedata64 (fid, name, datatype, rank, dimensions, NX_COMP_NONE, chunk_size); + } + + + /* --------------------------------------------------------------------- */ + + NXstatus NX5compress (NXhandle fid, int compress_type) + { + printf(" NXcompress ERROR: NeXus API based on HDF5 doesn't support\n"); + printf(" NXcompress function! Using HDF5 library,\n"); + printf(" the NXcompmakedata function can be applied\n"); + printf(" for compression of data!\n"); return NX_ERROR; - } else { - pFile->iCurrentD = iRet; - } - if (dimensions[0] == NX_UNLIMITED) { - size[0] = 1; - iNew = H5Dextend(pFile->iCurrentD, size); - if (iNew < 0) { - sprintf(pBuffer, "ERROR: cannot create Dataset %s, check arguments", - name); - NXIReportError(NXpData, pBuffer); + } + + /* --------------------------------------------------------------------- */ + + NXstatus NX5opendata (NXhandle fid, CONSTCHAR *name) + { + pNexusFile5 pFile; + char pBuffer[256]; + + pFile = NXI5assert (fid); + /* clear pending attribute directories first */ + NXI5KillAttDir (pFile); + + + /* find the ID number and open the dataset */ + pFile->iCurrentD = H5Dopen(pFile->iCurrentG, name, H5P_DEFAULT); + if (pFile->iCurrentD < 0) { + sprintf (pBuffer, "ERROR: dataset \"%s\" not found at this level", name); + NXReportError( pBuffer); return NX_ERROR; } - } - if (cparms != -1) { - iRet = H5Pclose(cparms); - } - iRet = H5Sclose(dataspace); - iRet = H5Tclose(datatype1); - iRet = H5Dclose(pFile->iCurrentD); - pFile->iCurrentD = 0; - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot close Dataset"); - return NX_ERROR; - } - return NX_OK; -} - - - /* --------------------------------------------------------------------- */ - -NXstatus NX5makedata(NXhandle fid, CONSTCHAR * name, int datatype, - int rank, int dimensions[]) -{ - pNexusFile5 pFile; - int chunk_size[H5S_MAX_RANK]; - int i; - - pFile = NXI5assert(fid); - memset(chunk_size, 0, H5S_MAX_RANK * sizeof(int)); - if (dimensions[0] == NX_UNLIMITED) { - for (i = 0; i < H5S_MAX_RANK; i++) { - chunk_size[i] = 1; + /* find the ID number of datatype */ + pFile->iCurrentT = H5Dget_type(pFile->iCurrentD); + if (pFile->iCurrentT < 0) { + NXReportError( "ERROR: error opening dataset"); + pFile->iCurrentT=0; + return NX_ERROR; } + /* find the ID number of dataspace */ + pFile->iCurrentS = H5Dget_space(pFile->iCurrentD); + if (pFile->iCurrentS < 0) { + NXReportError( "ERROR:HDF error opening dataset"); + pFile->iCurrentS=0; + return NX_ERROR; + } + if(pFile->iCurrentLD != NULL){ + free(pFile->iCurrentLD); + } + pFile->iCurrentLD = strdup(name); + return NX_OK; } - return NX5compmakedata(fid, name, datatype, rank, dimensions, - NX_COMP_NONE, chunk_size); - - return NX_OK; -} - - - /* --------------------------------------------------------------------- */ - -NXstatus NX5compress(NXhandle fid, int compress_type) -{ - printf - (" NXcompress ERROR: NeXus API based on HDF5 doesn't support\n"); - printf - (" NXcompress function! Using HDF5 library,\n"); - printf - (" the NXcompmakedata function can be applied\n"); - printf(" for compression of data!\n"); - return NX_ERROR; -} - - /* --------------------------------------------------------------------- */ - -NXstatus NX5opendata(NXhandle fid, CONSTCHAR * name) -{ - pNexusFile5 pFile; - char pBuffer[256]; - - pFile = NXI5assert(fid); - /* clear pending attribute directories first */ - NXI5KillAttDir(pFile); - - - /* find the ID number and open the dataset */ - pFile->iCurrentD = H5Dopen(pFile->iCurrentG, name); - if (pFile->iCurrentD < 0) { - sprintf(pBuffer, "ERROR: Dataset %s not found at this level", name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - /* find the ID number of datatype */ - pFile->iCurrentT = H5Dget_type(pFile->iCurrentD); - if (pFile->iCurrentT < 0) { - NXIReportError(NXpData, "ERROR:HDF error opening Dataset"); - pFile->iCurrentT = 0; - return NX_ERROR; - } - /* find the ID number of dataspace */ - pFile->iCurrentS = H5Dget_space(pFile->iCurrentD); - if (pFile->iCurrentS < 0) { - NXIReportError(NXpData, "ERROR:HDF error opening Dataset"); - pFile->iCurrentS = 0; - return NX_ERROR; - } - if (pFile->iCurrentLD != NULL) { - free(pFile->iCurrentLD); - } - pFile->iCurrentLD = strdup(name); - return NX_OK; -} - + /* ----------------------------------------------------------------- */ -NXstatus NX5closedata(NXhandle fid) -{ - pNexusFile5 pFile; - int iRet; - - pFile = NXI5assert(fid); - iRet = H5Sclose(pFile->iCurrentS); - iRet = H5Tclose(pFile->iCurrentT); - iRet = H5Dclose(pFile->iCurrentD); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: HDF cannot end access to Dataset"); - return NX_ERROR; + NXstatus NX5closedata (NXhandle fid) + { + pNexusFile5 pFile; + herr_t iRet; + + pFile = NXI5assert (fid); + iRet = H5Sclose(pFile->iCurrentS); + iRet = H5Tclose(pFile->iCurrentT); + iRet = H5Dclose(pFile->iCurrentD); + if (iRet < 0) { + NXReportError( "ERROR: cannot end access to dataset"); + return NX_ERROR; + } + pFile->iCurrentD=0; + return NX_OK; } - pFile->iCurrentD = 0; - return NX_OK; -} - + /* ------------------------------------------------------------------- */ + - -NXstatus NX5putdata(NXhandle fid, void *data) -{ - pNexusFile5 pFile; - hid_t iRet; - - char pError[512] = ""; - - pFile = NXI5assert(fid); - - /* actually write */ - iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, H5S_ALL, H5S_ALL, - H5P_DEFAULT, data); - if (iRet < 0) { - snprintf(pError, 511, "ERROR: failure to write data"); - NXIReportError(NXpData, pError); - return NX_ERROR; + NXstatus NX5putdata (NXhandle fid, const void *data) + { + pNexusFile5 pFile; + herr_t iRet; + int64_t myStart[H5S_MAX_RANK]; + int64_t mySize[H5S_MAX_RANK]; + hsize_t thedims[H5S_MAX_RANK],maxdims[H5S_MAX_RANK]; + int i, rank, unlimiteddim = 0; + + char pError[512] = ""; + + pFile = NXI5assert (fid); + rank = H5Sget_simple_extent_ndims(pFile->iCurrentS); + if (rank < 0) + { + NXReportError("ERROR: Cannot determine dataset rank"); + return NX_ERROR; + } + iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, thedims, maxdims); + if (iRet < 0) + { + NXReportError("ERROR: Cannot determine dataset dimensions"); + return NX_ERROR; + } + for(i=0; iiCurrentD, pFile->iCurrentT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, data); + if (iRet < 0) { + snprintf (pError,sizeof(pError)-1, "ERROR: failure to write data"); + NXReportError( pError); + return NX_ERROR; + } + } + return NX_OK; } - return NX_OK; -} - /*------------------------------------------------------------------*/ -static int getAttVID(pNexusFile5 pFile) -{ +static int getAttVID(pNexusFile5 pFile){ int vid; - if (pFile->iCurrentG == 0 && pFile->iCurrentD == 0) { - /* global attribute */ - vid = H5Gopen(pFile->iFID, "/"); - } else if (pFile->iCurrentD != 0) { - /* dataset attribute */ - vid = pFile->iCurrentD; - } else { - /* group attribute */ ; - vid = pFile->iCurrentG; - } - return vid; + if(pFile->iCurrentG == 0 && pFile->iCurrentD == 0){ + /* global attribute */ + vid = H5Gopen(pFile->iFID,"/", H5P_DEFAULT); + } else if(pFile->iCurrentD != 0) { + /* dataset attribute */ + vid = pFile->iCurrentD; + } else { + /* group attribute */; + vid = pFile->iCurrentG; + } + return vid; } - /*---------------------------------------------------------------*/ -static void killAttVID(pNexusFile5 pFile, int vid) -{ - if (pFile->iCurrentG == 0 && pFile->iCurrentD == 0) { +static void killAttVID(pNexusFile5 pFile, int vid){ + if(pFile->iCurrentG == 0 && pFile->iCurrentD == 0){ H5Gclose(vid); } } - /* ------------------------------------------------------------------- */ -NXstatus NX5putattr(NXhandle fid, CONSTCHAR * name, void *data, - int datalen, int iType) -{ - pNexusFile5 pFile; - hid_t attr1, aid1, aid2; - hid_t type; - int iRet; - int vid; + NXstatus NX5putattr (NXhandle fid, CONSTCHAR *name, const void *data, - pFile = NXI5assert(fid); + int datalen, int iType) + { + pNexusFile5 pFile; + hid_t attr1, aid1, aid2; + hid_t type; + herr_t iRet; + int vid; - type = nxToHDF5Type(iType); + pFile = NXI5assert (fid); - /* determine vid */ - vid = getAttVID(pFile); - aid2 = H5Screate(H5S_SCALAR); - aid1 = H5Tcopy(type); - if (iType == NX_CHAR) { - H5Tset_size(aid1, datalen); - } - iRet = H5Aopen_name(vid, name); - if (iRet > 0) { - H5Aclose(iRet); - iRet = H5Adelete(vid, name); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: Old attribute cannot removed! "); - killAttVID(pFile, vid); + type = nxToHDF5Type(iType); + + /* determine vid */ + vid = getAttVID(pFile); + aid2=H5Screate(H5S_SCALAR); + aid1=H5Tcopy(type); + if (iType == NX_CHAR){ + H5Tset_size(aid1,datalen); + } + iRet = H5Aopen_by_name(vid, ".", name, H5P_DEFAULT, H5P_DEFAULT); + if (iRet>0) { + H5Aclose(iRet); + iRet=H5Adelete(vid,name); + if (iRet<0) { + NXReportError( "ERROR: old attribute cannot be removed! "); + killAttVID(pFile,vid); + return NX_ERROR; + } + } + attr1 = H5Acreate(vid, name, aid1, aid2, H5P_DEFAULT, H5P_DEFAULT); + if (attr1 < 0) { + NXReportError( "ERROR: attribute cannot created! "); + killAttVID(pFile,vid); + return NX_ERROR; + } + if (H5Awrite(attr1,aid1,data) < 0) { + NXReportError( "ERROR: failed to store attribute "); + killAttVID(pFile,vid); return NX_ERROR; } - } - attr1 = H5Acreate(vid, name, aid1, aid2, H5P_DEFAULT); - if (attr1 < 0) { - NXIReportError(NXpData, "ERROR: Attribute cannot created! "); - killAttVID(pFile, vid); - return NX_ERROR; - } - if (H5Awrite(attr1, aid1, data) < 0) { - NXIReportError(NXpData, "ERROR: HDF failed to store attribute "); - killAttVID(pFile, vid); - return NX_ERROR; - } - /* Close attribute dataspace */ - iRet = H5Tclose(aid1); - iRet = H5Sclose(aid2); - /* Close attribute */ - iRet = H5Aclose(attr1); - killAttVID(pFile, vid); - return NX_OK; -} - - /* ------------------------------------------------------------------- */ - -NXstatus NX5putslab(NXhandle fid, void *data, int iStart[], int iSize[]) -{ - pNexusFile5 pFile; - int iRet, i; - int rank; - hsize_t myStart[H5S_MAX_RANK]; - hsize_t mySize[H5S_MAX_RANK]; - hsize_t size[H5S_MAX_RANK], maxdims[H5S_MAX_RANK]; - hid_t filespace, dataspace; - - pFile = NXI5assert(fid); - /* check if there is an Dataset open */ - if (pFile->iCurrentD == 0) { - NXIReportError(NXpData, "ERROR: no dataset open"); - return NX_ERROR; - } - rank = H5Sget_simple_extent_ndims(pFile->iCurrentS); - iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, NULL, maxdims); - for (i = 0; i < rank; i++) { - myStart[i] = iStart[i]; - mySize[i] = iSize[i]; - size[i] = iSize[i]; - } - if (H5Tget_class(pFile->iCurrentT) == H5T_STRING) { - mySize[rank - 1] = 1; - myStart[rank - 1] = 0; - } - dataspace = H5Screate_simple(rank, mySize, NULL); - if (maxdims[0] == NX_UNLIMITED) { - size[0] = iStart[0] + iSize[0]; - iRet = H5Dextend(pFile->iCurrentD, size); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: extend slab failed"); - return NX_ERROR; - } - - filespace = H5Dget_space(pFile->iCurrentD); - - /* define slab */ - iRet = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, myStart, - NULL, mySize, NULL); - /* deal with HDF errors */ - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: selecting slab failed"); - return NX_ERROR; - } - /* write slab */ - iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace, - filespace, H5P_DEFAULT, data); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: writing slab failed"); - } - iRet = H5Sclose(filespace); - } else { - /* define slab */ - iRet = H5Sselect_hyperslab(pFile->iCurrentS, H5S_SELECT_SET, myStart, - NULL, mySize, NULL); - /* deal with HDF errors */ - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: selecting slab failed"); - return NX_ERROR; - } - /* write slab */ - iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace, - pFile->iCurrentS, H5P_DEFAULT, data); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: writing slab failed"); - } - } - /* deal with HDF errors */ - iRet = H5Sclose(dataspace); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: closing slab failed"); - return NX_ERROR; - } - return NX_OK; -} - - /* ------------------------------------------------------------------- */ - -NXstatus NX5getdataID(NXhandle fid, NXlink * sRes) -{ - pNexusFile5 pFile; - ErrFunc oldErr; - int datalen, type = NX_CHAR; - - pFile = NXI5assert(fid); - - /* - we cannot return ID's when no datset is open - */ - if (pFile->iCurrentD <= 0) { - return NX_ERROR; - } - - /* - this means: if the item is already linked: use the target attribute else, - the path to the current node - */ - oldErr = NXMGetError(); - NXMSetError(NXpData, ignoreError); - datalen = 1024; - memset(&sRes->targetPath, 0, datalen * sizeof(char)); - if (NX5getattr(fid, "target", &sRes->targetPath, &datalen, &type) != - NX_OK) { - buildCurrentPath(pFile, sRes->targetPath, 1024); - } - NXMSetError(NXpData, oldErr); - sRes->linkType = 1; - return NX_OK; -} - - /* ------------------------------------------------------------------- */ - -NXstatus NX5printlink(NXhandle fid, NXlink * sLink) -{ - pNexusFile5 pFile; - pFile = NXI5assert(fid); - printf("HDF5 link: targetPath = \"%s\", linkType = \"%d\"\n", - sLink->targetPath, sLink->linkType); - return NX_OK; -} - -/*--------------------------------------------------------------------*/ -static NXstatus NX5settargetattribute(pNexusFile5 pFile, NXlink * sLink) -{ - herr_t length, dataID, status, aid2, aid1, attID; - int type = NX_CHAR; - char name[] = "target"; - - length = strlen(sLink->targetPath); - /* - set the target attribute - */ - if (sLink->linkType > 0) { - dataID = H5Dopen(pFile->iFID, sLink->targetPath); - } else { - dataID = H5Gopen(pFile->iFID, sLink->targetPath); - } - if (dataID < 0) { - NXIReportError(NXpData, "Internal error, path to link does not exist"); - return NX_ERROR; - } - status = H5Aopen_name(dataID, name); - if (status > 0) { - H5Aclose(status); - status = H5Adelete(dataID, name); - if (status < 0) { - return NX_OK; - } - } - aid2 = H5Screate(H5S_SCALAR); - aid1 = H5Tcopy(H5T_C_S1); - H5Tset_size(aid1, strlen(sLink->targetPath)); - attID = H5Acreate(dataID, name, aid1, aid2, H5P_DEFAULT); - if (attID < 0) { + /* Close attribute dataspace */ + iRet=H5Tclose(aid1); + iRet=H5Sclose(aid2); + /* Close attribute */ + iRet=H5Aclose(attr1); + killAttVID(pFile,vid); return NX_OK; } - status = H5Awrite(attID, aid1, sLink->targetPath); - H5Tclose(aid1); - H5Sclose(aid2); - H5Aclose(attID); - if (sLink->linkType > 0) { - H5Dclose(dataID); - } else { - H5Gclose(dataID); + + /* ------------------------------------------------------------------- */ + + NXstatus NX5putslab64 (NXhandle fid, const void *data, const int64_t iStart[], const int64_t iSize[]) + { + pNexusFile5 pFile; + int iRet, rank, i; + hsize_t myStart[H5S_MAX_RANK]; + hsize_t mySize[H5S_MAX_RANK]; + hsize_t size[H5S_MAX_RANK],thedims[H5S_MAX_RANK],maxdims[H5S_MAX_RANK]; + hid_t filespace,dataspace; + int unlimiteddim = 0; + + pFile = NXI5assert (fid); + /* check if there is an Dataset open */ + if (pFile->iCurrentD == 0) { + NXReportError( "ERROR: no dataset open"); + return NX_ERROR; + } + rank = H5Sget_simple_extent_ndims(pFile->iCurrentS); + if (rank < 0) { + NXReportError( "ERROR: cannot get rank"); + return NX_ERROR; + } + iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, thedims, maxdims); + if (iRet < 0) { + NXReportError( "ERROR: cannot get dimensions"); + return NX_ERROR; + } + + for(i = 0; i < rank; i++) + { + myStart[i] = iStart[i]; + mySize[i] = iSize[i]; + size[i] = iStart[i] + iSize[i]; + if (maxdims[i] == H5S_UNLIMITED) { + unlimiteddim = 1; + } + } + if (H5Tget_class(pFile->iCurrentT) == H5T_STRING) + { + mySize[rank - 1] = 1; + myStart[rank - 1] = 0; + size[rank - 1] = 1; + } + dataspace = H5Screate_simple(rank, mySize, NULL); + if (unlimiteddim) + { + for(i = 0; i < rank; i++) + { + if (size[i] < thedims[i]) { + size[i] = thedims[i]; + } + } + iRet = H5Dset_extent(pFile->iCurrentD, size); + if (iRet < 0) + { + NXReportError( "ERROR: extend slab failed"); + return NX_ERROR; + } + + filespace = H5Dget_space(pFile->iCurrentD); + + /* define slab */ + iRet = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, myStart, + NULL, mySize, NULL); + /* deal with HDF errors */ + if (iRet < 0) + { + NXReportError( "ERROR: selecting slab failed"); + return NX_ERROR; + } + /* write slab */ + iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace, + filespace, H5P_DEFAULT, data); + if (iRet < 0) + { + NXReportError( "ERROR: writing slab failed"); + } + /* update with new size */ + iRet = H5Sclose(pFile->iCurrentS); + pFile->iCurrentS = filespace; + } else { + /* define slab */ + iRet = H5Sselect_hyperslab(pFile->iCurrentS, H5S_SELECT_SET, myStart, + NULL, mySize, NULL); + /* deal with HDF errors */ + if (iRet < 0) + { + NXReportError( "ERROR: selecting slab failed"); + return NX_ERROR; + } + /* write slab */ + iRet = H5Dwrite(pFile->iCurrentD, pFile->iCurrentT, dataspace, + pFile->iCurrentS, H5P_DEFAULT, data); + if (iRet < 0) + { + NXReportError( "ERROR: writing slab failed"); + } + } + /* deal with HDF errors */ + iRet = H5Sclose(dataspace); + if (iRet < 0) + { + NXReportError( "ERROR: closing slab failed"); + return NX_ERROR; + } + return NX_OK; } - return NX_OK; -} + + /* ------------------------------------------------------------------- */ -/*---------------------------------------------------------------------*/ -NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR * name, NXlink * sLink) -{ - pNexusFile5 pFile; - char linkTarget[1024]; - int type = NX_CHAR, length; - int status; + NXstatus NX5getdataID (NXhandle fid, NXlink* sRes) + { + pNexusFile5 pFile; + int datalen, type = NX_CHAR; + + pFile = NXI5assert (fid); - pFile = NXI5assert(fid); - if (pFile->iCurrentG == 0) { /* root level, can not link here */ - return NX_ERROR; + /* + we cannot return ID's when no datset is open + */ + if(pFile->iCurrentD <= 0){ + return NX_ERROR; + } + + /* + this means: if the item is already linked: use the target attribute else, + the path to the current node + */ + NXMDisableErrorReporting(); + datalen = 1024; + memset(&sRes->targetPath,0,datalen*sizeof(char)); + if(NX5getattr(fid,"target",&sRes->targetPath,&datalen,&type) != NX_OK) + { + buildCurrentPath(pFile, sRes->targetPath, 1024); + } + NXMEnableErrorReporting(); + sRes->linkType = 1; + return NX_OK; } - /* - build pathname to link from our current group and the name - of the thing to link - */ - if (strlen(pFile->name_ref) + strlen(name) + 2 < 1024) { - strcpy(linkTarget, "/"); - strcat(linkTarget, pFile->name_ref); - strcat(linkTarget, "/"); - strcat(linkTarget, name); - } else { - NXIReportError(NXpData, "Path string to long"); - return NX_ERROR; - } - - status = - H5Glink(pFile->iFID, H5G_LINK_HARD, sLink->targetPath, linkTarget); - - return NX5settargetattribute(pFile, sLink); -} - /* ------------------------------------------------------------------- */ - -NXstatus NX5makelink(NXhandle fid, NXlink * sLink) + + NXstatus NX5printlink (NXhandle fid, NXlink* sLink) + { + NXI5assert(fid); + printf("HDF5 link: targetPath = \"%s\", linkType = \"%d\"\n", sLink->targetPath, sLink->linkType); + return NX_OK; + } +/*--------------------------------------------------------------------*/ +static NXstatus NX5settargetattribute(pNexusFile5 pFile, NXlink *sLink) { - pNexusFile5 pFile; - char linkTarget[1024]; - int type = NX_CHAR, length; - char *itemName = NULL; - int status; + hid_t dataID, aid2, aid1, attID; + herr_t status; + char name[] = "target"; - pFile = NXI5assert(fid); - if (pFile->iCurrentG == 0) { /* root level, can not link here */ - return NX_ERROR; - } - - /* - locate name of the element to link - */ - itemName = strrchr(sLink->targetPath, '/'); - if (itemName == NULL) { - NXIReportError(NXpData, "Bad link structure"); - return NX_ERROR; - } - itemName++; - - /* - build pathname to link from our current group and the name - of the thing to link - */ - if (strlen(pFile->name_ref) + strlen(itemName) + 2 < 1024) { - strcpy(linkTarget, "/"); - strcat(linkTarget, pFile->name_ref); - strcat(linkTarget, "/"); - strcat(linkTarget, itemName); - } else { - NXIReportError(NXpData, "Path string to long"); - return NX_ERROR; - } - - status = - H5Glink(pFile->iFID, H5G_LINK_HARD, sLink->targetPath, linkTarget); - - return NX5settargetattribute(pFile, sLink); + /* + set the target attribute + */ + if(sLink->linkType > 0) + { + dataID = H5Dopen(pFile->iFID,sLink->targetPath, H5P_DEFAULT); + } else { + dataID = H5Gopen(pFile->iFID,sLink->targetPath, H5P_DEFAULT); + } + if(dataID < 0) + { + NXReportError("Internal error, path to link does not exist"); + return NX_ERROR; + } + status = H5Aopen_by_name(dataID,".", name, H5P_DEFAULT, H5P_DEFAULT); + if(status > 0) + { + H5Aclose(status); + status = H5Adelete(dataID,name); + if(status < 0) + { + return NX_OK; + } + } + aid2 = H5Screate(H5S_SCALAR); + aid1 = H5Tcopy(H5T_C_S1); + H5Tset_size(aid1,strlen(sLink->targetPath)); + attID = H5Acreate(dataID,name,aid1,aid2,H5P_DEFAULT, H5P_DEFAULT); + if(attID < 0) + { + return NX_OK; + } + status = H5Awrite(attID,aid1,sLink->targetPath); + H5Tclose(aid1); + H5Sclose(aid2); + H5Aclose(attID); + if(sLink->linkType > 0){ + H5Dclose(dataID); + } else { + H5Gclose(dataID); + } + return NX_OK; } +/*---------------------------------------------------------------------*/ +NXstatus NX5makenamedlink(NXhandle fid, CONSTCHAR *name, NXlink *sLink) +{ + pNexusFile5 pFile; + char linkTarget[1024]; + pFile = NXI5assert (fid); + if (pFile->iCurrentG == 0) { /* root level, can not link here */ + return NX_ERROR; + } + + /* + build pathname to link from our current group and the name + of the thing to link + */ + if(strlen(pFile->name_ref) + strlen(name) + 2 < 1024) + { + strcpy(linkTarget,"/"); + strcat(linkTarget,pFile->name_ref); + strcat(linkTarget,"/"); + strcat(linkTarget,name); + } + else + { + NXReportError("ERROR: path string to long"); + return NX_ERROR; + } + + //targetid = H5Oopen(pFile->iFID, sLink->targetPath, H5P_DEFAULT); + H5Lcreate_hard(pFile->iFID, sLink->targetPath, H5L_SAME_LOC, linkTarget, H5P_DEFAULT, H5P_DEFAULT); + //H5Oclose(targetid); + + return NX5settargetattribute(pFile,sLink); +} + /* ------------------------------------------------------------------- */ + + NXstatus NX5makelink (NXhandle fid, NXlink* sLink) + { + pNexusFile5 pFile; + char linkTarget[1024]; + char *itemName = NULL; + + pFile = NXI5assert (fid); + if (pFile->iCurrentG == 0) { /* root level, can not link here */ + return NX_ERROR; + } + + /* + locate name of the element to link + */ + itemName = strrchr(sLink->targetPath,'/'); + if(itemName == NULL){ + NXReportError("ERROR: bad link structure"); + return NX_ERROR; + } + itemName++; + + /* + build pathname to link from our current group and the name + of the thing to link + */ + if(strlen(pFile->name_ref) + strlen(itemName) + 2 < 1024) + { + strcpy(linkTarget,"/"); + strcat(linkTarget,pFile->name_ref); + strcat(linkTarget,"/"); + strcat(linkTarget,itemName); + } + else + { + NXReportError("ERROR: path string to long"); + return NX_ERROR; + } + + //targetid = H5Oopen(pFile->iFID, sLink->targetPath, H5P_DEFAULT); + H5Lcreate_hard(pFile->iFID, sLink->targetPath, H5L_SAME_LOC, linkTarget, H5P_DEFAULT, H5P_DEFAULT); + //H5Oclose(targetid); + + return NX5settargetattribute(pFile,sLink); + } + /*----------------------------------------------------------------------*/ -NXstatus NX5flush(NXhandle * pHandle) -{ - pNexusFile5 pFile = NULL; - int iRet; - - pFile = NXI5assert(*pHandle); - if (pFile->iCurrentD != 0) { - iRet = H5Fflush(pFile->iCurrentD, H5F_SCOPE_LOCAL); - } else if (pFile->iCurrentG != 0) { - iRet = H5Fflush(pFile->iCurrentG, H5F_SCOPE_LOCAL); - } else { - iRet = H5Fflush(pFile->iFID, H5F_SCOPE_LOCAL); - } - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: The object cannot be flushed"); - return NX_ERROR; - } - return NX_OK; -} - + NXstatus NX5flush(NXhandle *pHandle) + { + pNexusFile5 pFile = NULL; + herr_t iRet; + + pFile = NXI5assert (*pHandle); + if (pFile->iCurrentD != 0) + { + iRet=H5Fflush(pFile->iCurrentD,H5F_SCOPE_LOCAL); + } + else if (pFile->iCurrentG != 0) + { + iRet=H5Fflush(pFile->iCurrentG,H5F_SCOPE_LOCAL); + } + else + { + iRet=H5Fflush(pFile->iFID,H5F_SCOPE_LOCAL); + } + if (iRet < 0){ + NXReportError( "ERROR: The object cannot be flushed"); + return NX_ERROR; + } + return NX_OK; + } + /*-------------------------------------------------------------------------*/ - + /* Operator function. */ - -herr_t nxgroup_info(hid_t loc_id, const char *name, void *op_data) -{ - H5G_stat_t statbuf; - pinfo self; - - self = (pinfo) op_data; - H5Gget_objinfo(loc_id, name, 0, &statbuf); - switch (statbuf.type) { - case H5G_GROUP: - self->iname = strdup(name); - self->type = H5G_GROUP; - break; - case H5G_DATASET: - self->iname = strdup(name); - self->type = H5G_DATASET; - break; - default: - self->type = 0; - break; + + herr_t nxgroup_info(hid_t loc_id, const char *name, const H5L_info_t *statbuf, void *op_data) + { + pinfo self = (pinfo) op_data; + H5O_info_t object_info; + H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT); + switch ((object_info).type) { + case H5O_TYPE_GROUP: + self->iname = strdup(name); + self->type = H5O_TYPE_GROUP; + break; + case H5O_TYPE_DATASET: + self->iname = strdup(name); + self->type = H5O_TYPE_DATASET; + break; + default: + // TODO defaults to group. not what we would want? + self->type=0; + break; + } + return 1; } - return 1; -} - /* --------------------------------------------------------------------- */ /* Operator function. */ -herr_t group_info1(hid_t loc_id, const char *name, void *opdata) -{ - NexusFile5 self; - H5G_stat_t statbuf; - self.iNX = *((int *) opdata); - H5Gget_objinfo(loc_id, name, 0, &statbuf); - - switch (statbuf.type) { - case H5G_GROUP: - self.iNX++; - *((int *) opdata) = self.iNX; - break; - case H5G_DATASET: - self.iNX++; - *((int *) opdata) = self.iNX; - break; - default: - break; + herr_t group_info1(hid_t loc_id, const char *name, const H5L_info_t *statbuf, void *opdata) + { + int iNX = *((int*)opdata); + H5O_info_t object_info; + H5Oget_info_by_name(loc_id, name, &object_info, H5P_DEFAULT); + switch ((object_info).type) { + case H5O_TYPE_GROUP: + iNX++; + *((int*)opdata)=iNX; + break; + case H5O_TYPE_DATASET: + iNX++; + *((int*)opdata)=iNX; + break; + default: + break; + } + return 0; } - return 0; -} - + /*-------------------------------------------------------------------------*/ -NXstatus NX5getgroupinfo(NXhandle fid, int *iN, NXname pName, - NXname pClass) -{ - pNexusFile5 pFile; - hid_t atype, attr_id; - char data[64]; - int iRet; - - pFile = NXI5assert(fid); - /* check if there is a group open */ - if (pFile->iCurrentG == 0) { - strcpy(pName, "root"); - strcpy(pClass, "NXroot"); - pFile->iNX = 0; - iRet = H5Giterate(pFile->iFID, "/", 0, group_info1, &pFile->iNX); - *iN = pFile->iNX; - } else { - strcpy(pName, pFile->name_ref); - attr_id = H5Aopen_name(pFile->iCurrentG, "NX_class"); - if (attr_id < 0) { - strcpy(pClass, NX_UNKNOWN_GROUP); - } else { - atype = H5Tcopy(H5T_C_S1); - H5Tset_size(atype, 64); - H5Aread(attr_id, atype, data); - strcpy(pClass, data); - pFile->iNX = 0; - iRet = - H5Giterate(pFile->iFID, pFile->name_ref, 0, group_info1, - &pFile->iNX); - *iN = pFile->iNX; - H5Aclose(attr_id); + NXstatus NX5getgroupinfo_recurse(NXhandle fid, int *iN, NXname pName, NXname pClass) + { + pNexusFile5 pFile; + hid_t atype, attr_id, grp; + char data[64]; + + pFile = NXI5assert (fid); + /* check if there is a group open */ + if (pFile->iCurrentG == 0) { + strcpy (pName, "root"); + strcpy (pClass, "NXroot"); + pFile->iNX=0; + grp = H5Gopen(pFile->iFID,"/",H5P_DEFAULT); + H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1, &pFile->iNX); + H5Gclose(grp); + *iN=pFile->iNX; } - } - return NX_OK; -} - -/*------------------------------------------------------------------------*/ -static int hdf5ToNXType(int data_id, hid_t atype) -{ - int iPtype = -1; - hid_t sign_id, size_id; - - if (data_id == H5T_STRING) { - iPtype = NX_CHAR; - } - if (data_id == H5T_INTEGER) { - size_id = H5Tget_size(atype); - sign_id = H5Tget_sign(atype); - if (size_id == 1) { - if (sign_id == H5T_SGN_2) { - iPtype = NX_INT8; + else { + strcpy (pName,pFile->name_ref); + attr_id = H5Aopen_by_name(pFile->iCurrentG,".", "NX_class", H5P_DEFAULT, H5P_DEFAULT); + if (attr_id<0) { + strcpy(pClass, NX_UNKNOWN_GROUP); } else { - iPtype = NX_UINT8; + atype=H5Tcopy(H5T_C_S1); + H5Tset_size(atype,sizeof(data)); + H5Aread(attr_id, atype, data); + strcpy(pClass,data); + pFile->iNX=0; + grp = H5Gopen(pFile->iFID,pFile->name_ref,H5P_DEFAULT); + H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1, &pFile->iNX); + H5Gclose(grp); + *iN=pFile->iNX; + H5Aclose(attr_id); } - } else if (size_id == 2) { - if (sign_id == H5T_SGN_2) { - iPtype = NX_INT16; - } else { - iPtype = NX_UINT16; - } - } else if (size_id == 4) { - if (sign_id == H5T_SGN_2) { - iPtype = NX_INT32; - } else { - iPtype = NX_UINT32; - } - } else if (size_id == 8) { - if (sign_id == H5T_SGN_2) { - iPtype = NX_INT64; - } else { - iPtype = NX_UINT64; - } - } - } else if (data_id == H5T_FLOAT) { - size_id = H5Tget_size(atype); - if (size_id == 4) { - iPtype = NX_FLOAT32; - } else if (size_id == 8) { - iPtype = NX_FLOAT64; - } - } - if (iPtype == -1) { - NXIReportError(NXpData, "ERROR: hdf5ToNXtype: invalid type"); - } - - return iPtype; -} - -/*--------------------------------------------------------------------------*/ -static int h5MemType(hid_t atype) -{ - hid_t data_id, size_id, sign_id, memtype_id = -1; - - data_id = H5Tget_class(atype); - - if (data_id == H5T_INTEGER) { - size_id = H5Tget_size(atype); - sign_id = H5Tget_sign(atype); - if (size_id == 1) { - if (sign_id == H5T_SGN_2) { - memtype_id = H5T_NATIVE_INT8; - } else { - memtype_id = H5T_NATIVE_UINT8; - } - } else if (size_id == 2) { - if (sign_id == H5T_SGN_2) { - memtype_id = H5T_NATIVE_INT16; - } else { - memtype_id = H5T_NATIVE_UINT16; - } - } else if (size_id == 4) { - if (sign_id == H5T_SGN_2) { - memtype_id = H5T_NATIVE_INT32; - } else { - memtype_id = H5T_NATIVE_UINT32; - } - } else if (size_id == 8) { - if (sign_id == H5T_SGN_2) { - memtype_id = H5T_NATIVE_INT64; - } else { - memtype_id = H5T_NATIVE_UINT64; - } - } - } else if (data_id == H5T_FLOAT) { - size_id = H5Tget_size(atype); - if (size_id == 4) { - memtype_id = H5T_NATIVE_FLOAT; - } else if (size_id == 8) { - memtype_id = H5T_NATIVE_DOUBLE; - } - } - if (memtype_id == -1) { - NXIReportError(NXpData, "ERROR: h5MemType: invalid type"); - } - return memtype_id; -} - - /*-------------------------------------------------------------------------*/ - -NXstatus NX5getnextentry(NXhandle fid, NXname name, NXname nxclass, - int *datatype) -{ - pNexusFile5 pFile; - hid_t grp, attr1, type, atype; - int iRet, iPtype, i; - int idx, data_id, size_id, sign_id; - char data[128]; - char ph_name[1024]; - info_type op_data; - int iRet_iNX = -1; - char pBuffer[256]; - - pFile = NXI5assert(fid); - op_data.iname = NULL; - - /* - iterate to next entry in group list - */ - idx = pFile->iStack5[pFile->iStackPtr].iCurrentIDX; - if (strlen(pFile->name_ref) == 0) { - /* root group */ - strcpy(pFile->name_ref, "/"); - } - iRet = - H5Giterate(pFile->iFID, pFile->name_ref, &idx, nxgroup_info, - &op_data); - strcpy(nxclass, NX_UNKNOWN_GROUP); - - /* - figure out the number of items in the current group. We need this in order to - find out if we are at the end of the search. - */ - if (pFile->iCurrentG == 0) { - pFile->iNX = 0; - iRet_iNX = H5Giterate(pFile->iFID, "/", 0, group_info1, &pFile->iNX); - } else { - pFile->iNX = 0; - iRet_iNX = - H5Giterate(pFile->iFID, pFile->name_ref, 0, group_info1, - &pFile->iNX); - } - if (idx == pFile->iNX) { - iRet_iNX = 2; - } - - if (iRet > 0) { - pFile->iStack5[pFile->iStackPtr].iCurrentIDX++; - if (op_data.iname != NULL) { - strcpy(name, op_data.iname); - free(op_data.iname); - } else { - pFile->iStack5[pFile->iStackPtr].iCurrentIDX = 0; - return NX_EOD; - } - if (op_data.type == H5G_GROUP) { - /* - open group and find class name attribute - */ - strcpy(ph_name, ""); - for (i = 1; i < (pFile->iStackPtr + 1); i++) { - strcat(ph_name, pFile->iStack5[i].irefn); - strcat(ph_name, "/"); - } - strcat(ph_name, name); - grp = H5Gopen(pFile->iFID, ph_name); - if (grp < 0) { - sprintf(pBuffer, "ERROR: Group %s does not exist!", ph_name); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - attr1 = H5Aopen_name(grp, "NX_class"); - if (attr1 < 0) { - strcpy(nxclass, NX_UNKNOWN_GROUP); - } else { - type = H5T_C_S1; - atype = H5Tcopy(type); - H5Tset_size(atype, 128); - iRet = H5Aread(attr1, atype, data); - strcpy(nxclass, data); - H5Tclose(atype); - H5Aclose(attr1); - } - H5Gclose(grp); - } else if (op_data.type == H5G_DATASET) { - /* - open dataset and find type - */ - grp = H5Dopen(pFile->iCurrentG, name); - type = H5Dget_type(grp); - atype = H5Tcopy(type); - data_id = H5Tget_class(atype); - iPtype = hdf5ToNXType(data_id, atype); - *datatype = iPtype; - strcpy(nxclass, "SDS"); - H5Tclose(atype); - H5Tclose(type); - H5Dclose(grp); } return NX_OK; - } else { - /* - we are at the end of the search: clear the data structure and reset - iCurrentIDX to 0 - */ - if (iRet_iNX == 2) { - if (op_data.iname != NULL) { - free(op_data.iname); + } +/*---------------------------------------------------------------------------*/ +static int countObjectsInGroup(hid_t loc_id) +{ + int count = 0; + H5G_info_t numobj; + + herr_t status; + + status = H5Gget_info(loc_id, &numobj); + if(status < 0) { + NXReportError("Internal error, failed to retrive no of objects"); + return 0; + } + + count = numobj.nlinks; + return count; +} +/*----------------------------------------------------------------------------*/ + NXstatus NX5getgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass) + { + pNexusFile5 pFile; + hid_t atype, attr_id, gid; + char data[64]; + + pFile = NXI5assert (fid); + /* check if there is a group open */ + if (pFile->iCurrentG == 0) { + strcpy (pName, "root"); + strcpy (pClass, "NXroot"); + gid = H5Gopen(pFile->iFID,"/", H5P_DEFAULT); + *iN = countObjectsInGroup(gid); + H5Gclose(gid); + } + else { + strcpy (pName,pFile->name_ref); + attr_id = H5Aopen_by_name(pFile->iCurrentG,".", "NX_class", H5P_DEFAULT, H5P_DEFAULT); + if (attr_id<0) { + strcpy(pClass, NX_UNKNOWN_GROUP); + } else { + atype=H5Tcopy(H5T_C_S1); + H5Tset_size(atype,sizeof(data)); + H5Aread(attr_id, atype, data); + strcpy(pClass,data); + pFile->iNX=0; + *iN = countObjectsInGroup(pFile->iCurrentG); + H5Aclose(attr_id); } - pFile->iStack5[pFile->iStackPtr].iCurrentIDX = 0; - return NX_EOD; } - if (op_data.iname != NULL) { - free(op_data.iname); + return NX_OK; + } + + +/*------------------------------------------------------------------------- + * Function: hdf5ToNXType + * + * Purpose: Convert a HDF5 class to a NeXus type; it handles the following HDF5 classes + * H5T_STRING + * H5T_INTEGER + * H5T_FLOAT + * + * Return: the NeXus type + * + *------------------------------------------------------------------------- + */ + static int hdf5ToNXType(H5T_class_t tclass, hid_t atype) + { + int iPtype = -1; + size_t size; + H5T_sign_t sign; + + if (tclass==H5T_STRING) + { + iPtype=NX_CHAR; + } + else if (tclass==H5T_INTEGER) + { + size=H5Tget_size(atype); + sign=H5Tget_sign(atype); + if (size==1) + { + if (sign==H5T_SGN_2) + { + iPtype=NX_INT8; + } else { + iPtype=NX_UINT8; + } + } + else if (size==2) + { + if (sign==H5T_SGN_2) + { + iPtype=NX_INT16; + } else { + iPtype=NX_UINT16; + } + } + else if (size==4) + { + if (sign==H5T_SGN_2) + { + iPtype=NX_INT32; + } else { + iPtype=NX_UINT32; + } + } + else if(size == 8) + { + if (sign==H5T_SGN_2) + { + iPtype=NX_INT64; + } else { + iPtype=NX_UINT64; + } + } + } + else if (tclass==H5T_FLOAT) + { + size=H5Tget_size(atype); + if (size==4) + { + iPtype=NX_FLOAT32; + } + else if (size==8) + { + iPtype=NX_FLOAT64; + } + } + if (iPtype == -1) + { + NXReportError( "ERROR: hdf5ToNXtype: invalid type"); + } + + return iPtype; + } +/*--------------------------------------------------------------------------*/ + static hid_t h5MemType(hid_t atype) + { + hid_t memtype_id = -1; + size_t size; + H5T_sign_t sign; + H5T_class_t tclass; + + tclass = H5Tget_class(atype); + + if (tclass==H5T_INTEGER) + { + size=H5Tget_size(atype); + sign=H5Tget_sign(atype); + if (size==1) + { + if (sign==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT8; + } else { + memtype_id = H5T_NATIVE_UINT8; + } + } + else if (size==2) + { + if (sign==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT16; + } else { + memtype_id = H5T_NATIVE_UINT16; + } + } + else if (size==4) + { + if (sign==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT32; + } else { + memtype_id = H5T_NATIVE_UINT32; + } + } + else if (size==8) + { + if (sign==H5T_SGN_2) + { + memtype_id = H5T_NATIVE_INT64; + } else { + memtype_id = H5T_NATIVE_UINT64; + } + } + } else if (tclass==H5T_FLOAT) + { + size=H5Tget_size(atype); + if (size==4) + { + memtype_id = H5T_NATIVE_FLOAT; + } else if (size==8) { + memtype_id = H5T_NATIVE_DOUBLE; + } + } + if (memtype_id == -1) + { + NXReportError( "ERROR: h5MemType: invalid type"); + } + return memtype_id; + } + /*-------------------------------------------------------------------------*/ + + NXstatus NX5getnextentry(NXhandle fid, NXname name, NXname nxclass, int *datatype) + { + pNexusFile5 pFile; + hid_t grp, attr1,type,atype; + herr_t iRet; + int iPtype, i; + hsize_t idx; + H5T_class_t tclass; + char data[128]; + char ph_name[1024]; + info_type op_data; + herr_t iRet_iNX=-1; + char pBuffer[256]; + + pFile = NXI5assert (fid); + op_data.iname = NULL; + + /* + iterate to next entry in group list + */ + idx=pFile->iStack5[pFile->iStackPtr].iCurrentIDX; + if (strlen(pFile->name_ref) == 0) { + /* root group */ + strcpy(pFile->name_ref,"/"); + } + grp = H5Gopen(pFile->iFID, pFile->name_ref, H5P_DEFAULT); + // index can be wrong here + iRet=H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, &idx, nxgroup_info, &op_data); + H5Gclose(grp); + strcpy(nxclass, NX_UNKNOWN_GROUP); + + /* + figure out the number of items in the current group. We need this in order to + find out if we are at the end of the search. + */ + if (pFile->iCurrentG == 0) { + // if pFile->iCurrentG == 0 would not pFile->name_ref be "/" already, so we could skip that if statement ? + pFile->iNX=0; + grp = H5Gopen(pFile->iFID, "/", H5P_DEFAULT); + iRet_iNX=H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1, &pFile->iNX); + H5Gclose(grp); + } else { + pFile->iNX=0; + grp = H5Gopen(pFile->iFID, pFile->name_ref, H5P_DEFAULT); + // index can be wrong here + iRet_iNX=H5Literate(grp, H5_INDEX_NAME, H5_ITER_INC, 0, group_info1, &pFile->iNX); + H5Gclose(grp); } - NXIReportError(NXpData, - "ERROR: Iteration (directory) was not successful"); - return NX_ERROR; - } -} + if (idx == pFile->iNX) { + // why 2? + iRet_iNX = 2; + } + + if (iRet > 0) + { + pFile->iStack5[pFile->iStackPtr].iCurrentIDX++; + if (op_data.iname != NULL) { + strcpy(name,op_data.iname); + free(op_data.iname); + } else { + pFile->iStack5[pFile->iStackPtr].iCurrentIDX = 0; + return NX_EOD; + } + if (op_data.type == H5O_TYPE_GROUP) { + /* + open group and find class name attribute + */ + strcpy(ph_name,""); + for(i = 1; i < (pFile->iStackPtr + 1); i++) + { + strcat(ph_name,pFile->iStack5[i].irefn); + strcat(ph_name,"/"); + } + strcat(ph_name,name); + grp = H5Gopen(pFile->iFID,ph_name, H5P_DEFAULT); + if (grp < 0) { + sprintf(pBuffer, "ERROR: group %s does not exist", ph_name); + NXReportError(pBuffer); + return NX_ERROR; + } + attr1 = H5Aopen_by_name(grp,".", "NX_class", H5P_DEFAULT, H5P_DEFAULT); + if (attr1 < 0) { + strcpy(nxclass, NX_UNKNOWN_GROUP); + } else { + type=H5T_C_S1; + atype=H5Tcopy(type); + H5Tset_size(atype,sizeof(data)); + iRet = H5Aread(attr1, atype, data); + strcpy(nxclass,data); + H5Tclose(atype); + H5Aclose(attr1); + } + H5Gclose(grp); + } else if (op_data.type==H5O_TYPE_DATASET) { + /* + open dataset and find type + */ + grp=H5Dopen(pFile->iCurrentG,name, H5P_DEFAULT); + type=H5Dget_type(grp); + atype=H5Tcopy(type); + tclass = H5Tget_class(atype); + iPtype = hdf5ToNXType(tclass, atype); + *datatype=iPtype; + strcpy(nxclass, "SDS"); + H5Tclose(atype); + H5Tclose(type); + H5Dclose(grp); + } + return NX_OK; + } else { + /* + we are at the end of the search: clear the data structure and reset + iCurrentIDX to 0 + */ + if (iRet_iNX == 2) { + if (op_data.iname != NULL) { + free(op_data.iname); + } + pFile->iStack5[pFile->iStackPtr].iCurrentIDX = 0; + return NX_EOD; + } + if (op_data.iname != NULL) { + free(op_data.iname); + } + NXReportError("ERROR: iterating through group not successful"); + return NX_ERROR; + } + } /*-------------------------------------------------------------------------*/ -NXstatus NX5getdata(NXhandle fid, void *data) -{ - pNexusFile5 pFile; - int iStart[H5S_MAX_RANK], status; - hid_t data_id, memtype_id, size_id, sign_id; - int dims; + NXstatus NX5getdata (NXhandle fid, void *data) + { + pNexusFile5 pFile; + int iStart[H5S_MAX_RANK], status; + hid_t memtype_id; + H5T_class_t tclass; + int dims; - pFile = NXI5assert(fid); - /* check if there is an Dataset open */ - if (pFile->iCurrentD == 0) { - NXIReportError(NXpData, "ERROR: no Dataset open"); - return NX_ERROR; - } - memset(iStart, 0, H5S_MAX_RANK * sizeof(int)); - /* map datatypes of other plateforms */ - data_id = H5Tget_class(pFile->iCurrentT); - if (data_id == H5T_STRING) { - dims = H5Tget_size(pFile->iCurrentT); - memtype_id = H5Tcopy(H5T_C_S1); - H5Tset_size(memtype_id, dims); - } else { - memtype_id = h5MemType(pFile->iCurrentT); - } + pFile = NXI5assert (fid); + /* check if there is an Dataset open */ + if (pFile->iCurrentD == 0) + { + NXReportError( "ERROR: no dataset open"); + return NX_ERROR; + } + memset (iStart, 0, H5S_MAX_RANK * sizeof(int)); + /* map datatypes of other plateforms */ + tclass = H5Tget_class(pFile->iCurrentT); + if (tclass==H5T_STRING) + { + dims = H5Tget_size(pFile->iCurrentT); + memtype_id = H5Tcopy(H5T_C_S1); + H5Tset_size(memtype_id, dims); + } + else + { + memtype_id = h5MemType(pFile->iCurrentT); + } - /* actually read */ - status = H5Dread(pFile->iCurrentD, memtype_id, - H5S_ALL, H5S_ALL, H5P_DEFAULT, data); - if (data_id == H5T_STRING) { - H5Tclose(memtype_id); - } - if (status < 0) { - NXIReportError(NXpData, "ERROR: failed to transfer dataset"); - return NX_ERROR; + /* actually read */ + status = H5Dread (pFile->iCurrentD, memtype_id, + H5S_ALL, H5S_ALL,H5P_DEFAULT, data); + if(tclass == H5T_STRING) + { + H5Tclose(memtype_id); + } + if(status < 0) + { + NXReportError( "ERROR: failed to transfer dataset"); + return NX_ERROR; - } - return NX_OK; -} + } + return NX_OK; + } /*-------------------------------------------------------------------------*/ -NXstatus NX5getinfo(NXhandle fid, int *rank, int dimension[], int *iType) -{ - pNexusFile5 pFile; - int i, iRank, mType, iRet; - hsize_t myDim[H5S_MAX_RANK]; - hid_t data_id, size_id, sign_id; + NXstatus NX5getinfo64 (NXhandle fid, int *rank, int64_t dimension[], int *iType) + { + pNexusFile5 pFile; + int i, iRank, mType; + hsize_t myDim[H5S_MAX_RANK]; + H5T_class_t tclass; - pFile = NXI5assert(fid); - /* check if there is an Dataset open */ - if (pFile->iCurrentD == 0) { - NXIReportError(NXpData, "ERROR: no Dataset open"); - return NX_ERROR; - } + pFile = NXI5assert (fid); + /* check if there is an Dataset open */ + if (pFile->iCurrentD == 0) { + NXReportError( "ERROR: no dataset open"); + return NX_ERROR; + } - /* read information */ - data_id = H5Tget_class(pFile->iCurrentT); - mType = hdf5ToNXType(data_id, pFile->iCurrentT); - iRank = H5Sget_simple_extent_ndims(pFile->iCurrentS); - iRet = H5Sget_simple_extent_dims(pFile->iCurrentS, myDim, NULL); - /* conversion to proper ints for the platform */ - *iType = (int) mType; - if (data_id == H5T_STRING && myDim[iRank - 1] == 1) { - myDim[iRank - 1] = H5Tget_size(pFile->iCurrentT); - } - *rank = (int) iRank; - for (i = 0; i < iRank; i++) { - dimension[i] = (int) myDim[i]; - } - return NX_OK; -} + /* read information */ + tclass = H5Tget_class(pFile->iCurrentT); + mType = hdf5ToNXType(tclass,pFile->iCurrentT); + iRank = H5Sget_simple_extent_ndims(pFile->iCurrentS); + H5Sget_simple_extent_dims(pFile->iCurrentS, myDim, NULL); + /* conversion to proper ints for the platform */ + *iType = (int)mType; + if (tclass==H5T_STRING && myDim[iRank-1] == 1) { + myDim[iRank-1] = H5Tget_size(pFile->iCurrentT); + } + *rank = (int)iRank; + for (i = 0; i < iRank; i++) + { + dimension[i] = (int)myDim[i]; + } + return NX_OK; + } /*-------------------------------------------------------------------------*/ -NXstatus NX5getslab(NXhandle fid, void *data, int iStart[], int iSize[]) -{ - pNexusFile5 pFile; - hsize_t myStart[H5S_MAX_RANK]; - hsize_t mySize[H5S_MAX_RANK]; - hsize_t mStart[H5S_MAX_RANK]; - hid_t memspace, iRet, data_id; - hid_t memtype_id, size_id, sign_id; - char *tmp_data = NULL; - char *data1; - int i, dims, iRank, mtype = 0; + NXstatus NX5getslab64 (NXhandle fid, void *data, const int64_t iStart[], const int64_t iSize[]) + { + pNexusFile5 pFile; + hsize_t myStart[H5S_MAX_RANK]; + hsize_t mySize[H5S_MAX_RANK]; + hsize_t mStart[H5S_MAX_RANK]; + hid_t memspace, iRet; + H5T_class_t tclass; + hid_t memtype_id; + char *tmp_data = NULL; + char *data1; + int i, dims, iRank, mtype = 0; - pFile = NXI5assert(fid); - /* check if there is an Dataset open */ - if (pFile->iCurrentD == 0) { - NXIReportError(NXpData, "ERROR: no Dataset open"); - return NX_ERROR; - } - iRank = H5Sget_simple_extent_ndims(pFile->iCurrentS); - for (i = 0; i < iRank; i++) { - myStart[i] = (hssize_t) iStart[i]; - mySize[i] = (hsize_t) iSize[i]; - mStart[i] = (hsize_t) 0; - } - data_id = H5Tget_class(pFile->iCurrentT); - if (data_id == H5T_STRING) { + pFile = NXI5assert (fid); + /* check if there is an Dataset open */ + if (pFile->iCurrentD == 0) + { + NXReportError( "ERROR: no dataset open"); + return NX_ERROR; + } + iRank = H5Sget_simple_extent_ndims(pFile->iCurrentS); + for (i = 0; i < iRank; i++) + { + myStart[i] = (hssize_t)iStart[i]; + mySize[i] = (hsize_t)iSize[i]; + mStart[i] = (hsize_t)0; + } + tclass = H5Tget_class(pFile->iCurrentT); + if (tclass == H5T_STRING) { /* * FAA 24/1/2007: I don't think this will work for multidimensional * string arrays. * MK 23/7/2007: You are right Freddie. */ - mtype = NX_CHAR; - if (mySize[0] == 1) { - mySize[0] = H5Tget_size(pFile->iCurrentT); - } - tmp_data = (char *) malloc(mySize[0]); - memset(tmp_data, 0, sizeof(mySize[0])); - iRet = H5Sselect_hyperslab(pFile->iCurrentS, H5S_SELECT_SET, mStart, - NULL, mySize, NULL); - } else { - iRet = H5Sselect_hyperslab(pFile->iCurrentS, H5S_SELECT_SET, myStart, - NULL, mySize, NULL); - } - /* define slab */ - /* deal with HDF errors */ - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: selecting slab failed"); - return NX_ERROR; - } + mtype = NX_CHAR; + if (mySize[0] == 1) { + mySize[0] = H5Tget_size(pFile->iCurrentT); + } + tmp_data = (char*) malloc(mySize[0]); + memset(tmp_data,0,sizeof(mySize[0])); + iRet = H5Sselect_hyperslab(pFile->iCurrentS, H5S_SELECT_SET, mStart, + NULL, mySize, NULL); + } else { + iRet = H5Sselect_hyperslab(pFile->iCurrentS, H5S_SELECT_SET, myStart, + NULL, mySize, NULL); + } + /* define slab */ + /* deal with HDF errors */ + if (iRet < 0) + { + NXReportError( "ERROR: selecting slab failed"); + return NX_ERROR; + } - memspace = H5Screate_simple(iRank, mySize, NULL); - iRet = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, mStart, - NULL, mySize, NULL); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: Select memspace failed"); - return NX_ERROR; - } - /* map datatypes of other plateforms */ - if (data_id == H5T_STRING) { - dims = H5Tget_size(pFile->iCurrentT); - memtype_id = H5Tcopy(H5T_C_S1); - H5Tset_size(memtype_id, dims); - } else { - memtype_id = h5MemType(pFile->iCurrentT); - } + memspace=H5Screate_simple(iRank, mySize, NULL); + iRet = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, mStart, + NULL, mySize, NULL); + if (iRet < 0) + { + NXReportError( "ERROR: selecting memspace failed"); + return NX_ERROR; + } + /* map datatypes of other plateforms */ + if (tclass == H5T_STRING) + { + dims = H5Tget_size(pFile->iCurrentT); + memtype_id = H5Tcopy(H5T_C_S1); + H5Tset_size(memtype_id, dims); + } + else + { + memtype_id = h5MemType(pFile->iCurrentT); + } - /* read slab */ - if (mtype == NX_CHAR) { - iRet = H5Dread(pFile->iCurrentD, memtype_id, H5S_ALL, - H5S_ALL, H5P_DEFAULT, tmp_data); - data1 = tmp_data + myStart[0]; - strncpy(data, data1, (hsize_t) iSize[0]); - free(tmp_data); - } else { - iRet = H5Dread(pFile->iCurrentD, memtype_id, memspace, - pFile->iCurrentS, H5P_DEFAULT, data); - } + /* read slab */ + if (mtype == NX_CHAR) { + iRet = H5Dread(pFile->iCurrentD, memtype_id, H5S_ALL, + H5S_ALL, H5P_DEFAULT,tmp_data); + data1 = tmp_data + myStart[0]; + strncpy((char*)data,data1,(hsize_t)iSize[0]); + free(tmp_data); + } else { + iRet = H5Dread(pFile->iCurrentD, memtype_id, memspace, + pFile->iCurrentS, H5P_DEFAULT,data); + } + /* cleanup */ + if (tclass == H5T_STRING) { /* we used H5Tcopy */ + H5Tclose(memtype_id); + } + H5Sclose(memspace); - if (iRet < 0) { - NXIReportError(NXpData, "ERROR: Reading slab failed"); - return NX_ERROR; - } - return NX_OK; -} + if (iRet < 0) + + { + NXReportError( "ERROR: reading slab failed"); + return NX_ERROR; + } + return NX_OK; + } /*-------------------------------------------------------------------------*/ /* Operator function. */ -herr_t attr_info(hid_t loc_id, const char *name, void *opdata) -{ - *((char **) opdata) = strdup(name); - return 1; -} + herr_t attr_info(hid_t loc_id, const char *name, const H5A_info_t *unused, void *opdata) + { + *((char**)opdata)=strdup(name); + return 1; + } -NXstatus NX5getnextattr(NXhandle fileid, NXname pName, - int *iLength, int *iType) -{ - pNexusFile5 pFile; - hid_t attr_id, size_id, sign_id; - hid_t iRet, atype, aspace; - int iPType, rank; - char *iname = NULL; - unsigned int idx; - int intern_idx = -1; - int vid; + NXstatus NX5getnextattr (NXhandle fileid, NXname pName, int *iLength, int *iType) + { + pNexusFile5 pFile; + hid_t attr_id; + hid_t atype, aspace; + herr_t iRet; + int iPType,rank; + char *iname = NULL; + hsize_t idx, intern_idx=-1; + int vid; + H5O_info_t oinfo; + pFile = NXI5assert (fileid); - pFile = NXI5assert(fileid); + vid = getAttVID(pFile); - vid = getAttVID(pFile); + pName[0] = '\0'; + idx=pFile->iAtt5.iCurrentIDX; + iRet=0; + + H5Oget_info(vid, &oinfo); + intern_idx=oinfo.num_attrs; + if(intern_idx == idx) { + killAttVID(pFile,vid); + return NX_EOD; + } - idx = pFile->iAtt5.iCurrentIDX; - iRet = 0; - intern_idx = H5Aget_num_attrs(vid); - if (intern_idx == idx) { - killAttVID(pFile, vid); - return NX_EOD; - } - - if (intern_idx > idx) { - iRet = H5Aiterate(vid, &idx, attr_info, &iname); - } else { - iRet = 0; - } - intern_idx = -1; - if (iRet < 0) { - NXIReportError(NXpData, "ERROR iterating through attribute list!"); - killAttVID(pFile, vid); - return NX_ERROR; - } - pFile->iAtt5.iCurrentIDX++; - if (iname != NULL) { - if (strcmp(iname, "NX_class") == 0 && pFile->iCurrentG != 0) { - /* - skip NXclass attribute which is internal - */ - killAttVID(pFile, vid); - return NX5getnextattr(fileid, pName, iLength, iType); - } - strcpy(pName, iname); - free(iname); - iname = NULL; - } else { - strcpy(pName, "What is this?"); - } - pFile->iCurrentA = H5Aopen_name(vid, pName); - atype = H5Aget_type(pFile->iCurrentA); - aspace = H5Aget_space(pFile->iCurrentA); - rank = H5Sget_simple_extent_ndims(aspace); - attr_id = H5Tget_class(atype); - if (attr_id == H5T_STRING) { - iPType = NX_CHAR; - rank = H5Tget_size(atype); - } - if (rank == 0) { - rank++; - } - iPType = hdf5ToNXType(attr_id, atype); - *iType = iPType; - *iLength = rank; - H5Tclose(atype); - H5Sclose(aspace); - H5Aclose(pFile->iCurrentA); - - intern_idx = H5Aget_num_attrs(vid); - - killAttVID(pFile, vid); - return NX_OK; -} + if (intern_idx > idx) { + iRet=H5Aiterate(vid,H5_INDEX_CRT_ORDER,H5_ITER_INC,&idx,attr_info,&iname); + } else { + iRet=0; + } + intern_idx=-1; + if (iRet < 0) { + NXReportError( "ERROR: iterating through attribute list"); + killAttVID(pFile,vid); + return NX_ERROR; + } + pFile->iAtt5.iCurrentIDX++; + if (iname != NULL) { + if(strcmp(iname, "NX_class") == 0 && pFile->iCurrentG != 0) { + /* + skip NXclass attribute which is internal + */ + killAttVID(pFile, vid); + return NX5getnextattr(fileid, pName, iLength, iType); + } + strcpy(pName, iname); + free(iname); + iname = NULL; + } else { + strcpy(pName,"What is this?"); + } + pFile->iCurrentA = H5Aopen_by_name(vid, ".", pName, H5P_DEFAULT, H5P_DEFAULT); + atype = H5Aget_type(pFile->iCurrentA); + aspace = H5Aget_space(pFile->iCurrentA); + rank = H5Sget_simple_extent_ndims(aspace); + attr_id = H5Tget_class(atype); + if (attr_id==H5T_STRING) { + iPType=NX_CHAR; + rank = H5Tget_size(atype); + } + if (rank == 0) { + rank++; + } + iPType = hdf5ToNXType(attr_id,atype); + *iType=iPType; + *iLength=rank; + H5Tclose(atype); + H5Sclose(aspace); + H5Aclose(pFile->iCurrentA); + + H5Oget_info(vid, &oinfo); + intern_idx=oinfo.num_attrs; + killAttVID(pFile,vid); + return NX_OK; + } /*-------------------------------------------------------------------------*/ -NXstatus NX5getattr(NXhandle fid, char *name, - void *data, int *datalen, int *iType) -{ - pNexusFile5 pFile; - int iNew, iRet, vid; - hid_t type, atype = -1, glob; - char pBuffer[256]; + NXstatus NX5getattr (NXhandle fid, char *name, + void *data, int* datalen, int* iType) + { + pNexusFile5 pFile; + int iNew, vid; + herr_t iRet; + hid_t type, atype = -1; + char pBuffer[256]; - pFile = NXI5assert(fid); - type = *iType; - glob = 0; + pFile = NXI5assert (fid); - type = nxToHDF5Type(type); + type = nxToHDF5Type(*iType); - vid = getAttVID(pFile); - iNew = H5Aopen_name(vid, name); - if (iNew < 0) { - sprintf(pBuffer, "ERROR: attribute %s not found", name); - killAttVID(pFile, vid); - NXIReportError(NXpData, pBuffer); - return NX_ERROR; - } - pFile->iCurrentA = iNew; - /* finally read the data */ - if (type == H5T_C_S1) { - atype = H5Tcopy(type); - H5Tset_size(atype, *datalen); - iRet = H5Aread(pFile->iCurrentA, atype, data); - *datalen = strlen(data); - } else { - iRet = H5Aread(pFile->iCurrentA, type, data); - *datalen = 1; - } + vid = getAttVID(pFile); + iNew = H5Aopen_by_name(vid, ".", name, H5P_DEFAULT, H5P_DEFAULT); + if (iNew < 0) { + sprintf (pBuffer, "ERROR: attribute \"%s\" not found", name); + killAttVID(pFile,vid); + NXReportError( pBuffer); + return NX_ERROR; + } + pFile->iCurrentA = iNew; + /* finally read the data */ + if (type==H5T_C_S1) + { + atype = H5Aget_type(pFile->iCurrentA); + H5Tclose(atype); + atype=H5Tcopy(type); + H5Tset_size(atype,*datalen); + iRet = H5Aread(pFile->iCurrentA, atype, data); + *datalen = strlen((char*)data); + } else { + iRet = H5Aread(pFile->iCurrentA, type, data); + *datalen=1; + } - if (iRet < 0) { - sprintf(pBuffer, "ERROR: HDF could not read attribute data"); - NXIReportError(NXpData, pBuffer); - killAttVID(pFile, vid); - return NX_ERROR; - } + if (iRet < 0) { + sprintf (pBuffer, "ERROR: could not read attribute data"); + NXReportError( pBuffer); + killAttVID(pFile,vid); + return NX_ERROR; + } - iRet = H5Aclose(pFile->iCurrentA); + H5Aclose(pFile->iCurrentA); - killAttVID(pFile, vid); - if (type == H5T_C_S1) { - H5Tclose(atype); - } - return NX_OK; -} + killAttVID(pFile,vid); + if (type==H5T_C_S1) + { + H5Tclose(atype); + } + return NX_OK; + } /*-------------------------------------------------------------------------*/ -NXstatus NX5getattrinfo(NXhandle fid, int *iN) -{ - pNexusFile5 pFile; - char *iname = NULL; - unsigned int idx; - int vid; - herr_t iRet; + NXstatus NX5getattrinfo (NXhandle fid, int *iN) + { + pNexusFile5 pFile; + hid_t idx; + int vid; + H5O_info_t oinfo; + + pFile = NXI5assert (fid); + idx=0; + *iN = idx; - pFile = NXI5assert(fid); - idx = 0; - *iN = idx; + vid = getAttVID(pFile); - vid = getAttVID(pFile); - - idx = H5Aget_num_attrs(vid); - if (idx > 0) { - if (pFile->iCurrentG > 0 && pFile->iCurrentD == 0) { - *iN = idx - 1; - } else { - *iN = idx; - } - } else { - *iN = 0; - } - killAttVID(pFile, vid); - return NX_OK; -} + H5Oget_info(vid, &oinfo); + idx=oinfo.num_attrs; + if (idx > 0) { + if(pFile->iCurrentG > 0 && pFile->iCurrentD == 0){ + *iN = idx -1; + } else { + *iN = idx; + } + } else { + *iN = 0; + } + killAttVID(pFile,vid); + return NX_OK; + } /*-------------------------------------------------------------------------*/ -NXstatus NX5getgroupID(NXhandle fileid, NXlink * sRes) -{ - pNexusFile5 pFile; - int u, datalen, type = NX_CHAR; - char group_name[64], class_name[64]; - ErrFunc oldErr; - - pFile = NXI5assert(fileid); - if (pFile->iCurrentG == 0) { - return NX_ERROR; - } else { - /* - this means: if the item is already linked: use the target attribute, else - the path to the current node - */ - oldErr = NXMGetError(); - NXMSetError(NXpData, ignoreError); - datalen = 1024; - memset(sRes->targetPath, 0, datalen * sizeof(char)); - if (NX5getattr(fileid, "target", sRes->targetPath, &datalen, &type) != - NX_OK) { - buildCurrentPath(pFile, sRes->targetPath, 1024); + NXstatus NX5getgroupID (NXhandle fileid, NXlink* sRes) + { + pNexusFile5 pFile; + int datalen, type = NX_CHAR; + + pFile = NXI5assert (fileid); + if (pFile->iCurrentG == 0) { + return NX_ERROR; + } + else { + /* + this means: if the item is already linked: use the target attribute, else + the path to the current node + */ + NXMDisableErrorReporting(); + datalen = 1024; + memset(sRes->targetPath,0,datalen*sizeof(char)); + if(NX5getattr(fileid,"target",sRes->targetPath,&datalen,&type) != NX_OK){ + buildCurrentPath(pFile,sRes->targetPath,1024); + } + NXMEnableErrorReporting(); + sRes->linkType = 0; + return NX_OK; } - NXMSetError(NXpData, oldErr); - sRes->linkType = 0; - return NX_OK; - } - /* not reached */ - return NX_ERROR; -} - + /* not reached */ + return NX_ERROR; + } + /* ------------------------------------------------------------------- */ -NXstatus NX5sameID(NXhandle fileid, NXlink * pFirstID, NXlink * pSecondID) -{ - pNexusFile5 pFile; + NXstatus NX5nativeexternallink(NXhandle fileid, const char* name, const char* externalfile, const char* remotetarget) + { + herr_t iRet; + pNexusFile5 pFile; + hid_t openwhere; - pFile = NXI5assert(fileid); - if ((strcmp(pFirstID->targetPath, pSecondID->targetPath) == 0)) { - return NX_OK; - } else { - return NX_ERROR; + pFile = NXI5assert(fileid); + + if (pFile->iCurrentG <= 0) { + openwhere = pFile->iFID; + } else { + openwhere = pFile->iCurrentG; + } + + iRet = H5Lcreate_external(externalfile, remotetarget, openwhere, name, H5P_DEFAULT, H5P_DEFAULT); + if (iRet < 0) { + NXReportError("ERROR: making external link failed"); + return NX_ERROR; + } + return NX_OK; } -} + /* ------------------------------------------------------------------- */ + NXstatus NX5nativeinquirefile(NXhandle fileid, char* externalfile, const int filenamelen) + { + pNexusFile5 pFile; + ssize_t name_size; + hid_t openthing; + + pFile = NXI5assert(fileid); + if (pFile->iCurrentD > 0) { + openthing = pFile->iCurrentD; + } else if (pFile->iCurrentG > 0) { + openthing = pFile->iCurrentG; + } else { + openthing = pFile->iFID; + } + + name_size = H5Fget_name(openthing, externalfile, filenamelen); + + // Check for failure again + if( name_size < 0 ) { + NXReportError("ERROR: retrieving file name"); + return NX_ERROR; + } + return NX_OK; + } + /* ------------------------------------------------------------------- */ + + NXstatus NX5nativeisexternallink(NXhandle fileid, const char* name, char* url, const int urllen) + { + pNexusFile5 pFile; + herr_t ret; + H5L_info_t link_buff; + char linkval_buff[1024]; + const char *filepath = NULL, *objpath = NULL; + size_t val_size; + + pFile = NXI5assert(fileid); + memset(url, 0, urllen); + + ret = H5Lget_info(pFile->iFID, name, &link_buff, H5P_DEFAULT); + if (ret < 0 || link_buff.type != H5L_TYPE_EXTERNAL) { + return NX_ERROR; + } + + val_size = link_buff.u.val_size; + if (val_size > sizeof(linkval_buff)) { + NXReportError("ERROR: linkval_buff too small"); + return NX_ERROR; + } + + ret = H5Lget_val(pFile->iFID, name, linkval_buff, val_size, H5P_DEFAULT); + if (ret < 0) { + NXReportError("ERROR: H5Lget_val failed"); + return NX_ERROR; + } + + ret = H5Lunpack_elink_val(linkval_buff, val_size, NULL, &filepath, &objpath); + if (ret < 0) { + NXReportError("ERROR: H5Lunpack_elink_val failed"); + return NX_ERROR; + } + + snprintf(url, urllen-1, "nxfile://%s#%s", filepath, objpath); + return NX_OK; + + } + /* ------------------------------------------------------------------- */ + + NXstatus NX5sameID (NXhandle fileid, NXlink* pFirstID, NXlink* pSecondID) + { + NXI5assert(fileid); + if ((strcmp(pFirstID->targetPath,pSecondID->targetPath) == 0)){ + return NX_OK; + } else { + return NX_ERROR; + } + } + /*-------------------------------------------------------------------------*/ - -NXstatus NX5initattrdir(NXhandle fid) -{ - pNexusFile5 pFile; - - pFile = NXI5assert(fid); - NXI5KillAttDir(fid); - return NX_OK; -} + + NXstatus NX5initattrdir (NXhandle fid) + { + pNexusFile5 pFile; + + pFile = NXI5assert (fid); + NXI5KillAttDir (pFile); + return NX_OK; + } /*-------------------------------------------------------------------------*/ - -NXstatus NX5initgroupdir(NXhandle fid) -{ - pNexusFile5 pFile; - - pFile = NXI5assert(fid); - NXI5KillDir(fid); - return NX_OK; -} - + + NXstatus NX5initgroupdir (NXhandle fid) + { + pNexusFile5 pFile; + + pFile = NXI5assert (fid); + NXI5KillDir (pFile); + return NX_OK; + } /*------------------------------------------------------------------------*/ void NX5assignFunctions(pNexusFunction fHandle) { - - fHandle->nxclose = NX5close; - fHandle->nxflush = NX5flush; - fHandle->nxmakegroup = NX5makegroup; - fHandle->nxopengroup = NX5opengroup; - fHandle->nxclosegroup = NX5closegroup; - fHandle->nxmakedata = NX5makedata; - fHandle->nxcompmakedata = NX5compmakedata; - fHandle->nxcompress = NX5compress; - fHandle->nxopendata = NX5opendata; - fHandle->nxclosedata = NX5closedata; - fHandle->nxputdata = NX5putdata; - fHandle->nxputattr = NX5putattr; - fHandle->nxputslab = NX5putslab; - fHandle->nxgetdataID = NX5getdataID; - fHandle->nxmakelink = NX5makelink; - fHandle->nxmakenamedlink = NX5makenamedlink; - fHandle->nxgetdata = NX5getdata; - fHandle->nxgetinfo = NX5getinfo; - fHandle->nxgetnextentry = NX5getnextentry; - fHandle->nxgetslab = NX5getslab; - fHandle->nxgetnextattr = NX5getnextattr; - fHandle->nxgetattr = NX5getattr; - fHandle->nxgetattrinfo = NX5getattrinfo; - fHandle->nxgetgroupID = NX5getgroupID; - fHandle->nxgetgroupinfo = NX5getgroupinfo; - fHandle->nxsameID = NX5sameID; - fHandle->nxinitgroupdir = NX5initgroupdir; - fHandle->nxinitattrdir = NX5initattrdir; - fHandle->nxprintlink = NX5printlink; + + fHandle->nxclose=NX5close; + fHandle->nxreopen=NX5reopen; + fHandle->nxflush=NX5flush; + fHandle->nxmakegroup=NX5makegroup; + fHandle->nxopengroup=NX5opengroup; + fHandle->nxclosegroup=NX5closegroup; + fHandle->nxmakedata64=NX5makedata64; + fHandle->nxcompmakedata64=NX5compmakedata64; + fHandle->nxcompress=NX5compress; + fHandle->nxopendata=NX5opendata; + fHandle->nxclosedata=NX5closedata; + fHandle->nxputdata=NX5putdata; + fHandle->nxputattr=NX5putattr; + fHandle->nxputslab64=NX5putslab64; + fHandle->nxgetdataID=NX5getdataID; + fHandle->nxmakelink=NX5makelink; + fHandle->nxmakenamedlink=NX5makenamedlink; + fHandle->nxgetdata=NX5getdata; + fHandle->nxgetinfo64=NX5getinfo64; + fHandle->nxgetnextentry=NX5getnextentry; + fHandle->nxgetslab64=NX5getslab64; + fHandle->nxgetnextattr=NX5getnextattr; + fHandle->nxgetattr=NX5getattr; + fHandle->nxgetattrinfo=NX5getattrinfo; + fHandle->nxgetgroupID=NX5getgroupID; + fHandle->nxgetgroupinfo=NX5getgroupinfo; + fHandle->nxsameID=NX5sameID; + fHandle->nxinitgroupdir=NX5initgroupdir; + fHandle->nxinitattrdir=NX5initattrdir; + fHandle->nxprintlink=NX5printlink; + fHandle->nxnativeexternallink=NX5nativeexternallink; + fHandle->nxnativeinquirefile=NX5nativeinquirefile; + fHandle->nxnativeisexternallink=NX5nativeisexternallink; } + +#endif /* HDF5 */ diff --git a/napi5.h b/napi5.h index 2ee47d98..79490782 100644 --- a/napi5.h +++ b/napi5.h @@ -1,61 +1,54 @@ +#ifndef NAPI5_H +#define NAPI5_H + #define NX5SIGNATURE 959695 #include /* HDF5 interface */ -extern NXstatus NX5open(CONSTCHAR * filename, NXaccess access_method, - NXhandle * pHandle); -extern NXstatus NX5close(NXhandle * pHandle); -extern NXstatus NX5flush(NXhandle * pHandle); +extern NXstatus NX5open(CONSTCHAR *filename, NXaccess access_method, NXhandle* pHandle); +extern NXstatus NX5reopen(NXhandle pOrigHandle, NXhandle* pNewHandle); -extern NXstatus NX5makegroup(NXhandle handle, CONSTCHAR * name, - CONSTCHAR * NXclass); -extern NXstatus NX5opengroup(NXhandle handle, CONSTCHAR * name, - CONSTCHAR * NXclass); -extern NXstatus NX5closegroup(NXhandle handle); +extern NXstatus NX5close(NXhandle* pHandle); +extern NXstatus NX5flush(NXhandle* pHandle); + +extern NXstatus NX5makegroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); +extern NXstatus NX5opengroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); +extern NXstatus NX5closegroup(NXhandle handle); + +extern NXstatus NX5makedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[]); +extern NXstatus NX5compmakedata64 (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int64_t dim[], int comp_typ, int64_t bufsize[]); +extern NXstatus NX5compress (NXhandle handle, int compr_type); +extern NXstatus NX5opendata (NXhandle handle, CONSTCHAR* label); +extern NXstatus NX5closedata(NXhandle handle); +extern NXstatus NX5putdata(NXhandle handle, const void* data); -extern NXstatus NX5makedata(NXhandle handle, CONSTCHAR * label, - int datatype, int rank, int dim[]); -extern NXstatus NX5compmakedata(NXhandle handle, CONSTCHAR * label, - int datatype, int rank, int dim[], - int comp_typ, int bufsize[]); -extern NXstatus NX5compress(NXhandle handle, int compr_type); -extern NXstatus NX5opendata(NXhandle handle, CONSTCHAR * label); -extern NXstatus NX5closedata(NXhandle handle); -extern NXstatus NX5putdata(NXhandle handle, void *data); +extern NXstatus NX5putattr(NXhandle handle, CONSTCHAR* name, const void* data, int iDataLen, int iType); +extern NXstatus NX5putslab64(NXhandle handle, const void* data, const int64_t start[], const int64_t size[]); -extern NXstatus NX5putattr(NXhandle handle, CONSTCHAR * name, void *data, - int iDataLen, int iType); -extern NXstatus NX5putslab(NXhandle handle, void *data, int start[], - int size[]); +extern NXstatus NX5getdataID(NXhandle handle, NXlink* pLink); +extern NXstatus NX5makelink(NXhandle handle, NXlink* pLink); +extern NXstatus NX5printlink(NXhandle handle, NXlink* pLink); -extern NXstatus NX5getdataID(NXhandle handle, NXlink * pLink); -extern NXstatus NX5makelink(NXhandle handle, NXlink * pLink); -extern NXstatus NX5printlink(NXhandle handle, NXlink * pLink); +extern NXstatus NX5getdata(NXhandle handle, void* data); +extern NXstatus NX5getinfo64(NXhandle handle, int* rank, int64_t dimension[], int* datatype); +extern NXstatus NX5getnextentry(NXhandle handle, NXname name, NXname nxclass, int* datatype); -extern NXstatus NX5getdata(NXhandle handle, void *data); -extern NXstatus NX5getinfo(NXhandle handle, int *rank, int dimension[], - int *datatype); -extern NXstatus NX5getnextentry(NXhandle handle, NXname name, - NXname nxclass, int *datatype); +extern NXstatus NX5getslab64(NXhandle handle, void* data, const int64_t start[], const int64_t size[]); +extern NXstatus NX5getnextattr(NXhandle handle, NXname pName, int *iLength, int *iType); +extern NXstatus NX5getattr(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); +extern NXstatus NX5getattrinfo(NXhandle handle, int* no_items); +extern NXstatus NX5getgroupID(NXhandle handle, NXlink* pLink); +extern NXstatus NX5getgroupinfo(NXhandle handle, int* no_items, NXname name, NXname nxclass); -extern NXstatus NX5getslab(NXhandle handle, void *data, int start[], - int size[]); -extern NXstatus NX5getnextattr(NXhandle handle, NXname pName, int *iLength, - int *iType); -extern NXstatus NX5getattr(NXhandle handle, char *name, void *data, - int *iDataLen, int *iType); -extern NXstatus NX5getattrinfo(NXhandle handle, int *no_items); -extern NXstatus NX5getgroupID(NXhandle handle, NXlink * pLink); -extern NXstatus NX5getgroupinfo(NXhandle handle, int *no_items, - NXname name, NXname nxclass); - -extern NXstatus NX5initgroupdir(NXhandle handle); -extern NXstatus NX5initattrdir(NXhandle handle); +extern NXstatus NX5initgroupdir(NXhandle handle); +extern NXstatus NX5initattrdir(NXhandle handle); void NX5assignFunctions(pNexusFunction fHandle); -herr_t nxgroup_info(hid_t loc_id, const char *name, void *op_data); -herr_t attr_info(hid_t loc_id, const char *name, void *opdata); -herr_t group_info(hid_t loc_id, const char *name, void *opdata); +herr_t attr_info(hid_t loc_id, const char *name, const H5A_info_t *unused, void *opdata); +herr_t group_info(hid_t loc_id, const char *name, const H5L_info_t *unused, void *opdata); +herr_t nxgroup_info(hid_t loc_id, const char *name, const H5L_info_t *unused, void *op_data); + +#endif /* NAPI5_H */ diff --git a/napiconfig.h b/napiconfig.h index e2608f3b..4282838a 100755 --- a/napiconfig.h +++ b/napiconfig.h @@ -1,22 +1,28 @@ #ifndef NAPICONFIG_H #define NAPICONFIG_H +#ifdef _WIN32 +#include +#endif /* _WIN32 */ + +#ifdef __VMS +#include +#else #include +#endif /* __VMS */ + /* - * Type definitions + * Integer type definitions + * + * int32_t etc will be defined by configure in nxconfig.h + * if they exist; otherwise include an appropriate header */ -#ifdef HAVE_STDINT_H +#if HAVE_STDINT_H #include -#else -typedef signed char int8_t; -typedef short int int16_t; -typedef int int32_t; -typedef long int64_t; -typedef unsigned char uint8_t; -typedef unsigned short int uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long uint64_t; +#elif HAVE_INTTYPES_H +#include +#endif /* HAVE_STDINT_H */ -#endif /* HAVE_STDINT_H */ -#endif /* NAPICONFIG_H */ + +#endif /* NAPICONFIG_H */ diff --git a/napiu.c b/napiu.c index 2f40cab3..63ad8c22 100644 --- a/napiu.c +++ b/napiu.c @@ -21,10 +21,10 @@ For further information, see - $Id: napiu.c,v 1.3 2009/02/13 09:00:20 koennecke Exp $ + $Id: napiu.c,v 1.4 2012/03/29 08:41:06 koennecke Exp $ ----------------------------------------------------------------------------*/ -static const char *rscid = "$Id: napiu.c,v 1.3 2009/02/13 09:00:20 koennecke Exp $"; /* Revision interted by CVS */ +static const char* rscid = "$Id: napiu.c,v 1.4 2012/03/29 08:41:06 koennecke Exp $"; /* Revision interted by CVS */ #include #include @@ -41,130 +41,120 @@ static const char *rscid = "$Id: napiu.c,v 1.3 2009/02/13 09:00:20 koennecke Exp } \ } -NXstatus NXUwriteglobals(NXhandle file_id, const char *user, - const char *affiliation, const char *address, - const char *telephone_number, - const char *fax_number, const char *email) -{ - DO_GLOBAL(user); - DO_GLOBAL(affiliation); - DO_GLOBAL(address); - DO_GLOBAL(telephone_number); - DO_GLOBAL(fax_number); - DO_GLOBAL(email); - return NX_OK; -} + NXstatus NXUwriteglobals(NXhandle file_id, const char* user, const char* affiliation, const char* address, const char* telephone_number, const char* fax_number, const char* email) + { + DO_GLOBAL(user); + DO_GLOBAL(affiliation); + DO_GLOBAL(address); + DO_GLOBAL(telephone_number); + DO_GLOBAL(fax_number); + DO_GLOBAL(email); + return NX_OK; + } /* NXUwritegroup creates and leaves open a group */ -NXstatus NXUwritegroup(NXhandle file_id, const char *group_name, - const char *group_class) -{ - int status; - status = NXmakegroup(file_id, group_name, group_class); - if (status == NX_OK) { - status = NXopengroup(file_id, group_name, group_class); - } - return status; -} + NXstatus NXUwritegroup(NXhandle file_id, const char* group_name, const char* group_class) + { + int status; + status = NXmakegroup(file_id, group_name, group_class); + if (status == NX_OK) + { + status = NXopengroup(file_id, group_name, group_class); + } + return status; + } -NXstatus NXUwritedata(NXhandle file_id, const char *data_name, - const void *data, int data_type, int rank, - const int dim[], const char *units, - const int start[], const int size[]) -{ - return NX_OK; -} + NXstatus NXUwritedata(NXhandle file_id, const char* data_name, const void* data, int data_type, int rank, const int dim[], const char* units, const int start[], const int size[]) + { + return NX_OK; + } -NXstatus NXUreaddata(NXhandle file_id, const char *data_name, void *data, - char *units, const int start[], const int size[]) -{ - return NX_OK; -} + NXstatus NXUreaddata(NXhandle file_id, const char* data_name, void* data, char* units, const int start[], const int size[]) + { + return NX_OK; + } -NXstatus NXUwritehistogram(NXhandle file_id, const char *data_name, - const void *data, const char *units) -{ - return NX_OK; -} + NXstatus NXUwritehistogram(NXhandle file_id, const char* data_name, const void* data, const char* units) + { + return NX_OK; + } -NXstatus NXUreadhistogram(NXhandle file_id, const char *data_name, - void *data, char *units) -{ - return NX_OK; -} + NXstatus NXUreadhistogram(NXhandle file_id, const char* data_name, void* data, char* units) + { + return NX_OK; + } static int NXcompress_type = 0; static int NXcompress_size = 0; /* NXUsetcompress sets the default compression type and minimum size */ -NXstatus NXUsetcompress(NXhandle file_id, int comp_type, int comp_size) -{ - int status; - if (comp_type == NX_COMP_LZW || comp_type == NX_COMP_HUF || - comp_type == NX_COMP_RLE || comp_type == NX_COMP_NONE) { - NXcompress_type = comp_type; - if (comp_size != 0) { - NXcompress_size = comp_size; - } - status = NX_OK; - } else { - NXIReportError(NXpData, "Invalid compression option"); - status = NX_ERROR; - } - return status; -} + NXstatus NXUsetcompress(NXhandle file_id, int comp_type, int comp_size) + { + int status; + if (comp_type == NX_COMP_LZW || comp_type == NX_COMP_HUF || + comp_type == NX_COMP_RLE || comp_type == NX_COMP_NONE) + { + NXcompress_type = comp_type; + if (comp_size != 0) + { + NXcompress_size = comp_size; + } + status = NX_OK; + } + else + { + NXReportError( "Invalid compression option"); + status = NX_ERROR; + } + return status; + } - /* !NXUfindgroup finds if a NeXus group of the specified name exists */ -NXstatus NXUfindgroup(NXhandle file_id, const char *group_name, - char *group_class) -{ - int status, n; - NXname vname, vclass; - status = NXgetgroupinfo(file_id, &n, vname, vclass); - if (status != NX_OK) { - return status; - } - return NX_OK; -} + /* !NXUfindgroup finds if a NeXus group of the specified name exists */ + NXstatus NXUfindgroup(NXhandle file_id, const char* group_name, char* group_class) + { + int status, n; + NXname vname, vclass; + status = NXgetgroupinfo(file_id, &n, vname, vclass); + if (status != NX_OK) + { + return status; + } + return NX_OK; + } -NXstatus NXUfindclass(NXhandle file_id, const char *group_class, - char *group_name, int find_index) -{ - return NX_OK; -} + NXstatus NXUfindclass(NXhandle file_id, const char* group_class, char* group_name, int find_index) + { + return NX_OK; + } /* NXUfinddata finds if a NeXus data item is in the current group */ -NXstatus NXUfinddata(NXhandle file_id, const char *data_name) -{ - return NX_OK; -} + NXstatus NXUfinddata(NXhandle file_id, const char* data_name) + { + return NX_OK; + } -NXstatus NXUfindattr(NXhandle file_id, const char *attr_name) -{ - return NX_OK; -} + NXstatus NXUfindattr(NXhandle file_id, const char* attr_name) + { + return NX_OK; + } -NXstatus NXUfindsignal(NXhandle file_id, int signal, char *data_name, - int *data_rank, int *data_type, - int data_dimensions[]) -{ - return NX_OK; -} + NXstatus NXUfindsignal(NXhandle file_id, int signal, char* data_name, int* data_rank, int* data_type, int data_dimensions[]) + { + return NX_OK; + } -NXstatus NXUfindaxis(NXhandle file_id, int axis, int primary, - char *data_name, int *data_rank, int *data_type, - int data_dimensions[]) -{ - return NX_OK; -} + NXstatus NXUfindaxis(NXhandle file_id, int axis, int primary, char* data_name, int* data_rank, int* data_type, int data_dimensions[]) + { + return NX_OK; + } -NXstatus NXUfindlink(NXhandle file_id, NXlink * group_id, - const char *group_class) -{ - return NX_OK; -} + NXstatus NXUfindlink(NXhandle file_id, NXlink* group_id, const char* group_class) + { + return NX_OK; + } + + NXstatus NXUresumelink(NXhandle file_id, NXlink group_id) + { + return NX_OK; + } -NXstatus NXUresumelink(NXhandle file_id, NXlink group_id) -{ - return NX_OK; -} diff --git a/nread.c b/nread.c index 36c77645..b4676c9a 100644 --- a/nread.c +++ b/nread.c @@ -700,10 +700,13 @@ int NetReaderTask(void *pData) GetCharArray(self->conList)); } + /* + * This costs a surprising amount of CPU-time, in a test 10%! + * This is why it has been commented away snprintf(num, sizeof num, "%d", conCount); IFSetOption(pSICSOptions, "ConnectionCount", num); IFSetOption(pSICSOptions, "ConMask", GetCharArray(self->conList)); - +*/ /* the select itself */ tmo.tv_usec = self->iReadTimeout; diff --git a/nx_stptok.h b/nx_stptok.h new file mode 100644 index 00000000..2f75e1ef --- /dev/null +++ b/nx_stptok.h @@ -0,0 +1,6 @@ +#ifndef NX_STPTOK +#define NX_STPTOK + +extern char *stptok(const char *s, char *tok, size_t toklen, char *brk); + +#endif /* NX_STPTOK */ diff --git a/nxcopy.c b/nxcopy.c index 6a12b592..89f0f899 100644 --- a/nxcopy.c +++ b/nxcopy.c @@ -13,6 +13,7 @@ #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. @@ -233,13 +234,190 @@ static int NXDataToHdbNode(ClientData clientData, Tcl_Interp * interp, val = NXDatasetToHdbValue(data); status = UpdateHipadabaPar(node, val, NULL); if (status != 1) { - Tcl_SetStringObj(resultPtr, "data type mismatch", - strlen("data type mismatch")); - return TCL_ERROR; + 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[]) @@ -306,5 +484,7 @@ int NXcopy_Init(Tcl_Interp * pInter) 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; } diff --git a/nxdataset.c b/nxdataset.c index 5992232e..327ad4f4 100644 --- a/nxdataset.c +++ b/nxdataset.c @@ -12,9 +12,8 @@ #include "nxdataset.h" /*-----------------------------------------------------------------------*/ -static int getTypeSize(int typecode) -{ - switch (typecode) { +static int getTypeSize(int typecode){ + switch(typecode){ case NX_FLOAT32: case NX_INT32: case NX_UINT32: @@ -34,51 +33,50 @@ static int getTypeSize(int typecode) break; } } - /*-----------------------------------------------------------------------*/ -pNXDS createNXDataset(int rank, int typecode, int dim[]) -{ +pNXDS createNXDataset(int rank, int typecode, int64_t dim[]){ pNXDS pNew = NULL; - int i, length; + int64_t length; + int i; - pNew = (pNXDS) malloc(sizeof(NXDS)); - if (pNew == NULL) { + pNew = (pNXDS)malloc(sizeof(NXDS)); + if(pNew == NULL){ return NULL; } - pNew->dim = (int *) malloc(rank * sizeof(int)); - for (i = 0, length = 1; i < rank; i++) { + pNew->dim = (int64_t *)malloc(rank*sizeof(int64_t)); + for(i = 0, length = 1; i < rank; i++){ length *= dim[i]; } - pNew->u.ptr = malloc(length * getTypeSize(typecode)); + /* add +1 in case of string NULL termination */ + pNew->u.ptr = malloc(length*getTypeSize(typecode)+1); - if (pNew->dim == NULL || pNew->u.ptr == NULL) { + if(pNew->dim == NULL || pNew->u.ptr == NULL){ free(pNew); return NULL; } pNew->rank = rank; pNew->type = typecode; pNew->format = NULL; - for (i = 0; i < rank; i++) { + for(i = 0; i < rank; i++){ pNew->dim[i] = dim[i]; } pNew->magic = MAGIC; - memset(pNew->u.ptr, 0, length * getTypeSize(typecode)); + /* add +1 in case of string NULL termination - see above */ + memset(pNew->u.ptr,0,length*getTypeSize(typecode)+1); return pNew; } - /*---------------------------------------------------------------------*/ -pNXDS createTextNXDataset(char *name) -{ +pNXDS createTextNXDataset(char *name){ pNXDS pNew = NULL; - pNew = (pNXDS) malloc(sizeof(NXDS)); - if (pNew == NULL) { + pNew = (pNXDS)malloc(sizeof(NXDS)); + if(pNew == NULL){ return NULL; } - pNew->dim = (int *) malloc(sizeof(int)); + pNew->dim = (int64_t *)malloc(sizeof(int64_t)); pNew->u.cPtr = strdup(name); - if (pNew->dim == NULL || pNew->u.ptr == NULL) { + if(pNew->dim == NULL || pNew->u.ptr == NULL){ free(pNew); return NULL; } @@ -88,249 +86,225 @@ pNXDS createTextNXDataset(char *name) pNew->dim[0] = strlen(name); return pNew; } - /*-----------------------------------------------------------------------*/ -void dropNXDataset(pNXDS dataset) -{ - if (dataset == NULL) { +void dropNXDataset(pNXDS dataset){ + if(dataset == NULL){ return; } - if (dataset->magic != MAGIC) { + if(dataset->magic != MAGIC){ return; } - if (dataset->dim != NULL) { + if(dataset->dim != NULL){ free(dataset->dim); } - if (dataset->u.ptr != NULL) { + if(dataset->u.ptr != NULL){ free(dataset->u.ptr); } - if (dataset->format != NULL) { + if(dataset->format != NULL){ free(dataset->format); } free(dataset); } - /*-----------------------------------------------------------------------*/ -int getNXDatasetRank(pNXDS dataset) -{ - if (dataset == NULL) { +int getNXDatasetRank(pNXDS dataset){ + if(dataset == NULL){ return 0; } - if (dataset->magic != MAGIC) { + if(dataset->magic != MAGIC){ return 0; } return dataset->rank; } - /*-----------------------------------------------------------------------*/ -int getNXDatasetDim(pNXDS dataset, int which) -{ - if (dataset == NULL) { +int getNXDatasetDim(pNXDS dataset, int which){ + if(dataset == NULL){ return 0; } - if (dataset->magic != MAGIC) { + if(dataset->magic != MAGIC){ return 0; } - if (which < 0 || which >= dataset->rank) { + if(which < 0 || which >= dataset->rank){ return 0; } return dataset->dim[which]; } - /*------------------------------------------------------------------------*/ -int getNXDatasetType(pNXDS dataset) -{ - if (dataset == NULL) { +int getNXDatasetType(pNXDS dataset){ + if(dataset == NULL){ return 0; } - if (dataset->magic != MAGIC) { + if(dataset->magic != MAGIC){ return 0; } return dataset->type; } - /*--------------------------------------------------------------------*/ -int getNXDatasetLength(pNXDS dataset) -{ +int getNXDatasetLength(pNXDS dataset){ int length, i; - if (dataset == NULL) { + if(dataset == NULL){ return 0; } - if (dataset->magic != MAGIC) { + if(dataset->magic != MAGIC){ return 0; } length = dataset->dim[0]; - for (i = 1; i < dataset->rank; i++) { + for(i = 1; i < dataset->rank; i++){ length *= dataset->dim[i]; } return length; } - /*---------------------------------------------------------------------*/ -int getNXDatasetByteLength(pNXDS dataset) -{ - return getNXDatasetLength(dataset) * getTypeSize(dataset->type); +int getNXDatasetByteLength(pNXDS dataset){ + return getNXDatasetLength(dataset)*getTypeSize(dataset->type); } - /*---------------------------------------------------------------------- This calculates an arbitray address in C storage order -----------------------------------------------------------------------*/ -static int calculateAddress(pNXDS dataset, int pos[]) -{ - int result, mult; +static int64_t calculateAddress(pNXDS dataset, int64_t pos[]){ + int64_t result, mult; int i, j; result = pos[dataset->rank - 1]; - for (i = 0; i < dataset->rank - 1; i++) { + for(i = 0; i < dataset->rank -1; i++){ mult = 1; - for (j = dataset->rank - 1; j > i; j--) { + for(j = dataset->rank -1; j > i; j--){ mult *= dataset->dim[j]; } - if (pos[i] < dataset->dim[i] && pos[i] > 0) { - result += mult * pos[i]; + if(pos[i] < dataset->dim[i] && pos[i] > 0){ + result += mult*pos[i]; } } return result; } - /*-----------------------------------------------------------------------*/ -double getNXDatasetValue(pNXDS dataset, int pos[]) -{ - int address; - double value; - - if (dataset == NULL) { +double getNXDatasetValue(pNXDS dataset, int64_t pos[]){ + int64_t address; + + if(dataset == NULL){ return 0; } - if (dataset->magic != MAGIC) { + if(dataset->magic != MAGIC){ return 0; } - address = calculateAddress(dataset, pos); + address = calculateAddress(dataset,pos); return getNXDatasetValueAt(dataset, address); } - /*----------------------------------------------------------------------*/ -double getNXDatasetValueAt(pNXDS dataset, int address) -{ +double getNXDatasetValueAt(pNXDS dataset, int64_t address){ double value; - if (dataset == NULL) { + if(dataset == NULL){ return 0; } - if (dataset->magic != MAGIC) { + if(dataset->magic != MAGIC){ return 0; } - switch (dataset->type) { + switch(dataset->type){ case NX_FLOAT64: value = dataset->u.dPtr[address]; break; case NX_FLOAT32: - value = (double) dataset->u.fPtr[address]; + value = (double)dataset->u.fPtr[address]; break; case NX_INT32: case NX_UINT32: - value = (double) dataset->u.iPtr[address]; + value = (double)dataset->u.iPtr[address]; break; case NX_INT64: case NX_UINT64: - value = (double) dataset->u.lPtr[address]; + value = (double)dataset->u.lPtr[address]; break; case NX_INT16: case NX_UINT16: - value = (double) dataset->u.sPtr[address]; + value = (double)dataset->u.sPtr[address]; break; default: - value = (double) dataset->u.cPtr[address]; + value = (double)dataset->u.cPtr[address]; break; } return value; } - /*-----------------------------------------------------------------------*/ -char *getNXDatasetText(pNXDS dataset) -{ +char *getNXDatasetText(pNXDS dataset){ char *resultBuffer = NULL; - int length, status = 1; + int status = 1; - if (dataset == NULL) { + if(dataset == NULL){ return strdup("NULL"); } - if (dataset->magic != MAGIC) { + if(dataset->magic != MAGIC){ return strdup("NULL"); } - if (dataset->rank > 1) { + if(dataset->rank > 1){ status = 0; - } - if (dataset->type == NX_FLOAT32 || - dataset->type == NX_FLOAT64 || - dataset->type == NX_INT32 || - dataset->type == NX_UINT32 || - dataset->type == NX_INT64 || - dataset->type == NX_UINT64 || - dataset->type == NX_INT16 || dataset->type == NX_UINT16) { + } + if(dataset->type == NX_FLOAT32 || + dataset->type == NX_FLOAT64 || + dataset->type == NX_INT32 || + dataset->type == NX_UINT32 || + dataset->type == NX_INT64 || + dataset->type == NX_UINT64 || + dataset->type == NX_INT16 || + dataset->type == NX_UINT16 ) { status = 0; } - if (status == 0) { + if(status == 0){ return strdup("NO type problem"); - } else { - resultBuffer = (char *) malloc((dataset->dim[0] + 10) * sizeof(char)); - if (resultBuffer == NULL) { + }else{ + resultBuffer = (char *)malloc((dataset->dim[0]+10)*sizeof(char)); + if(resultBuffer == NULL){ return strdup("NO Memory"); } - memset(resultBuffer, 0, (dataset->dim[0] + 10) * sizeof(char)); - strncpy(resultBuffer, dataset->u.cPtr, dataset->dim[0]); + memset(resultBuffer,0,(dataset->dim[0]+10)*sizeof(char)); + strncpy(resultBuffer,dataset->u.cPtr,dataset->dim[0]); } return resultBuffer; } - /*----------------------------------------------------------------------*/ -int putNXDatasetValue(pNXDS dataset, int pos[], double value) -{ - int address; +int putNXDatasetValue(pNXDS dataset, int64_t pos[], double value){ + int64_t address; - if (dataset == NULL) { + if(dataset == NULL){ return 0; } - if (dataset->magic != MAGIC) { + if(dataset->magic != MAGIC){ return 0; } - address = calculateAddress(dataset, pos); - return putNXDatasetValueAt(dataset, address, value); + address = calculateAddress(dataset,pos); + return putNXDatasetValueAt(dataset,address,value); } - /*---------------------------------------------------------------------*/ -int putNXDatasetValueAt(pNXDS dataset, int address, double value) -{ +int putNXDatasetValueAt(pNXDS dataset, int64_t address, double value){ /* - this code is dangerous, it casts without checking the data range. - This may cause trouble in some cases - */ - switch (dataset->type) { + this code is dangerous, it casts without checking the data range. + This may cause trouble in some cases + */ + switch(dataset->type){ case NX_FLOAT64: dataset->u.dPtr[address] = value; break; case NX_FLOAT32: - dataset->u.fPtr[address] = (float) value; + dataset->u.fPtr[address] = (float)value; break; case NX_INT32: case NX_UINT32: - dataset->u.iPtr[address] = (int) value; + dataset->u.iPtr[address] = (int)value; break; case NX_INT64: case NX_UINT64: - dataset->u.lPtr[address] = (int64_t) value; + dataset->u.lPtr[address] = (int64_t)value; break; case NX_INT16: case NX_UINT16: - dataset->u.sPtr[address] = (short int) value; + dataset->u.sPtr[address] = (short int)value; break; default: - dataset->u.cPtr[address] = (char) value; + dataset->u.cPtr[address] = (char)value; break; } return 1; @@ -340,8 +314,8 @@ int putNXDatasetValueAt(pNXDS dataset, int address, double value) This is working recursively through the dimensions. When at the last: actual copying takes place. -----------------------------------------------------------------------*/ -static void copyCutData(pNXDS source, pNXDS target, int sourceDim[], - int targetDim[], int start[], int end[], int dim) +static void copyCutData(pNXDS source, pNXDS target, int64_t sourceDim[], + int64_t targetDim[], int64_t start[], int64_t end[], int dim) { int i, length; double val; @@ -366,11 +340,11 @@ static void copyCutData(pNXDS source, pNXDS target, int sourceDim[], } /*-----------------------------------------------------------------------*/ -pNXDS cutNXDataset(pNXDS source, int start[], int end[]) +pNXDS cutNXDataset(pNXDS source, int64_t start[], int64_t end[]) { pNXDS result = NULL; - int newDim[NX_MAXRANK], i; - int sourceDim[NX_MAXRANK], targetDim[NX_MAXRANK]; + int64_t newDim[NX_MAXRANK], i; + int64_t sourceDim[NX_MAXRANK], targetDim[NX_MAXRANK]; for (i = 0; i < source->rank; i++) { if (start[i] < 0 || end[i] > source->dim[i]) { @@ -399,8 +373,8 @@ pNXDS cutNXDataset(pNXDS source, int start[], int end[]) This recurses through all dimensions, thereby skipping the summed one. At the end of the recursion the actual summing is performed. ----------------------------------------------------------------------*/ -static void sumData(pNXDS source, pNXDS target, int sourceDim[], - int targetDim[], int targetDimCount, int dimNo, +static void sumData(pNXDS source, pNXDS target, int64_t sourceDim[], + int64_t targetDim[], int targetDimCount, int dimNo, int start, int end, int currentDim) { int i, length; @@ -454,7 +428,7 @@ static void sumData(pNXDS source, pNXDS target, int sourceDim[], /*-----------------------------------------------------------------------*/ pNXDS sumNXDataset(pNXDS source, int dimNo, int start, int end) { - int newDim[NX_MAXRANK], targetDim[NX_MAXRANK], sourceDim[NX_MAXRANK]; + int64_t newDim[NX_MAXRANK], targetDim[NX_MAXRANK], sourceDim[NX_MAXRANK]; pNXDS result = NULL; int i, count; @@ -480,3 +454,5 @@ pNXDS sumNXDataset(pNXDS source, int dimNo, int start, int end) sumData(source, result, sourceDim, targetDim, 0, dimNo, start, end, 0); return result; } + + diff --git a/nxdataset.h b/nxdataset.h index 129a5350..98eff2e8 100644 --- a/nxdataset.h +++ b/nxdataset.h @@ -10,26 +10,26 @@ #define NXDATASET -#define MAGIC 7776622 +#define MAGIC 7776622 #include "napiconfig.h" typedef struct { - int magic; - int rank; - int type; - int *dim; - char *format; - union { - void *ptr; - float *fPtr; - double *dPtr; - int *iPtr; - short int *sPtr; - char *cPtr; - int64_t *lPtr; - } u; -} *pNXDS, NXDS; + int magic; + int rank; + int type; + int64_t *dim; + char *format; + union { + void *ptr; + float *fPtr; + double *dPtr; + int *iPtr; + short int *sPtr; + char *cPtr; + int64_t *lPtr; + } u; +}*pNXDS, NXDS; /* include NeXus type codes if not already defined @@ -38,9 +38,9 @@ typedef struct { #define NX_FLOAT32 5 #define NX_FLOAT64 6 -#define NX_INT8 20 +#define NX_INT8 20 #define NX_UINT8 21 -#define NX_INT16 22 +#define NX_INT16 22 #define NX_UINT16 23 #define NX_INT32 24 #define NX_UINT32 25 @@ -53,25 +53,25 @@ typedef struct { #endif -pNXDS createNXDataset(int rank, int typecode, int dim[]); +pNXDS createNXDataset(int rank, int typecode, int64_t dim[]); pNXDS createTextNXDataset(char *name); -void dropNXDataset(pNXDS dataset); +void dropNXDataset(pNXDS dataset); -int getNXDatasetRank(pNXDS dataset); -int getNXDatasetDim(pNXDS dataset, int which); -int getNXDatasetType(pNXDS dataset); -int getNXDatasetLength(pNXDS dataset); -int getNXDatasetByteLength(pNXDS dataset); +int getNXDatasetRank(pNXDS dataset); +int getNXDatasetDim(pNXDS dataset, int which); +int getNXDatasetType(pNXDS dataset); +int getNXDatasetLength(pNXDS dataset); +int getNXDatasetByteLength(pNXDS dataset); -double getNXDatasetValue(pNXDS dataset, int pos[]); -double getNXDatasetValueAt(pNXDS dataset, int address); -char *getNXDatasetText(pNXDS dataset); +double getNXDatasetValue(pNXDS dataset, int64_t pos[]); +double getNXDatasetValueAt(pNXDS dataset, int64_t address); +char *getNXDatasetText(pNXDS dataset); -int putNXDatasetValue(pNXDS dataset, int pos[], double value); -int putNXDatasetValueAt(pNXDS dataset, int address, double value); +int putNXDatasetValue(pNXDS dataset, int64_t pos[], double value); +int putNXDatasetValueAt(pNXDS dataset, int64_t address, double value); -pNXDS cutNXDataset(pNXDS source, int start[], int end[]); +pNXDS cutNXDataset(pNXDS source, int64_t start[], int64_t end[]); pNXDS sumNXDataset(pNXDS source, int dimNo, int start, int end); #endif diff --git a/nxdict.c b/nxdict.c index a5c07801..187bd21e 100644 --- a/nxdict.c +++ b/nxdict.c @@ -47,8 +47,7 @@ /*-------------------------------------------------------------------------- Things defined in napi.c for error reporting ---------------------------------------------------------------------------*/ -extern void *NXpData; -extern void (*NXIReportError) (void *pData, char *pBuffer); +static void *NXpData = NULL; /*--------------------------------------------------------------------------*/ /* #define DEFDEBUG 1 */ /* define DEFDEBUG when you wish to print your definition strings before @@ -95,7 +94,7 @@ static char *NXDIReadFile(FILE * fd) /* check for existence of the NXDICT string in the file */ if (strncmp(pNew, "##NXDICT-1.0", 12) != 0) { - NXIReportError(NXpData, "ERROR: This is NO NXdict file"); + NXReportError("ERROR: This is NO NXdict file"); free(pNew); return NULL; } @@ -256,11 +255,11 @@ NXstatus NXDinitfromfile(char *filename, NXdict * pData) /* allocate a new NXdict structure */ if (iVerbosity == NXalot) { - NXIReportError(NXpData, "Allocating new NXdict structure "); + NXReportError("Allocating new NXdict structure "); } pNew = (NXdict) malloc(sizeof(sNXdict)); if (!pNew) { - NXIReportError(NXpData, "Insufficient memory for creation of NXdict"); + NXReportError("Insufficient memory for creation of NXdict"); return NX_ERROR; } @@ -268,7 +267,7 @@ NXstatus NXDinitfromfile(char *filename, NXdict * pData) pNew->iID = NXDMAGIC; pNew->pDictionary = CreateStringDict(); if (!pNew->pDictionary) { - NXIReportError(NXpData, "Insufficient memory for creation of NXdict"); + NXReportError("Insufficient memory for creation of NXdict"); free(pNew); return NX_ERROR; } @@ -278,7 +277,7 @@ NXstatus NXDinitfromfile(char *filename, NXdict * pData) /* is there a file name argument */ if (filename == NULL) { if (iVerbosity == NXalot) { - NXIReportError(NXpData, "NXDinitfrom file finished without data"); + NXReportError("NXDinitfrom file finished without data"); } *pData = pNew; return NX_OK; @@ -288,8 +287,8 @@ NXstatus NXDinitfromfile(char *filename, NXdict * pData) fd = fopen(filename, "rb"); if (!fd) { sprintf(pError, "ERROR: file %s NOT found ", filename); - NXIReportError(NXpData, pError); - NXIReportError(NXpData, "NXDinitfrom file finished without data"); + NXReportError(pError); + NXReportError("NXDinitfrom file finished without data"); *pData = pNew; return NX_ERROR; } @@ -297,27 +296,27 @@ NXstatus NXDinitfromfile(char *filename, NXdict * pData) /* read the file contents */ if (iVerbosity == NXalot) { - NXIReportError(NXpData, "NXDinitfrom: reading file"); + NXReportError("NXDinitfrom: reading file"); } pBuffer = NXDIReadFile(fd); fclose(fd); /* we are done with it then */ if (!pBuffer) { sprintf(pError, "ERROR: reading file %s or no memory", filename); - NXIReportError(NXpData, pError); - NXIReportError(NXpData, "NXDinitfrom file finished without data"); + NXReportError(pError); + NXReportError("NXDinitfrom file finished without data"); *pData = pNew; return NX_ERROR; } /* parse it */ if (iVerbosity == NXalot) { - NXIReportError(NXpData, "NXDinitfrom: parsing dictionary definitions"); + NXReportError("NXDinitfrom: parsing dictionary definitions"); } NXDIParse(pBuffer, pNew->pDictionary); if (iVerbosity == NXalot) { - NXIReportError(NXpData, "NXDinitfrom: performed successfully"); + NXReportError("NXDinitfrom: performed successfully"); } free(pBuffer); *pData = pNew; @@ -350,12 +349,12 @@ NXstatus NXDclose(NXdict handle, char *filename) if (filename) { /* we must write a file */ if (iVerbosity == NXalot) { sprintf(pValue, "Writing file %s", filename); - NXIReportError(NXpData, pValue); + NXReportError(pValue); } fd = fopen(filename, "w"); if (!fd) { sprintf(pValue, "ERROR: opening file %s for write", filename); - NXIReportError(NXpData, pValue); + NXReportError(pValue); return NX_ERROR; } @@ -371,7 +370,7 @@ NXstatus NXDclose(NXdict handle, char *filename) fclose(fd); if (iVerbosity == NXalot) { sprintf(pValue, "File %s written", filename); - NXIReportError(NXpData, pValue); + NXReportError(pValue); } } @@ -445,7 +444,7 @@ pDynString NXDItextreplace(NXdict handle, char *pDefString) /* create a dynamic string */ pReplaced = CreateDynString(strlen(pDefString), 512); if (!pReplaced) { - NXIReportError(NXpData, "ERROR: out of memory in NXDtextreplace"); + NXReportError("ERROR: out of memory in NXDtextreplace"); return NULL; } @@ -479,8 +478,7 @@ pDynString NXDItextreplace(NXdict handle, char *pDefString) pBueffel[iPos] = *pPtr; iPos++; if (iPos >= 1024) { - NXIReportError(NXpData, - "ERROR: buffer overrun in NXDItextreplace"); + NXReportError("ERROR: buffer overrun in NXDItextreplace"); DeleteDynString(pReplaced); return NULL; } @@ -737,7 +735,7 @@ int NXDIParsePath(NXhandle hfil, ParDat * pParse) if (pParse->iToken != DWORD) { sprintf(pError, "ERROR: parse error at %s, expected vGroup name", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } strcpy(pName, pParse->pToken); @@ -747,7 +745,7 @@ int NXDIParsePath(NXhandle hfil, ParDat * pParse) if (pParse->iToken != DKOMMA) { sprintf(pError, "ERROR: parse error at %s, expected komma", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } @@ -756,18 +754,18 @@ int NXDIParsePath(NXhandle hfil, ParDat * pParse) if (pParse->iToken != DWORD) { sprintf(pError, "ERROR: parse error at %s, expected vGroup class", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } strcpy(pClass, pParse->pToken); /* done reading, ACTION, first install dummy error handler */ ErrFunc = NXIReportError; - NXMSetError(NXpData, DummyError); + NXMSetError(NXpData,DummyError); /* try opening vGroup */ iRet = NXopengroup(hfil, pName, pClass); - NXMSetError(NXpData, ErrFunc); + NXMSetError(NXpData,ErrFunc); if (iRet == NX_OK) { pParse->iDepth++; return NX_OK; @@ -789,7 +787,7 @@ int NXDIParsePath(NXhandle hfil, ParDat * pParse) } else { /* this is an error */ sprintf(pError, "ERROR: vGroup %s, %s NOT found", pName, pClass); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } } @@ -809,7 +807,7 @@ static int NXDIParseAttr(ParDat * pParse, int iList) NXDIDefToken(pParse); if (pParse->iToken != DOPEN) { sprintf(pError, "ERROR: expected {, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } @@ -818,7 +816,7 @@ static int NXDIParseAttr(ParDat * pParse, int iList) if (pParse->iToken != DWORD) { sprintf(pError, "ERROR: expected attribute name, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } strcpy(sAtt.name, pParse->pToken); @@ -827,7 +825,7 @@ static int NXDIParseAttr(ParDat * pParse, int iList) NXDIDefToken(pParse); if (pParse->iToken != DKOMMA) { sprintf(pError, "ERROR: expected , , got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } @@ -836,7 +834,7 @@ static int NXDIParseAttr(ParDat * pParse, int iList) if (pParse->iToken != DWORD) { sprintf(pError, "ERROR: expected attribute value, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } strcpy(sAtt.value, pParse->pToken); @@ -845,7 +843,7 @@ static int NXDIParseAttr(ParDat * pParse, int iList) NXDIDefToken(pParse); if (pParse->iToken != DCLOSE) { sprintf(pError, "ERROR: expected }, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } @@ -868,7 +866,7 @@ static int NXDIParseDim(ParDat * pParse, int *iDim) NXDIDefToken(pParse); if (pParse->iToken != DOPEN) { sprintf(pError, "ERROR: expected {, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } @@ -878,7 +876,7 @@ static int NXDIParseDim(ParDat * pParse, int *iDim) NXDIDefToken(pParse); if (pParse->iToken != DWORD) { sprintf(pError, "ERROR: expected number, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } iDim[i] = atoi(pParse->pToken); @@ -887,7 +885,7 @@ static int NXDIParseDim(ParDat * pParse, int *iDim) NXDIDefToken(pParse); if ((pParse->iToken != DKOMMA) && (pParse->iToken != DCLOSE)) { sprintf(pError, "ERROR: expected , or }, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError( pError); return NX_ERROR; } if (pParse->iToken == DCLOSE) { @@ -930,7 +928,7 @@ static int NXDIParseType(ParDat * pParse, int *iType) NXDIDefToken(pParse); if (pParse->iToken != DWORD) { sprintf(pError, "ERROR: expected data type, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } @@ -947,7 +945,7 @@ static int NXDIParseType(ParDat * pParse, int *iType) */ sprintf(pError, "ERROR: %s not recognized as valid data type", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } @@ -972,7 +970,7 @@ static int NXDIParseSDS(NXhandle hfil, ParDat * pParse) if (pParse->iToken != DWORD) { sprintf(pError, "ERROR: parsing, expected name, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } strcpy(pName, pParse->pToken); @@ -980,7 +978,7 @@ static int NXDIParseSDS(NXhandle hfil, ParDat * pParse) /* create the attribute list */ iList = LLDcreate(sizeof(AttItem)); if (iList < 0) { - NXIReportError(NXpData, "ERROR: cannot create list in NXDIParseSDS"); + NXReportError("ERROR: cannot create list in NXDIParseSDS"); return NX_ERROR; } @@ -991,7 +989,7 @@ static int NXDIParseSDS(NXhandle hfil, ParDat * pParse) NXDIDefToken(pParse); /* advance */ if (pParse->iToken != DWORD) { sprintf(pError, "ERROR: expected int, got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); LLDdelete(iList); return NX_ERROR; } @@ -1039,7 +1037,7 @@ static int NXDIParseSDS(NXhandle hfil, ParDat * pParse) break; default: sprintf(pError, "ERROR: cannot identify token %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); LLDdelete(iList); return NX_ERROR; @@ -1107,7 +1105,7 @@ static int NXDIParseSDS(NXhandle hfil, ParDat * pParse) } else { /* this is an error */ sprintf(pError, "ERROR: SDS %s NOT found", pName); - NXIReportError(NXpData, pError); + NXReportError(pError); LLDdelete(iList); return NX_ERROR; } @@ -1125,7 +1123,7 @@ static int NXDIParseLink(NXhandle hfil, NXdict pDict, ParDat * pParse) NXDIDefToken(pParse); if (pParse->iToken != DCLOSE) { sprintf(pError, "ERROR: expected alias , got %s", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; } @@ -1181,7 +1179,7 @@ int NXDIDefParse(NXhandle hFil, NXdict pDict, ParDat * pParse) sprintf(pError, "ERROR: Definition String parse error: %s not permitted here", pParse->pToken); - NXIReportError(NXpData, pError); + NXReportError(pError); return NX_ERROR; break; } @@ -1240,7 +1238,7 @@ NXstatus NXDopenalias(NXhandle hfil, NXdict dict, char *pAlias) iRet = NXDget(pDict, pAlias, pDefinition, 2047); if (iRet != NX_OK) { sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias); - NXIReportError(NXpData, pDefinition); + NXReportError(pDefinition); return NX_ERROR; } @@ -1281,7 +1279,7 @@ NXstatus NXDputdef(NXhandle hFil, NXdict dict, char *pDef, void *pData) /* only SDS can be written */ if (pParse.iTerminal != TERMSDS) { - NXIReportError(NXpData, "ERROR: can only write to an SDS!"); + NXReportError("ERROR: can only write to an SDS!"); iStat = NX_ERROR; } else { /* the SDS should be open by now, write it */ @@ -1312,7 +1310,7 @@ NXstatus NXDputalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData) iRet = NXDget(pDict, pAlias, pDefinition, 2047); if (iRet != NX_OK) { sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias); - NXIReportError(NXpData, pDefinition); + NXReportError( pDefinition); return NX_ERROR; } @@ -1354,7 +1352,7 @@ NXstatus NXDgetdef(NXhandle hFil, NXdict dict, char *pDef, void *pData) /* only SDS can be written */ if (pParse.iTerminal != TERMSDS) { - NXIReportError(NXpData, "ERROR: can only write to an SDS!"); + NXReportError("ERROR: can only write to an SDS!"); iStat = NX_ERROR; } else { /* the SDS should be open by now, read it */ @@ -1385,7 +1383,7 @@ NXstatus NXDgetalias(NXhandle hFil, NXdict dict, char *pAlias, void *pData) iRet = NXDget(pDict, pAlias, pDefinition, 2047); if (iRet != NX_OK) { sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias); - NXIReportError(NXpData, pDefinition); + NXReportError(pDefinition); return NX_ERROR; } @@ -1429,7 +1427,7 @@ NXstatus NXDinfodef(NXhandle hFil, NXdict dict, char *pDef, int *rank, /* only SDS can be written */ if (pParse.iTerminal != TERMSDS) { - NXIReportError(NXpData, "ERROR: can only write to an SDS!"); + NXReportError("ERROR: can only write to an SDS!"); iStat = NX_ERROR; } else { /* the SDS should be open by now, read it */ @@ -1462,7 +1460,7 @@ NXstatus NXDinfoalias(NXhandle hFil, NXdict dict, char *pAlias, int *rank, iRet = NXDget(pDict, pAlias, pDefinition, 2047); if (iRet != NX_OK) { sprintf(pDefinition, "ERROR: alias %s not recognized", pAlias); - NXIReportError(NXpData, pDefinition); + NXReportError(pDefinition); return NX_ERROR; } @@ -1540,7 +1538,7 @@ NXstatus NXDdeflink(NXhandle hFil, NXdict dict, } /* check it being a vGroup! */ if (pParseT.iTerminal != TERMVG) { - NXIReportError(NXpData, "ERROR: can link only into a vGroup"); + NXReportError("ERROR: can link only into a vGroup"); NXDIUnwind(hFil, pParseT.iDepth); return NX_ERROR; } @@ -1570,7 +1568,7 @@ NXstatus NXDaliaslink(NXhandle hFil, NXdict dict, iRet = NXDget(pDict, pTarget, pTargetDef, 2047); if (iRet != NX_OK) { sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget); - NXIReportError(NXpData, pTargetDef); + NXReportError(pTargetDef); return NX_ERROR; } @@ -1578,7 +1576,7 @@ NXstatus NXDaliaslink(NXhandle hFil, NXdict dict, iRet = NXDget(pDict, pVictim, pVictimDef, 2047); if (iRet != NX_OK) { sprintf(pTargetDef, "ERROR: alias %s not recognized", pTarget); - NXIReportError(NXpData, pTargetDef); + NXReportError(pTargetDef); return NX_ERROR; } @@ -1800,8 +1798,7 @@ NXstatus NXUallocSDS(NXhandle hFil, void **pData) lLength *= sizeof(int); break; default: - NXIReportError(NXpData, - "ERROR: Internal: number type not recoginized"); + NXReportError("ERROR: Internal: number type not recoginized"); return NX_ERROR; } @@ -1809,7 +1806,7 @@ NXstatus NXUallocSDS(NXhandle hFil, void **pData) *pData = NULL; *pData = malloc(lLength); if (*pData == NULL) { - NXIReportError(NXpData, "ERROR: memory exhausted in NXUallocSDS"); + NXReportError("ERROR: memory exhausted in NXUallocSDS"); return NX_ERROR; } memset(*pData, 0, lLength); diff --git a/nxinter_wrap.c b/nxinter_wrap.c index 4d2c4e90..a2aaf7d7 100644 --- a/nxinter_wrap.c +++ b/nxinter_wrap.c @@ -1741,7 +1741,7 @@ SWIGINTERNINLINE Tcl_Obj *SWIG_From_int(int value) void *create_nxds(int rank, int type, int dim0, int dim1, int dim2, int dim3, int dim4, int dim5, int dim6) { - int dim[MAXDIM], i; + int64_t dim[MAXDIM], i; dim[0] = dim0; dim[1] = dim1; @@ -1781,7 +1781,7 @@ int get_nxds_dim(void *ptr, int which) double get_nxds_value(void *ptr, int dim0, int dim1, int dim2, int dim3, int dim4, int dim5, int dim6) { - int dim[MAXDIM]; + int64_t dim[MAXDIM]; dim[0] = dim0; dim[1] = dim1; @@ -1802,7 +1802,7 @@ char *get_nxds_text(void *ptr) int put_nxds_value(void *ptr, double value, int dim0, int dim1, int dim2, int dim3, int dim4, int dim5, int dim6) { - int dim[MAXDIM]; + int64_t dim[MAXDIM]; dim[0] = dim0; dim[1] = dim1; diff --git a/nxinterhelper.c b/nxinterhelper.c index 297b3144..06aecfc4 100644 --- a/nxinterhelper.c +++ b/nxinterhelper.c @@ -314,6 +314,7 @@ void *nx_getslab(void *handle, void *startdim, void *sizedim) pNXDS resultdata; pNXDS start, size; int status, rank, type, dim[NX_MAXRANK]; + int64_t cdim[NX_MAXRANK], i; NXhandle hfil; hfil = (NXhandle) handle; @@ -328,7 +329,10 @@ void *nx_getslab(void *handle, void *startdim, void *sizedim) return NULL; } - resultdata = createNXDataset(rank, type, size->u.iPtr); + for(i = 0; i < rank; i++){ + cdim[i] = size->u.iPtr[i]; + } + resultdata = createNXDataset(rank, type, cdim); if (resultdata == NULL) { return NULL; } @@ -346,7 +350,8 @@ void *nx_getslab(void *handle, void *startdim, void *sizedim) void *nx_getds(void *handle, char *name) { pNXDS result = NULL; - int rank, type, dim[NX_MAXRANK], status; + int rank, type,status; + int64_t dim[NX_MAXRANK]; NXhandle hfil; hfil = (NXhandle) handle; @@ -355,7 +360,7 @@ void *nx_getds(void *handle, char *name) return NULL; } - status = NXgetinfo(hfil, &rank, dim, &type); + status = NXgetinfo64(hfil, &rank, dim, &type); if (status != NX_OK) { return NULL; } @@ -388,7 +393,7 @@ int nx_putds(void *handle, char *name, void *dataset) status = NXopendata(hfil, name); if (status != NX_OK) { - status = NXmakedata(hfil, name, data->type, data->rank, data->dim); + status = NXmakedata64(hfil, name, data->type, data->rank, data->dim); if (status != NX_OK) { return 0; } @@ -408,12 +413,13 @@ int nx_putds(void *handle, char *name, void *dataset) void *nx_getdata(void *handle) { pNXDS result = NULL; - int rank, type, dim[NX_MAXRANK], status; + int rank, type, status; + int64_t dim[NX_MAXRANK]; NXhandle hfil; hfil = (NXhandle) handle; - status = NXgetinfo(hfil, &rank, dim, &type); + status = NXgetinfo64(hfil, &rank, dim, &type); if (status != NX_OK) { return NULL; } @@ -459,7 +465,8 @@ int nx_putdata(void *handle, void *dataset) void *nx_getinfo(void *handle) { NXhandle hfil; - int status, type, rank, dim[NX_MAXRANK], rdim[1], i; + int status, type, rank, dim[NX_MAXRANK], i; + int64_t rdim[1]; pNXDS data = NULL; hfil = (NXhandle) handle; @@ -550,7 +557,8 @@ int nx_putattr(void *handle, char *name, void *ds) void *nx_getattr(void *handle, char *name, int type, int length) { NXhandle hfil; - int status, tp, ll, dim[1]; + int status, tp, ll; + int64_t dim[1]; pNXDS data = NULL; diff --git a/nxio.c b/nxio.c index d5e040aa..eed88b54 100644 --- a/nxio.c +++ b/nxio.c @@ -21,9 +21,12 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * For further information, see + * For further information, see */ -#include + +#ifdef NXXML + +#include #include #include "napi.h" #include "nxio.h" @@ -35,181 +38,188 @@ #define MXML_WRAP 79 #endif +#ifdef _MSC_VER +#define snprintf _snprintf +#endif /* _MSC_VER */ + /* #define TESTMAIN 1 */ /*=================== type code handling ================================= */ typedef struct { char name[30]; char format[30]; - int nx_type; -} type_code; + int nx_type; +}type_code; #define NTYPECODE 11 static type_code typecode[NTYPECODE]; /*-----------------------------------------------------------------------*/ -void initializeNumberFormats() -{ +void initializeNumberFormats(){ type_code myCode; - strcpy(myCode.name, "NX_FLOAT32"); - strcpy(myCode.format, "%12.4f"); + strcpy(myCode.name,"NX_FLOAT32"); + strcpy(myCode.format,"%12.4f"); myCode.nx_type = NX_FLOAT32; typecode[0] = myCode; - strcpy(myCode.name, "NX_FLOAT64"); - strcpy(myCode.format, "%16.5f"); + strcpy(myCode.name,"NX_FLOAT64"); + strcpy(myCode.format,"%16.5f"); myCode.nx_type = NX_FLOAT64; typecode[1] = myCode; - strcpy(myCode.name, "NX_INT8"); - strcpy(myCode.format, "%5d"); + strcpy(myCode.name,"NX_INT8"); + strcpy(myCode.format,"%5d"); myCode.nx_type = NX_INT8; typecode[2] = myCode; - strcpy(myCode.name, "NX_UINT8"); - strcpy(myCode.format, "%5d"); + strcpy(myCode.name,"NX_UINT8"); + strcpy(myCode.format,"%5d"); myCode.nx_type = NX_UINT8; typecode[3] = myCode; - strcpy(myCode.name, "NX_INT16"); - strcpy(myCode.format, "%8d"); + strcpy(myCode.name,"NX_INT16"); + strcpy(myCode.format,"%8d"); myCode.nx_type = NX_INT16; typecode[4] = myCode; - strcpy(myCode.name, "NX_UINT16"); - strcpy(myCode.format, "%8d"); + strcpy(myCode.name,"NX_UINT16"); + strcpy(myCode.format,"%8d"); myCode.nx_type = NX_UINT16; typecode[5] = myCode; - strcpy(myCode.name, "NX_INT32"); - strcpy(myCode.format, "%12d"); + strcpy(myCode.name,"NX_INT32"); + strcpy(myCode.format,"%12d"); myCode.nx_type = NX_INT32; typecode[6] = myCode; - strcpy(myCode.name, "NX_UINT32"); - strcpy(myCode.format, "%12d"); + strcpy(myCode.name,"NX_UINT32"); + strcpy(myCode.format,"%12d"); myCode.nx_type = NX_UINT32; typecode[7] = myCode; - strcpy(myCode.name, "NX_INT64"); - strcpy(myCode.format, "%24" PRINTF_INT64); + strcpy(myCode.name,"NX_INT64"); + strcpy(myCode.format,"%24lld"); myCode.nx_type = NX_INT64; typecode[8] = myCode; - strcpy(myCode.name, "NX_UINT64"); - strcpy(myCode.format, "%24" PRINTF_UINT64); + strcpy(myCode.name,"NX_UINT64"); + strcpy(myCode.format,"%24llu"); myCode.nx_type = NX_UINT64; typecode[9] = myCode; - strcpy(myCode.name, "NX_CHAR"); - strcpy(myCode.format, "%c"); + strcpy(myCode.name,"NX_CHAR"); + strcpy(myCode.format,"%c"); myCode.nx_type = NX_CHAR; typecode[10] = myCode; } - /*----------------------------------------------------------------------*/ -void setNumberFormat(int nx_type, char *format) -{ +void setNumberFormat(int nx_type, char *format){ int i; - for (i = 0; i < NTYPECODE; i++) { - if (typecode[i].nx_type == nx_type) { - strncpy(typecode[i].format, format, 29); + for(i = 0; i < NTYPECODE; i++){ + if(typecode[i].nx_type == nx_type){ + strncpy(typecode[i].format,format,29); } } } - /*------------------------------------------------------------------*/ -static void getNumberFormat(int nx_type, char format[30]) -{ +static void getNumberFormat(int nx_type, char format[30]){ int i; - for (i = 0; i < NTYPECODE; i++) { - if (typecode[i].nx_type == nx_type) { - strncpy(format, typecode[i].format, 29); + for(i = 0; i < NTYPECODE; i++){ + if(typecode[i].nx_type == nx_type){ + strncpy(format,typecode[i].format,29); } } } - /*----------------------------------------------------------------*/ -void getNumberText(int nx_type, char *typestring, int typeLen) -{ +void getNumberText(int nx_type, char *typestring, int typeLen){ int i; - for (i = 0; i < NTYPECODE; i++) { - if (typecode[i].nx_type == nx_type) { - strncpy(typestring, typecode[i].name, typeLen); + for(i = 0; i < NTYPECODE; i++){ + if(typecode[i].nx_type == nx_type){ + strncpy(typestring,typecode[i].name,typeLen); } } } - /* * 'mxml_add_char()' - Add a character to a buffer, expanding as needed. * copied here from mxml-file.c to achieve compatibility with mxml-2.1 * standard */ -static int /* O - 0 on success, -1 on error */ myxml_add_char(int ch, /* I - Character to add */ - char **bufptr, /* IO - Current position in buffer */ - char **buffer, /* IO - Current buffer */ - int - *bufsize) -{ /* IO - Current buffer size */ - char *newbuffer; /* New buffer value */ +static int /* O - 0 on success, -1 on error */ +myxml_add_char(int ch, /* I - Character to add */ + char **bufptr, /* IO - Current position in buffer */ + char **buffer, /* IO - Current buffer */ + size_t *bufsize) /* IO - Current buffer size */ +{ + char *newbuffer; /* New buffer value */ - if (*bufptr >= (*buffer + *bufsize - 4)) { - /* - * Increase the size of the buffer... - */ + if (*bufptr >= (*buffer + *bufsize - 4)) + { + /* + * Increase the size of the buffer... + */ - if (*bufsize < 1024) { + if (*bufsize < 1024) + { (*bufsize) *= 2; - } else { + } + else + { (*bufsize) *= 3; (*bufsize) /= 2; } - newbuffer = (char *) malloc(*bufsize * sizeof(char)); - if (!newbuffer) { + newbuffer = (char *)malloc(*bufsize*sizeof(char)); + if(!newbuffer){ free(*buffer); mxml_error("Unable to expand string buffer to %d bytes!", *bufsize); return (-1); } - memset(newbuffer, 0, *bufsize * sizeof(char)); - memcpy(newbuffer, *buffer, *bufptr - *buffer); + memset(newbuffer,0,*bufsize*sizeof(char)); + memcpy(newbuffer,*buffer,*bufptr - *buffer); free(*buffer); *bufptr = newbuffer + (*bufptr - *buffer); *buffer = newbuffer; } - if (ch < 128) { - /* - * Single byte ASCII... - */ + if (ch < 128) + { + /* + * Single byte ASCII... + */ *(*bufptr)++ = ch; - } else if (ch < 2048) { - /* - * Two-byte UTF-8... - */ + } + else if (ch < 2048) + { + /* + * Two-byte UTF-8... + */ *(*bufptr)++ = 0xc0 | (ch >> 6); *(*bufptr)++ = 0x80 | (ch & 0x3f); - } else if (ch < 65536) { - /* - * Three-byte UTF-8... - */ + } + else if (ch < 65536) + { + /* + * Three-byte UTF-8... + */ *(*bufptr)++ = 0xe0 | (ch >> 12); *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f); *(*bufptr)++ = 0x80 | (ch & 0x3f); - } else { - /* - * Four-byte UTF-8... - */ + } + else + { + /* + * Four-byte UTF-8... + */ *(*bufptr)++ = 0xf0 | (ch >> 18); *(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f); @@ -219,21 +229,27 @@ static int /* O - 0 on success, -1 on error */ myxml_add_char(int ch, /* I - return (0); } - /*------------------------------------------------------------------*/ extern char *stptok(char *s, char *tok, size_t toklen, char *brk); /*===================================================================== actual stuff for implementing the callback functions =====================================================================*/ -void analyzeDim(const char *typeString, int *rank, int *iDim, int *type) -{ + +/* + * if passed NX_CHAR, then returns dimension of -1 and the caller + * needs to do a strlen() or equivalent + */ +void analyzeDim(const char *typeString, int *rank, + int64_t *iDim, int *type){ char dimString[132]; char dim[20]; - char *dimStart, *dimEnd; + const char *dimStart, *dimEnd; + char* dimTemp; int myRank; - if (strchr(typeString, (int) '[') == NULL) { - switch (*type) { + if(strchr(typeString,(int)'[') == NULL){ + *rank = 1; + switch(*type){ case NX_INT8: case NX_UINT8: case NX_INT16: @@ -247,44 +263,45 @@ void analyzeDim(const char *typeString, int *rank, int *iDim, int *type) iDim[0] = 1; break; case NX_CHAR: - iDim[0] = -1; + iDim[0] = -1; /* length unknown, caller needs to determine later */ + break; + default: + mxml_error("ERROR: (analyzeDim) unknown type code %d for typeString %s", *type, typeString); break; } } else { /* - we have to determine rank and the dims. - Start by extracting the dimension string. - */ - dimStart = strchr(typeString, (int) '[') + 1; - dimEnd = strchr(typeString, (int) ']'); - if (!dimStart || !dimEnd) { - mxml_error("ERROR: malformed dimension string in %s", typeString); + we have to determine rank and the dims. + Start by extracting the dimension string. + */ + dimStart = strchr(typeString,(int)'[') + 1; + dimEnd = strchr(typeString,(int)']'); + if(!dimStart || !dimEnd) { + mxml_error("ERROR: malformed dimension string in %s",typeString); return; } - if ((dimEnd - dimStart) > 131) { - mxml_error("ERROR: run away dimension definition in %s", typeString); + if((dimEnd - dimStart) > 131){ + mxml_error("ERROR: run away dimension definition in %s",typeString); return; } - memset(dimString, 0, 132); - memcpy(dimString, dimStart, (dimEnd - dimStart) * sizeof(char)); - dimStart = stptok(dimString, dim, 19, ","); + memset(dimString,0,132); + memcpy(dimString,dimStart,(dimEnd-dimStart)*sizeof(char)); + dimTemp = stptok(dimString,dim,19,","); myRank = 0; - while (dimStart != NULL) { + while(dimTemp != NULL){ iDim[myRank] = atoi(dim); - dimStart = stptok(dimStart, dim, 19, ","); + dimTemp = stptok(dimTemp,dim,19,","); myRank++; } *rank = myRank; } } - /*--------------------------------------------------------------------*/ -int translateTypeCode(char *code) -{ +int translateTypeCode(const char *code){ int i, result = -1; - - for (i = 0; i < NTYPECODE; i++) { - if (strstr(code, typecode[i].name) != NULL) { + + for(i = 0; i < NTYPECODE; i++){ + if(strstr(code,typecode[i].name) != NULL){ result = typecode[i].nx_type; break; } @@ -292,68 +309,95 @@ int translateTypeCode(char *code) return result; } -/*---------------------------------------------------------------------*/ -static void analyzeDataType(mxml_node_t * parent, int *rank, int *type, - int *iDim) +/* + * This is used to locate an Idims node from the new style table data layout + */ +static mxml_node_t* findDimsNode(mxml_node_t *node) { + mxml_node_t *tnode = NULL; + const char* name = node->value.element.name; + if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DATA_NODE_NAME) ) + { + tnode = mxmlFindElement(node->parent->parent, node->parent->parent, DIMS_NODE_NAME, NULL, NULL, MXML_DESCEND_FIRST); + if (tnode != NULL) + { + tnode = mxmlFindElement(tnode,tnode,name,NULL,NULL,MXML_DESCEND_FIRST); + } + } + return tnode; +} + +/*---------------------------------------------------------------------*/ +/*return 1 if in table mode , 0 if not */ +static void analyzeDataType(mxml_node_t *parent, int *rank, int *type, + int64_t *iDim){ const char *typeString; - mxml_type_t myType; - int i, nx_type = -1; + mxml_node_t* tnode; + int nx_type = -1; + int table_mode = 0; *rank = 1; *type = NX_CHAR; iDim[0] = -1; /* - get the type attribute. No attribute means: plain text - */ - typeString = mxmlElementGetAttr(parent, TYPENAME); - if (typeString == NULL) { + get the type attribute. No attribute means: plain text + */ + tnode = findDimsNode(parent); + if (tnode != NULL) + { + table_mode = 1; + parent = tnode; + } + typeString = mxmlElementGetAttr(parent,TYPENAME); + if(typeString == NULL){ return; } - nx_type = translateTypeCode((char *) typeString); + nx_type = translateTypeCode((char *)typeString); /* - assign type - */ - if (nx_type == -1) { - mxml_error - ("ERROR: %s is an invalid NeXus type, I try to continue but may fail", - typeString); - *type = NX_CHAR; + assign type + */ + if(nx_type == -1){ + mxml_error( + "ERROR: %s is an invalid NeXus type, I try to continue but may fail", + typeString); + *type =NX_CHAR; return; } *type = nx_type; - + analyzeDim(typeString, rank, iDim, type); + if (table_mode) + { + *rank = 1; + iDim[0] = 1; + } + return; } - /*-------------------------------------------------------------------*/ -void destroyDataset(void *data) -{ - if (data != NULL) { - dropNXDataset((pNXDS) data); +void destroyDataset(void *data){ + if(data != NULL){ + dropNXDataset((pNXDS)data); } } - /*-------------------------------------------------------------------*/ -static char *getNextNumber(char *pStart, char pNumber[80]) -{ +static char *getNextNumber(char *pStart, char pNumber[80]){ int charCount = 0; pNumber[0] = '\0'; /* advance to first digit */ - while (isspace(*pStart) && *pStart != '\0') { + while(isspace(*pStart) && *pStart != '\0'){ pStart++; } - if (*pStart == '\0') { + if(*pStart == '\0'){ return NULL; } /* copy */ - while (!isspace(*pStart) && *pStart != '\0' && charCount < 78) { + while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){ pNumber[charCount] = *pStart; pStart++; charCount++; @@ -361,108 +405,111 @@ static char *getNextNumber(char *pStart, char pNumber[80]) pNumber[charCount] = '\0'; return pStart; } - /*--------------------------------------------------------------------*/ -mxml_type_t nexusTypeCallback(mxml_node_t * parent) -{ +mxml_type_t nexusTypeCallback(mxml_node_t *parent){ const char *typeString; - if (strstr(parent->value.element.name, "?xml") != NULL || - strstr(parent->value.element.name, "NX") != NULL) { + if(strstr(parent->value.element.name,"?xml") != NULL || + !strncmp(parent->value.element.name,"NX",2) || + !strcmp(parent->value.element.name,DATA_NODE_NAME) || + !strcmp(parent->value.element.name,DIMS_NODE_NAME)){ return MXML_ELEMENT; } else { - typeString = mxmlElementGetAttr(parent, TYPENAME); - if (typeString == NULL) { + /* data nodes do not habe TYPENAME in table style but are always CUSTOM */ + if (parent->parent != NULL && !strcmp(parent->parent->value.element.name, DATA_NODE_NAME)) + { + return MXML_CUSTOM; + } + if (parent->parent != NULL && !strcmp(parent->parent->value.element.name, DIMS_NODE_NAME)) + { + return MXML_OPAQUE; + } + typeString = mxmlElementGetAttr(parent,TYPENAME); + if(typeString == NULL){ /* - MXML_TEXT seems more appropriate here. But mxml hacks text into - single words which is not what NeXus wants. - */ + MXML_TEXT seems more appropriate here. But mxml hacks text into + single words which is not what NeXus wants. + */ return MXML_OPAQUE; - } else { - if (strstr(typeString, "NX_CHAR") != NULL) { - return MXML_OPAQUE; + } else{ + if(strstr(typeString,"NX_CHAR") != NULL){ + return MXML_OPAQUE; } else { - return MXML_CUSTOM; + return MXML_CUSTOM; } } } } - /*----------------------------------------------------------------------*/ -int nexusLoadCallback(mxml_node_t * node, const char *buffer) -{ +int nexusLoadCallback(mxml_node_t *node, const char *buffer){ mxml_node_t *parent = NULL; - int rank, type, iDim[NX_MAXRANK]; + int rank, type; + int64_t iDim[NX_MAXRANK]; char pNumber[80], *pStart; long address, maxAddress; pNXDS dataset = NULL; - int i; parent = node->parent; - analyzeDataType(parent, &rank, &type, iDim); - if (iDim[0] == -1) { + analyzeDataType(parent,&rank,&type,iDim); + if(iDim[0] == -1 || !strcmp(parent->parent->value.element.name, DIMS_NODE_NAME)){ iDim[0] = strlen(buffer); node->value.custom.data = strdup(buffer); node->value.custom.destroy = free; return 0; } else { - node->value.custom.data = createNXDataset(rank, type, iDim); - dataset = (pNXDS) node->value.custom.data; - if (dataset == NULL) { + node->value.custom.data = createNXDataset(rank,type,iDim); + dataset = (pNXDS)node->value.custom.data; + if(dataset == NULL){ mxml_error("Failed to allocate custom dataset"); return 1; } - node->value.custom.destroy = destroyDataset; + node->value.custom.destroy = destroyDataset; } /* - load data - */ - pStart = (char *) buffer; + load data + */ + pStart = (char *)buffer; maxAddress = getNXDatasetLength(dataset); address = 0; - while ((pStart = getNextNumber(pStart, pNumber)) != NULL && - address < maxAddress) { - putNXDatasetValueAt(dataset, address, atof(pNumber)); + while( (pStart = getNextNumber(pStart,pNumber)) != NULL && + address < maxAddress){ + putNXDatasetValueAt(dataset,address,atof(pNumber)); address++; } return 0; } - /*---------------------------------------------------------------------*/ -static void stringIntoBuffer(char **buffer, char **bufPtr, int *bufSize, - char *string) -{ - int i; +static void stringIntoBuffer(char **buffer, char **bufPtr, size_t *bufSize, + char *string){ + size_t i; - for (i = 0; i < strlen(string); i++) { - myxml_add_char(string[i], bufPtr, buffer, bufSize); + for(i = 0; i < strlen(string); i++){ + myxml_add_char(string[i],bufPtr,buffer,bufSize); } } - /*--------------------------------------------------------------------*/ static void formatNumber(double value, char *txt, int txtLen, - char *format, int type) -{ - switch (type) { + char *format, int type){ + switch(type){ case NX_INT8: case NX_UINT8: case NX_INT16: case NX_UINT16: case NX_INT32: case NX_UINT32: - snprintf(txt, txtLen, format, (int) value); + snprintf(txt,txtLen,format,(int)value); break; case NX_INT64: - snprintf(txt, txtLen, format, (int64_t) value); + snprintf(txt,txtLen,format,(int64_t)value); break; case NX_UINT64: - snprintf(txt, txtLen, format, (uint64_t) value); + snprintf(txt,txtLen,format,(uint64_t)value); break; case NX_FLOAT32: case NX_FLOAT64: - snprintf(txt, txtLen, format, value); + snprintf(txt,txtLen,format,value); break; default: /*assert(0); something is very wrong here */ @@ -470,205 +517,231 @@ static void formatNumber(double value, char *txt, int txtLen, break; } } - /*--------------------------------------------------------------------*/ -static int countDepth(mxml_node_t * node) -{ +static int countDepth(mxml_node_t *node){ int count = 0; mxml_node_t *cur; cur = node; - while (cur != NULL) { + while(cur != NULL){ count++; cur = cur->parent; } count--; return count; } - /*---------------------------------------------------------------------*/ -char *nexusWriteCallback(mxml_node_t * node) -{ +char *nexusWriteCallback(mxml_node_t *node){ int type, col; char pNumber[80], indent[80], format[30]; char *buffer, *bufPtr; pNXDS dataset; - int bufsize, i, length, currentLen; + int currentLen, table_style = 0; + size_t i, bufsize, length; + int is_definition = 0; + /* this is set by nxconvert when making a definiton */ + is_definition = (getenv("NX_IS_DEFINITION") != NULL); + if (!strcmp(node->parent->parent->value.element.name, DATA_NODE_NAME)) + { + table_style = 1; + } /* - allocate output buffer - */ - buffer = (char *) malloc(1024 * sizeof(char)); - if (buffer == NULL) { + allocate output buffer + */ + buffer = (char *)malloc(1024*sizeof(char)); + if(buffer == NULL){ mxml_error("Unable to allocate buffer"); return NULL; } - memset(buffer, 0, 1024); + memset(buffer,0,1024); bufPtr = buffer; bufsize = 1024; - dataset = (pNXDS) node->value.custom.data; + dataset = (pNXDS)node->value.custom.data; /* - prepare indentation level - */ - col = countDepth(node) * 2; - memset(indent, 0, 80); - for (i = 0; i < col; i++) { + prepare indentation level + */ + col = countDepth(node)*2; + memset(indent,0,80); + for(i = 0; i < col; i++){ indent[i] = ' '; } /* - get dataset info - */ + get dataset info + */ type = getNXDatasetType(dataset); - length = getNXDatasetLength(dataset); - if (dataset->format != NULL) { - strcpy(format, dataset->format); + if (is_definition) { + length = 1; } else { - getNumberFormat(type, format); + length = getNXDatasetLength(dataset); + } + if(dataset->format != NULL){ + strcpy(format,dataset->format); + } else { + getNumberFormat(type,format); } /* - actually get the data out - */ - currentLen = col; - myxml_add_char('\n', &bufPtr, &buffer, &bufsize); - stringIntoBuffer(&buffer, &bufPtr, &bufsize, indent); - for (i = 0; i < length; i++) { - formatNumber(getNXDatasetValueAt(dataset, i), pNumber, 79, format, - type); - if (currentLen + strlen(pNumber) > MXML_WRAP) { - /* - wrap line - */ - myxml_add_char('\n', &bufPtr, &buffer, &bufsize); - stringIntoBuffer(&buffer, &bufPtr, &bufsize, indent); + actually get the data out + */ + if (table_style) + { + for(i = 0; i < length; i++){ + formatNumber(getNXDatasetValueAt(dataset,i),pNumber,79,format,type); + stringIntoBuffer(&buffer,&bufPtr,&bufsize,pNumber); + } + } + else + { currentLen = col; - } - stringIntoBuffer(&buffer, &bufPtr, &bufsize, pNumber); - myxml_add_char(' ', &bufPtr, &buffer, &bufsize); - currentLen += strlen(pNumber) + 1; + myxml_add_char('\n',&bufPtr,&buffer,&bufsize); + stringIntoBuffer(&buffer,&bufPtr,&bufsize,indent); + for(i = 0; i < length; i++){ + formatNumber(getNXDatasetValueAt(dataset,i),pNumber,79,format,type); + if(currentLen + strlen(pNumber) > MXML_WRAP){ + /* + wrap line + */ + myxml_add_char('\n',&bufPtr,&buffer,&bufsize); + stringIntoBuffer(&buffer,&bufPtr,&bufsize,indent); + currentLen = col; + } + stringIntoBuffer(&buffer,&bufPtr,&bufsize,pNumber); + myxml_add_char(' ',&bufPtr,&buffer,&bufsize); + currentLen += strlen(pNumber) + 1; + } } - myxml_add_char('\0', &bufPtr, &buffer, &bufsize); - return (char *) buffer; + myxml_add_char('\0',&bufPtr,&buffer,&bufsize); + return (char *)buffer; } - /*------------------------------------------------------------------*/ -int isDataNode(mxml_node_t * node) -{ - if (mxmlElementGetAttr(node, "name") != NULL) { +int isDataNode(mxml_node_t *node){ + if(mxmlElementGetAttr(node,"name") != NULL){ return 0; } - if (strcmp(node->value.element.name, "NXroot") == 0) { + if(strcmp(node->value.element.name,"NXroot") == 0){ return 0; } - if (strcmp(node->value.element.name, "NAPIlink") == 0) { + if(strcmp(node->value.element.name,DIMS_NODE_NAME) == 0){ + return 0; + } + if(strcmp(node->value.element.name,DATA_NODE_NAME) == 0){ + return 0; + } + if(strcmp(node->value.element.name,"NAPIlink") == 0){ return 0; } return 1; } - /*--------------------------------------------------------------------*/ -static int isTextData(mxml_node_t * node) -{ +static int isTextData(mxml_node_t *node){ const char *attr = NULL; - int rank, type = 0, iDim[NX_MAXRANK]; - if (!isDataNode(node)) { + if(!isDataNode(node)){ return 0; } /* - test datasets - */ - attr = mxmlElementGetAttr(node, TYPENAME); - if (attr == NULL) { + test datasets + */ + attr = mxmlElementGetAttr(node,TYPENAME); + if(attr == NULL){ return 1; } - analyzeDim(attr, &rank, iDim, &type); - if (type == NX_CHAR) { + if(strstr(attr,"NX_CHAR") != NULL){ return 1; } else { return 0; } } - /*---------------------------------------------------------------------*/ /* * note: not reentrant or thead safe; returns pointer to static storage */ -const char *NXwhitespaceCallback(mxml_node_t * node, int where) -{ +const char *NXwhitespaceCallback(mxml_node_t *node, int where){ static char *indent = NULL; - int len; + int len; - if (strstr(node->value.element.name, "?xml") != NULL) { + if(strstr(node->value.element.name,"?xml") != NULL){ + return NULL; + } + if (node->parent != NULL && !strcmp(node->parent->value.element.name, DATA_NODE_NAME)) + { + return NULL; + } + if (where == MXML_WS_BEFORE_CLOSE && !strcmp(node->value.element.name, DATA_NODE_NAME)) + { return NULL; } - if (isTextData(node)) { - if (where == MXML_WS_BEFORE_OPEN) { - len = countDepth(node) * 2 + 2; - if (indent != NULL) { - free(indent); - indent = NULL; + if(isTextData(node)){ + if(where == MXML_WS_BEFORE_OPEN){ + len = countDepth(node)*2 + 2; + if (indent != NULL) + { + free(indent); + indent = NULL; } - indent = (char *) malloc(len * sizeof(char)); - if (indent != NULL) { - memset(indent, ' ', len); - indent[0] = '\n'; - indent[len - 1] = '\0'; - return (const char *) indent; + indent = (char *)malloc(len*sizeof(char)); + if(indent != NULL){ + memset(indent,' ',len); + indent[0]= '\n'; + indent[len-1] = '\0'; + return (const char*)indent; } } return NULL; } - if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_BEFORE_CLOSE) { - len = countDepth(node) * 2 + 2; - if (indent != NULL) { - free(indent); - indent = NULL; + if(where == MXML_WS_BEFORE_OPEN || where == MXML_WS_BEFORE_CLOSE){ + len = countDepth(node)*2 + 2; + if (indent != NULL) + { + free(indent); + indent = NULL; } - indent = (char *) malloc(len * sizeof(char)); - if (indent != NULL) { - memset(indent, ' ', len); - indent[0] = '\n'; - indent[len - 1] = '\0'; - return (const char *) indent; + indent = (char *)malloc(len*sizeof(char)); + if(indent != NULL){ + memset(indent,' ',len); + indent[0]= '\n'; + indent[len-1] = '\0'; + return (const char*)indent; } } return NULL; } - /*-----------------------------------------------------------------------*/ #ifdef TESTMAIN #include -int main(int argc, char *argv[]) -{ - mxml_node_t *root = NULL; - FILE *f; +int main(int argc, char *argv[]){ + mxml_node_t *root = NULL; + FILE *f; - mxmlSetCustomHandlers(nexusLoadCallback, nexusWriteCallback); - initializeNumberFormats(); + mxmlSetCustomHandlers(nexusLoadCallback, nexusWriteCallback); + initializeNumberFormats(); - /* + /* read test */ - f = fopen("dmc.xml", "r"); - root = mxmlLoadFile(NULL, f, nexusTypeCallback); - fclose(f); + f = fopen("dmc.xml","r"); + root = mxmlLoadFile(NULL,f,nexusTypeCallback); + fclose(f); - /* + /* write test */ - setNumberFormat(NX_INT32, "%8d"); - setNumberFormat(NX_FLOAT32, "%8.2f"); - f = fopen("dmc2.xml", "w"); - mxmlSaveFile(root, f, NXwhitespaceCallback); - fclose(f); + setNumberFormat(NX_INT32,"%8d"); + setNumberFormat(NX_FLOAT32,"%8.2f"); + f = fopen("dmc2.xml","w"); + mxmlSaveFile(root,f,NXwhitespaceCallback); + fclose(f); } #endif + + +#endif /*NXXML*/ diff --git a/nxio.h b/nxio.h index b2d44cae..1788762a 100644 --- a/nxio.h +++ b/nxio.h @@ -20,7 +20,7 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * For further information, see + * For further information, see */ #ifndef __NXIO @@ -29,18 +29,22 @@ #define TYPENAME "NAPItype" -mxml_type_t nexusTypeCallback(mxml_node_t * parent); -const char *NXwhitespaceCallback(mxml_node_t * node, int where); -int nexusLoadCallback(mxml_node_t * node, const char *buffer); -char *nexusWriteCallback(mxml_node_t * node); +#define DIMS_NODE_NAME "columns" +#define DATA_NODE_NAME "row" + +mxml_type_t nexusTypeCallback(mxml_node_t *parent); +const char *NXwhitespaceCallback(mxml_node_t *node, int where); +int nexusLoadCallback(mxml_node_t *node, const char *buffer); +char *nexusWriteCallback(mxml_node_t *node); void setNumberFormat(int dataType, char *formatString); void initializeNumberFormats(); void getNumberText(int nx_type, char *typestring, int typeLen); void destroyDataset(void *data); -int translateTypeCode(char *code); -int isDataNode(mxml_node_t * node); -void analyzeDim(const char *typeString, int *rank, int *iDim, int *type); +int translateTypeCode(const char *code); +int isDataNode(mxml_node_t *node); +void analyzeDim(const char *typeString, int *rank, + int64_t *iDim, int *type); #endif diff --git a/nxscript.c b/nxscript.c index ae899bbb..fc6277b1 100644 --- a/nxscript.c +++ b/nxscript.c @@ -828,7 +828,7 @@ static void putHistogramMemoryChunked(SConnection * pCon, int status, start, length, i, noChunks, chunkDim[MAXDIM], rank; HistInt *iData = NULL; char buffer[256]; - int subset; + int subset =0; if (argc < 5) { SCWrite(pCon, diff --git a/nxstack.c b/nxstack.c index 3199f8e2..a5ba2bd7 100644 --- a/nxstack.c +++ b/nxstack.c @@ -18,7 +18,10 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see + + Added code to support the path stack for NXgetpath, + Mark Koennecke, October 2009 */ #include #include @@ -33,88 +36,110 @@ typedef struct { pNexusFunction pDriver; NXlink closeID; char filename[1024]; -} fileStackEntry; +}fileStackEntry; typedef struct __fileStack { int fileStackPointer; fileStackEntry fileStack[MAXEXTERNALDEPTH]; -} fileStack; + int pathPointer; + char pathStack[NXMAXSTACK][NX_MAXNAMELEN]; +}fileStack; /*---------------------------------------------------------------------*/ -pFileStack makeFileStack() -{ +pFileStack makeFileStack(){ pFileStack pNew = NULL; - - pNew = malloc(sizeof(fileStack)); - if (pNew == NULL) { + + pNew = (pFileStack)malloc(sizeof(fileStack)); + if(pNew == NULL){ return NULL; } - memset(pNew, 0, sizeof(fileStack)); + memset(pNew,0,sizeof(fileStack)); pNew->fileStackPointer = -1; + pNew->pathPointer = -1; return pNew; } - /*---------------------------------------------------------------------*/ -void killFileStack(pFileStack self) -{ - if (self != NULL) { +void killFileStack(pFileStack self){ + if(self != NULL){ free(self); } } - +/*---------------------------------------------------------------------*/ +int getFileStackSize(){ + return sizeof(fileStack); +} /*----------------------------------------------------------------------*/ -void pushFileStack(pFileStack self, pNexusFunction pDriv, char *file) -{ - int length; +void pushFileStack(pFileStack self, pNexusFunction pDriv, char *file){ + size_t length; self->fileStackPointer++; self->fileStack[self->fileStackPointer].pDriver = pDriv; - memset(&self->fileStack[self->fileStackPointer].closeID, 0, - sizeof(NXlink)); + memset(&self->fileStack[self->fileStackPointer].closeID,0,sizeof(NXlink)); length = strlen(file); - if (length >= 1024) { + if(length >= 1024){ length = 1023; } - memcpy(&self->fileStack[self->fileStackPointer].filename, file, length); + memcpy(&self->fileStack[self->fileStackPointer].filename,file,length); } - /*----------------------------------------------------------------------*/ -void popFileStack(pFileStack self) -{ +void popFileStack(pFileStack self){ self->fileStackPointer--; - if (self->fileStackPointer < -1) { + if(self->fileStackPointer < -1){ self->fileStackPointer = -1; } } - /*----------------------------------------------------------------------*/ -pNexusFunction peekFileOnStack(pFileStack self) -{ +pNexusFunction peekFileOnStack(pFileStack self){ return self->fileStack[self->fileStackPointer].pDriver; } - /*---------------------------------------------------------------------*/ -char *peekFilenameOnStack(pFileStack self) -{ +char *peekFilenameOnStack(pFileStack self){ return self->fileStack[self->fileStackPointer].filename; } - /*----------------------------------------------------------------------*/ -void peekIDOnStack(pFileStack self, NXlink * id) -{ - memcpy(id, &self->fileStack[self->fileStackPointer].closeID, - sizeof(NXlink)); +void peekIDOnStack(pFileStack self, NXlink *id){ + memcpy(id, &self->fileStack[self->fileStackPointer].closeID, sizeof(NXlink)); } - /*---------------------------------------------------------------------*/ -void setCloseID(pFileStack self, NXlink id) -{ - memcpy(&self->fileStack[self->fileStackPointer].closeID, &id, - sizeof(NXlink)); +void setCloseID(pFileStack self, NXlink id){ + memcpy(&self->fileStack[self->fileStackPointer].closeID, &id, sizeof(NXlink)); } - /*----------------------------------------------------------------------*/ -int fileStackDepth(pFileStack self) -{ +int fileStackDepth(pFileStack self){ return self->fileStackPointer; } +/*----------------------------------------------------------------------*/ +void pushPath(pFileStack self, const char *name){ + self->pathPointer++; + strncpy(self->pathStack[self->pathPointer],name,NX_MAXNAMELEN-1); +} +/*-----------------------------------------------------------------------*/ +void popPath(pFileStack self){ + self->pathPointer--; + if(self->pathPointer < -1){ + self->pathPointer = -1; + } +} +/*-----------------------------------------------------------------------*/ +int buildPath(pFileStack self, char *path, int pathlen){ + int i; + size_t totalPathLength; + char *totalPath; + + for(i = 0, totalPathLength = 5; i <= self->pathPointer; i++){ + totalPathLength += strlen(self->pathStack[i]) + 1; + } + totalPath = (char*)malloc(totalPathLength*sizeof(char)); + if(totalPath == NULL){ + return 0; + } + memset(totalPath,0,totalPathLength*sizeof(char)); + for(i = 0; i <= self->pathPointer; i++){ + strcat(totalPath,"/"); + strcat(totalPath,self->pathStack[i]); + } + + strncpy(path,totalPath,pathlen-1); + free(totalPath); + return 1; +} diff --git a/nxstack.h b/nxstack.h index 578129fe..2faaf041 100755 --- a/nxstack.h +++ b/nxstack.h @@ -18,7 +18,11 @@ License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - For further information, see + For further information, see + + Added functions to deal with the path stack for NXgetpath + Mark Koennecke, October 2009 + */ #ifndef NEXUSFILESTACK #define NEXUSFILESTACK @@ -28,15 +32,21 @@ typedef struct __fileStack *pFileStack; pFileStack makeFileStack(); void killFileStack(pFileStack self); +int getFileStackSize(); void pushFileStack(pFileStack self, pNexusFunction pDriv, char *filename); void popFileStack(pFileStack self); pNexusFunction peekFileOnStack(pFileStack self); char *peekFilenameOnStack(pFileStack self); -void peekIDOnStack(pFileStack self, NXlink * id); +void peekIDOnStack(pFileStack self, NXlink *id); void setCloseID(pFileStack self, NXlink id); - + int fileStackDepth(pFileStack self); +void pushPath(pFileStack self, const char *name); +void popPath(pFileStack self); +int buildPath(pFileStack self, char *path, int pathlen); + #endif + diff --git a/nxxml.c b/nxxml.c index 559682b1..12f4de16 100644 --- a/nxxml.c +++ b/nxxml.c @@ -20,18 +20,26 @@ * * For further information, see */ + + +#ifdef NXXML + #include -#include #include +#include #include +#include #include #include "nxio.h" #include "nxdataset.h" +#ifdef _MSC_VER +#define snprintf _snprintf +#endif /* _MSC_VER */ -extern void *NXpData; - -char *nxitrim(char *str); /* from napi.c */ +extern void *NXpData; +extern int validNXName(const char* name, int allow_colon); /* from napi.c */ +char *nxitrim(char *str); /* from napi.c */ /*----------------------- our data structures -------------------------- One might wonder why a node stack is still needed even if this API @@ -46,46 +54,63 @@ char *nxitrim(char *str); /* from napi.c */ the tree. -----------------------------------------------------------------------*/ typedef struct { - mxml_node_t *current; - mxml_node_t *currentChild; - int currentAttribute; -} xmlStack; + mxml_node_t *current; + mxml_node_t *currentChild; + int currentAttribute; + int options; /**< additional information about the node */ +}xmlStack; + +/* + * Freddie Akeroyd, 19/03/2008 + * + * Add in support for table style data writing - this is + * indicated internally via the XMLSTACK_OPTION_TABLE flag + * and separates the dimensions and data into separate nodes contained + * in DIMS_NODE_NAME and DATA_NODE_NAME. This is a first commit and + * involves some code duplication that will need to be cleaned up later. + * Also writing in table style is only enabled for 1D arrays as + * I haven't done slab writing yet which the nexus test program uses + * for writing 2D arrays. + * + * Table output is enabled by opening a file with (NXACC_CREATEXML | NXACC_TABLE) + * + * See http://trac.nexusformat.org/code/ticket/111 for further details + */ +#define XMLSTACK_OPTION_TABLE 0x1 /**< indicates table option in xmlStack */ + + /*---------------------------------------------------------------------*/ typedef struct { - mxml_node_t *root; /* root node */ - int readOnly; /* read only flag */ - int stackPointer; /* stack pointer */ - char filename[1024]; /* file name, for NXflush, NXclose */ - xmlStack stack[NXMAXSTACK]; /* stack */ -} XMLNexus, *pXMLNexus; + mxml_node_t *root; /* root node */ + int readOnly; /* read only flag */ + int tableStyle; /**< whether to output data in XML table style */ + int stackPointer; /* stack pointer */ + char filename[1024]; /* file name, for NXflush, NXclose */ + xmlStack stack[NXMAXSTACK]; /* stack */ +}XMLNexus, *pXMLNexus; /*===================== support functions ===============================*/ extern char *stptok(char *s, char *tok, size_t toklen, char *brk); /*----------------------------------------------------------------------*/ -static mxml_node_t *getLinkTarget(pXMLNexus xmlHandle, const char *target) -{ +static mxml_node_t *getLinkTarget(pXMLNexus xmlHandle, const char *target){ mxml_node_t *node = NULL; mxml_node_t *testNode = NULL; char path[132], *pPtr; - pPtr = (char *) target + 1; + pPtr = (char *)target + 1; node = xmlHandle->stack[0].current; - while ((pPtr = stptok(pPtr, path, 131, "/")) != NULL) { + while((pPtr = stptok(pPtr,path,131,"/")) != NULL){ /* - search for group node - */ - testNode = - mxmlFindElement(node, node, NULL, "name", path, - MXML_DESCEND_FIRST); - if (testNode == NULL) { + search for group node + */ + testNode = mxmlFindElement(node,node,NULL,"name",path,MXML_DESCEND_FIRST); + if(testNode == NULL){ /* - it can still be a data node - */ - testNode = - mxmlFindElement(node, node, path, NULL, NULL, - MXML_DESCEND_FIRST); + it can still be a data node + */ + testNode = mxmlFindElement(node,node,path,NULL,NULL,MXML_DESCEND_FIRST); } - if (testNode == NULL) { - NXIReportError(NXpData, "Cannot follow broken link"); + if(testNode == NULL){ + NXReportError("Cannot follow broken link"); return NULL; } else { node = testNode; @@ -93,109 +118,111 @@ static mxml_node_t *getLinkTarget(pXMLNexus xmlHandle, const char *target) } return node; } - /*==================== file functions ===================================*/ -static void errorCallbackForMxml(const char *txt) -{ - NXIReportError(NXpData, (char *) txt); +static void errorCallbackForMxml(const char *txt){ + NXReportError((char *)txt); } - /*-----------------------------------------------------------------------*/ -NXstatus NXXopen(CONSTCHAR * filename, NXaccess am, NXhandle * pHandle) -{ +NXstatus NXXopen(CONSTCHAR *filename, NXaccess am, + NXhandle* pHandle) { pXMLNexus xmlHandle = NULL; FILE *fp = NULL; char *time_buffer = NULL; mxml_node_t *current; /* - allocate data - */ - xmlHandle = (pXMLNexus) malloc(sizeof(XMLNexus)); - if (!xmlHandle) { - NXIReportError(NXpData, "Out of memory allocating XML file handle"); + allocate data + */ + xmlHandle = (pXMLNexus)malloc(sizeof(XMLNexus)); + if(!xmlHandle){ + NXReportError( "Out of memory allocating XML file handle"); return NX_ERROR; } - memset(xmlHandle, 0, sizeof(XMLNexus)); + memset(xmlHandle,0,sizeof(XMLNexus)); /* - initialize mxml XML parser - */ + initialize mxml XML parser + */ mxmlSetCustomHandlers(nexusLoadCallback, nexusWriteCallback); initializeNumberFormats(); mxmlSetErrorCallback(errorCallbackForMxml); + xmlHandle->tableStyle = ((am & NXACC_TABLE) ? 1 : 0); /* - open file - */ - strncpy(xmlHandle->filename, filename, 1023); - switch (am) { + open file + */ + strncpy(xmlHandle->filename,filename,1023); + switch(am & NXACCMASK_REMOVEFLAGS){ case NXACC_READ: xmlHandle->readOnly = 1; case NXACC_RDWR: - fp = fopen(filename, "r"); - if (fp == NULL) { - NXIReportError(NXpData, "Failed to open file:"); - NXIReportError(NXpData, (char *) filename); + fp = fopen(filename,"r"); + if(fp == NULL){ + NXReportError("Failed to open file:"); + NXReportError((char *)filename); free(xmlHandle); return NX_ERROR; } - xmlHandle->root = mxmlLoadFile(NULL, fp, nexusTypeCallback); + xmlHandle->root = mxmlLoadFile(NULL,fp,nexusTypeCallback); xmlHandle->stack[0].current = mxmlFindElement(xmlHandle->root, - xmlHandle->root, - "NXroot", - NULL, NULL, - MXML_DESCEND); + xmlHandle->root, + "NXroot", + NULL,NULL, + MXML_DESCEND); xmlHandle->stack[0].currentChild = NULL; xmlHandle->stack[0].currentAttribute = 0; + xmlHandle->stack[0].options = 0; fclose(fp); break; case NXACC_CREATEXML: xmlHandle->root = mxmlNewElement(NULL, - "?xml version=\"1.0\" encoding=\"UTF-8\"?"); - current = mxmlNewElement(xmlHandle->root, "NXroot"); - mxmlElementSetAttr(current, "NeXus_version", NEXUS_VERSION); - mxmlElementSetAttr(current, "XML_version", "mxml"); - mxmlElementSetAttr(current, "file_name", filename); + "?xml version=\"1.0\" encoding=\"UTF-8\"?"); + current = mxmlNewElement(xmlHandle->root,"NXroot"); + mxmlElementSetAttr(current,"NeXus_version",NEXUS_VERSION); + mxmlElementSetAttr(current,"XML_version","mxml"); + mxmlElementSetAttr(current,"file_name",filename); + mxmlElementSetAttr(current,"xmlns", NEXUS_SCHEMA_NAMESPACE); + mxmlElementSetAttr(current,"xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance"); + mxmlElementSetAttr(current,"xsi:schemaLocation", + NEXUS_SCHEMA_NAMESPACE " " NEXUS_SCHEMA_URL); time_buffer = NXIformatNeXusTime(); - if (time_buffer != NULL) { - mxmlElementSetAttr(current, "file_time", time_buffer); + if(time_buffer != NULL){ + mxmlElementSetAttr(current,"file_time",time_buffer); free(time_buffer); - } + } xmlHandle->stack[0].current = current; xmlHandle->stack[0].currentChild = NULL; xmlHandle->stack[0].currentAttribute = 0; + xmlHandle->stack[0].options = 0; break; default: - NXIReportError(NXpData, "Bad access parameter specified in NXXopen"); + NXReportError("Bad access parameter specified in NXXopen"); return NX_ERROR; } - if (xmlHandle->stack[0].current == NULL) { - NXIReportError(NXpData, - "No NXroot element in XML-file, no NeXus-XML file"); - return NX_ERROR; + if(xmlHandle->stack[0].current == NULL){ + NXReportError( + "No NXroot element in XML-file, no NeXus-XML file"); + return NX_ERROR; } *pHandle = xmlHandle; return NX_OK; } - /*----------------------------------------------------------------------*/ -NXstatus NXXclose(NXhandle * fid) -{ +NXstatus NXXclose (NXhandle* fid){ pXMLNexus xmlHandle = NULL; FILE *fp = NULL; - xmlHandle = (pXMLNexus) * fid; + xmlHandle = (pXMLNexus)*fid; assert(xmlHandle); - - if (xmlHandle->readOnly == 0) { - fp = fopen(xmlHandle->filename, "w"); - if (fp == NULL) { - NXIReportError(NXpData, "Failed to open NeXus XML file for writing"); + + if(xmlHandle->readOnly == 0) { + fp = fopen(xmlHandle->filename,"w"); + if(fp == NULL){ + NXReportError("Failed to open NeXus XML file for writing"); return NX_ERROR; } - mxmlSaveFile(xmlHandle->root, fp, NXwhitespaceCallback); + mxmlSaveFile(xmlHandle->root,fp,NXwhitespaceCallback); fclose(fp); } mxmlDelete(xmlHandle->root); @@ -203,60 +230,61 @@ NXstatus NXXclose(NXhandle * fid) *fid = NULL; return NX_OK; } - /*----------------------------------------------------------------------*/ -NXstatus NXXflush(NXhandle * fid) -{ +NXstatus NXXflush(NXhandle *fid){ pXMLNexus xmlHandle = NULL; FILE *fp = NULL; - xmlHandle = (pXMLNexus) * fid; + xmlHandle = (pXMLNexus)*fid; assert(xmlHandle); - - if (xmlHandle->readOnly == 0) { - fp = fopen(xmlHandle->filename, "w"); - if (fp == NULL) { - NXIReportError(NXpData, "Failed to open NeXus XML file for writing"); + + if(xmlHandle->readOnly == 0) { + fp = fopen(xmlHandle->filename,"w"); + if(fp == NULL){ + NXReportError("Failed to open NeXus XML file for writing"); return NX_ERROR; } - mxmlSaveFile(xmlHandle->root, fp, NXwhitespaceCallback); + mxmlSaveFile(xmlHandle->root,fp,NXwhitespaceCallback); fclose(fp); } return NX_OK; } - /*======================================================================= Group functions =========================================================================*/ -NXstatus NXXmakegroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass) -{ +NXstatus NXXmakegroup (NXhandle fid, CONSTCHAR *name, + CONSTCHAR *nxclass){ + char buffer[256]; pXMLNexus xmlHandle = NULL; mxml_node_t *newGroup = NULL; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, - "Close dataset before trying to create a group"); + if (!validNXName(name, 0)) + { + sprintf(buffer, "ERROR: invalid characters in group name \"%s\"", name); + NXReportError(buffer); return NX_ERROR; } - newGroup = - mxmlNewElement(xmlHandle->stack[xmlHandle->stackPointer].current, - nxclass); - if (!newGroup) { - NXIReportError(NXpData, "failed to allocate new group"); + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("Close dataset before trying to create a group"); return NX_ERROR; } - mxmlElementSetAttr(newGroup, "name", name); + + newGroup = mxmlNewElement(xmlHandle->stack[xmlHandle->stackPointer].current, + nxclass); + if(!newGroup){ + NXReportError("failed to allocate new group"); + return NX_ERROR; + } + mxmlElementSetAttr(newGroup,"name",name); return NX_OK; -} - +} /*----------------------------------------------------------------------*/ -static mxml_node_t *searchGroupLinks(pXMLNexus xmlHandle, CONSTCHAR * name, - CONSTCHAR * nxclass) -{ +static mxml_node_t *searchGroupLinks(pXMLNexus xmlHandle, CONSTCHAR *name, + CONSTCHAR *nxclass){ mxml_node_t *linkNode = NULL; mxml_node_t *current; mxml_node_t *test = NULL; @@ -265,196 +293,276 @@ static mxml_node_t *searchGroupLinks(pXMLNexus xmlHandle, CONSTCHAR * name, current = xmlHandle->stack[xmlHandle->stackPointer].current; linkNode = current; - while ((linkNode = - mxmlFindElement(linkNode, current, "NAPIlink", NULL, NULL, - MXML_DESCEND_FIRST)) != NULL) { - linkTarget = mxmlElementGetAttr(linkNode, "target"); - test = getLinkTarget(xmlHandle, linkTarget); - if (test != NULL) { - if (strcmp(test->value.element.name, nxclass) == 0) { - if (strcmp(mxmlElementGetAttr(test, "name"), name) == 0) { - return test; - } + while((linkNode = mxmlFindElement(linkNode,current,"NAPIlink",NULL,NULL, + MXML_DESCEND_FIRST)) != NULL){ + linkTarget = mxmlElementGetAttr(linkNode,"target"); + test = getLinkTarget(xmlHandle,linkTarget); + if(test != NULL){ + if(strcmp(test->value.element.name,nxclass) == 0){ + if(strcmp(mxmlElementGetAttr(test,"name"),name) == 0){ + return test; + } } } /* - test for named links - */ - linkName = mxmlElementGetAttr(linkNode, "name"); - if (test != NULL && linkName != NULL) { - if (strcmp(test->value.element.name, nxclass) == 0) { - if (strcmp(linkName, name) == 0) { - return test; - } + test for named links + */ + linkName = mxmlElementGetAttr(linkNode,"name"); + if(test != NULL && linkName != NULL){ + if(strcmp(test->value.element.name,nxclass) == 0){ + if(strcmp(linkName, name) == 0){ + return test; + } } } } return NULL; } - /*------------------------------------------------------------------------*/ -NXstatus NXXopengroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass) -{ +NXstatus NXXopengroup (NXhandle fid, CONSTCHAR *name, + CONSTCHAR *nxclass){ pXMLNexus xmlHandle = NULL; mxml_node_t *newGroup = NULL; char error[1024]; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "Close dataset before trying to open a group"); + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("Close dataset before trying to open a group"); return NX_ERROR; } - newGroup = - mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current, - xmlHandle->stack[xmlHandle->stackPointer].current, - nxclass, "name", name, MXML_DESCEND_FIRST); - if (newGroup == NULL) { - newGroup = searchGroupLinks(xmlHandle, name, nxclass); + newGroup = mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current, + xmlHandle->stack[xmlHandle->stackPointer].current, + nxclass, + "name", + name, + MXML_DESCEND_FIRST); + if(newGroup == NULL){ + newGroup = searchGroupLinks(xmlHandle,name,nxclass); } - if (!newGroup) { - snprintf(error, 1023, "Failed to open %s, %s", name, nxclass); - NXIReportError(NXpData, error); + if(!newGroup){ + snprintf(error,1023,"Failed to open %s, %s",name,nxclass); + NXReportError(error); return NX_ERROR; } xmlHandle->stackPointer++; xmlHandle->stack[xmlHandle->stackPointer].current = newGroup; xmlHandle->stack[xmlHandle->stackPointer].currentChild = NULL; xmlHandle->stack[xmlHandle->stackPointer].currentAttribute = 0; + xmlHandle->stack[xmlHandle->stackPointer].options = 0; return NX_OK; } - /*----------------------------------------------------------------------*/ -NXstatus NXXclosegroup(NXhandle fid) -{ +NXstatus NXXclosegroup (NXhandle fid){ pXMLNexus xmlHandle = NULL; - mxml_node_t *newGroup = NULL; - char error[1024]; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ /* - silently fix this - */ + silently fix this + */ NXXclosedata(fid); } - if (xmlHandle->stackPointer > 0) { + if(xmlHandle->stackPointer > 0){ xmlHandle->stackPointer--; } return NX_OK; } - /*========================================================================= dataset functions =========================================================================*/ -NXstatus NXXcompmakedata(NXhandle fid, CONSTCHAR * name, - int datatype, - int rank, - int dimensions[], - int compress_type, int chunk_size[]) -{ +NXstatus NXXcompmakedata64 (NXhandle fid, CONSTCHAR *name, + int datatype, + int rank, + int64_t dimensions[], + int compress_type, int64_t chunk_size[]){ /* - compression does not relly make sense with XML - */ - return NXXmakedata(fid, name, datatype, rank, dimensions); + compression does not relly make sense with XML + */ + return NXXmakedata64(fid,name,datatype,rank,dimensions); } - /*-----------------------------------------------------------------------*/ -static char *buildTypeString(int datatype, int rank, int dimensions[]) -{ +static char *buildTypeString(int datatype, int rank, int64_t dimensions[]){ char *typestring = NULL; char pNumber[20]; int i; /* - allocate data - */ - typestring = (char *) malloc(132 * sizeof(char)); - if (!typestring) { - NXIReportError(NXpData, "Failed to allocate typestring"); + allocate data + */ + typestring = (char *)malloc(132*sizeof(char)); + if(!typestring){ + NXReportError("Failed to allocate typestring"); return NULL; } - memset(typestring, 0, 132 * sizeof(char)); + memset(typestring,0,132*sizeof(char)); - getNumberText(datatype, typestring, 130); - if (rank > 1 || dimensions[0] > 1) { - strcat(typestring, "["); - snprintf(pNumber, 19, "%d", dimensions[0]); - strncat(typestring, pNumber, 130 - strlen(typestring)); - for (i = 1; i < rank; i++) { - snprintf(pNumber, 19, ",%d", dimensions[i]); - strncat(typestring, pNumber, 130 - strlen(typestring)); + getNumberText(datatype,typestring,130); + if(rank > 1 || datatype == NX_CHAR || dimensions[0] > 1) { + strcat(typestring,"["); + snprintf(pNumber,19,"%lld", (long long)dimensions[0]); + strncat(typestring,pNumber,130-strlen(typestring)); + for(i = 1; i < rank; i++){ + snprintf(pNumber,19,",%lld", (long long)dimensions[i]); + strncat(typestring,pNumber,130-strlen(typestring)); } - strcat(typestring, "]"); + strcat(typestring,"]"); } return typestring; } /*------------------------------------------------------------------------*/ -NXstatus NXXmakedata(NXhandle fid, - CONSTCHAR * name, int datatype, - int rank, int dimensions[]) -{ +NXstatus NXXmakedatatable64 (NXhandle fid, + CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[]){ + pXMLNexus xmlHandle = NULL; + mxml_node_t *dataNode = NULL, *dataNodeRoot = NULL, *dimsNode = NULL, *dimsNodeRoot = NULL; + mxml_node_t *newData = NULL; + mxml_node_t *current; + char *typestring; + int i, ndata; + char buffer[256]; + static int64_t one = 1; + + xmlHandle = (pXMLNexus)fid; + assert(xmlHandle); + if (!validNXName(name, 0)) + { + sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } + + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("Close dataset before trying to create a dataset"); + return NX_ERROR; + } + if(dimensions[0] < 0){ + dimensions[0] = 1; + } + + current = xmlHandle->stack[xmlHandle->stackPointer].current; + + dimsNodeRoot = mxmlFindElement(current, current, DIMS_NODE_NAME, NULL, NULL, MXML_DESCEND_FIRST); + if (dimsNodeRoot == NULL) + { + dimsNodeRoot = mxmlNewElement(current, DIMS_NODE_NAME); + } + dimsNode = mxmlNewElement(dimsNodeRoot, name); + mxmlNewOpaque(dimsNode, ""); + typestring = buildTypeString(datatype,rank,dimensions); + if(typestring != NULL){ + mxmlElementSetAttr(dimsNode,TYPENAME,typestring); + free(typestring); + } else { + NXReportError("Failed to allocate typestring"); + return NX_ERROR; + } + ndata = 1; + for(i=0; itype = MXML_CUSTOM; +/* newData->value.custom.data = createNXDataset(rank,datatype,dimensions); */ + newData->value.custom.data = createNXDataset(1,datatype,&one); + if(!newData->value.custom.data){ + NXReportError("Failed to allocate space for dataset"); + return NX_ERROR; + } + newData->value.custom.destroy = destroyDataset; + } + return NX_OK; +} + +NXstatus NXXmakedata64 (NXhandle fid, + CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[]){ pXMLNexus xmlHandle = NULL; mxml_node_t *dataNode = NULL; mxml_node_t *newData = NULL; mxml_node_t *current; char *typestring; + char buffer[256]; - xmlHandle = (pXMLNexus) fid; + + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, - "Close dataset before trying to create a dataset"); + if (!validNXName(name, 0)) + { + sprintf(buffer, "ERROR: invalid characters in dataset name \"%s\"", name); + NXReportError(buffer); return NX_ERROR; } - if (dimensions[0] < 0) { + + if (xmlHandle->tableStyle && datatype != NX_CHAR && dimensions[0] != NX_UNLIMITED && rank == 1) + { + return NXXmakedatatable64(fid,name,datatype,rank,dimensions); + } + + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("Close dataset before trying to create a dataset"); + return NX_ERROR; + } + if(dimensions[0] < 0){ dimensions[0] = 1; } current = xmlHandle->stack[xmlHandle->stackPointer].current; - dataNode = mxmlNewElement(current, name); - typestring = buildTypeString(datatype, rank, dimensions); - if (typestring != NULL) { - mxmlElementSetAttr(dataNode, TYPENAME, typestring); + dataNode = mxmlNewElement(current,name); + typestring = buildTypeString(datatype,rank,dimensions); + if(typestring != NULL){ + mxmlElementSetAttr(dataNode,TYPENAME,typestring); free(typestring); } else { - NXIReportError(NXpData, "Failed to allocate typestring"); + NXReportError("Failed to allocate typestring"); return NX_ERROR; } /* - NX_CHAR maps to MXML_OPAQUE datasets - */ - if (datatype == NX_CHAR) { - newData = mxmlNewOpaque(dataNode, ""); + NX_CHAR maps to MXML_OPAQUE datasets + */ + if(datatype == NX_CHAR){ + newData = mxmlNewOpaque(dataNode,""); return NX_OK; } else { - newData = (mxml_node_t *) malloc(sizeof(mxml_node_t)); - if (!newData) { - NXIReportError(NXpData, "Failed to allocate space for dataset"); + newData = (mxml_node_t *)malloc(sizeof(mxml_node_t)); + if(!newData){ + NXReportError("Failed to allocate space for dataset"); return NX_ERROR; } - memset(newData, 0, sizeof(mxml_node_t)); + memset(newData,0,sizeof(mxml_node_t)); mxmlAdd(dataNode, MXML_ADD_AFTER, MXML_ADD_TO_PARENT, newData); newData->type = MXML_CUSTOM; - newData->value.custom.data = - createNXDataset(rank, datatype, dimensions); - if (!newData->value.custom.data) { - NXIReportError(NXpData, "Failed to allocate space for dataset"); + newData->value.custom.data = createNXDataset(rank,datatype,dimensions); + if(!newData->value.custom.data){ + NXReportError("Failed to allocate space for dataset"); return NX_ERROR; } newData->value.custom.destroy = destroyDataset; } return NX_OK; } - /*----------------------------------------------------------------------*/ -static mxml_node_t *searchSDSLinks(pXMLNexus xmlHandle, CONSTCHAR * name) -{ +static mxml_node_t *searchSDSLinks(pXMLNexus xmlHandle, CONSTCHAR *name){ mxml_node_t *linkNode = NULL; mxml_node_t *current; mxml_node_t *test = NULL; @@ -463,196 +571,373 @@ static mxml_node_t *searchSDSLinks(pXMLNexus xmlHandle, CONSTCHAR * name) current = xmlHandle->stack[xmlHandle->stackPointer].current; linkNode = current; - while ((linkNode = - mxmlFindElement(linkNode, current, "NAPIlink", NULL, NULL, - MXML_DESCEND_FIRST)) != NULL) { - linkTarget = mxmlElementGetAttr(linkNode, "target"); - test = getLinkTarget(xmlHandle, linkTarget); - if (test != NULL) { - if (strcmp(test->value.element.name, name) == 0) { - return test; + while((linkNode = mxmlFindElement(linkNode,current,"NAPIlink",NULL,NULL, + MXML_DESCEND_FIRST)) != NULL){ + linkTarget = mxmlElementGetAttr(linkNode,"target"); + test = getLinkTarget(xmlHandle,linkTarget); + if(test != NULL){ + if(strcmp(test->value.element.name,name) == 0){ + return test; } } /* - test for named links - */ - linkName = mxmlElementGetAttr(linkNode, "name"); - if (test != NULL && linkName != NULL) { - if (strcmp(linkName, name) == 0) { - return test; + test for named links + */ + linkName = mxmlElementGetAttr(linkNode,"name"); + if(test != NULL && linkName != NULL){ + if(strcmp(linkName,name) == 0){ + return test; } } } return NULL; } - /*-----------------------------------------------------------------------*/ -NXstatus NXXopendata(NXhandle fid, CONSTCHAR * name) -{ +NXstatus NXXopendatatable (NXhandle fid, CONSTCHAR *name){ pXMLNexus xmlHandle = NULL; - mxml_node_t *dataNode = NULL; + mxml_node_t *dataNode = NULL, *dimsNode = NULL; char error[1024]; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { + + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ /* - silently fix this - */ + silently fix this + */ xmlHandle->stackPointer--; - if (xmlHandle->stackPointer < 0) { + if(xmlHandle->stackPointer < 0){ xmlHandle->stackPointer = 0; } } + + dimsNode = mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current, + xmlHandle->stack[xmlHandle->stackPointer].current, + DIMS_NODE_NAME, + NULL, + NULL, + MXML_DESCEND_FIRST); - dataNode = - mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current, - xmlHandle->stack[xmlHandle->stackPointer].current, - name, NULL, NULL, MXML_DESCEND_FIRST); - if (dataNode == NULL) { - dataNode = searchSDSLinks(xmlHandle, name); + if(!dimsNode){ + snprintf(error,1023,"Failed to open dataset %s",name); + NXReportError(error); + return NX_ERROR; } - if (!dataNode) { - snprintf(error, 1023, "Failed to open dataset %s", name); - NXIReportError(NXpData, error); + + dataNode = mxmlFindElement(dimsNode, + dimsNode, + name, + NULL, + NULL, + MXML_DESCEND_FIRST); + if(dataNode == NULL){ + dataNode = searchSDSLinks(xmlHandle,name); + } + if(!dataNode){ + snprintf(error,1023,"Failed to open dataset %s",name); + NXReportError(error); return NX_ERROR; } xmlHandle->stackPointer++; xmlHandle->stack[xmlHandle->stackPointer].current = dataNode; xmlHandle->stack[xmlHandle->stackPointer].currentChild = NULL; xmlHandle->stack[xmlHandle->stackPointer].currentAttribute = 0; + xmlHandle->stack[xmlHandle->stackPointer].options = XMLSTACK_OPTION_TABLE; return NX_OK; } -/*----------------------------------------------------------------------*/ -NXstatus NXXclosedata(NXhandle fid) -{ - pXMLNexus xmlHandle = NULL; - xmlHandle = (pXMLNexus) fid; +NXstatus NXXopendata (NXhandle fid, CONSTCHAR *name){ + pXMLNexus xmlHandle = NULL; + mxml_node_t *dataNode = NULL, *current = NULL; + char error[1024]; + + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - if (xmlHandle->stackPointer > 0) { + /* is this a table style node ? */ + current = xmlHandle->stack[xmlHandle->stackPointer].current; + dataNode = mxmlFindElement(current, + current, + DATA_NODE_NAME, + NULL, + NULL, + MXML_DESCEND_FIRST); + if (dataNode != NULL) + { + dataNode = mxmlFindElement(dataNode, + dataNode, + name, + NULL, + NULL, + MXML_DESCEND_FIRST); + } + if (dataNode != NULL) + { + return NXXopendatatable(fid, name); + } + + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + /* + silently fix this + */ + xmlHandle->stackPointer--; + if(xmlHandle->stackPointer < 0){ + xmlHandle->stackPointer = 0; + } + } + + dataNode = mxmlFindElement(xmlHandle->stack[xmlHandle->stackPointer].current, + xmlHandle->stack[xmlHandle->stackPointer].current, + name, + NULL, + NULL, + MXML_DESCEND_FIRST); + if(dataNode == NULL){ + dataNode = searchSDSLinks(xmlHandle,name); + } + if(!dataNode){ + snprintf(error,1023,"Failed to open dataset %s",name); + NXReportError(error); + return NX_ERROR; + } + xmlHandle->stackPointer++; + xmlHandle->stack[xmlHandle->stackPointer].current = dataNode; + xmlHandle->stack[xmlHandle->stackPointer].currentChild = NULL; + xmlHandle->stack[xmlHandle->stackPointer].currentAttribute = 0; + xmlHandle->stack[xmlHandle->stackPointer].options = 0; + return NX_OK; +} +/*----------------------------------------------------------------------*/ + +NXstatus NXXclosedata (NXhandle fid){ + pXMLNexus xmlHandle = NULL; + + xmlHandle = (pXMLNexus)fid; + assert(xmlHandle); + + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + if(xmlHandle->stackPointer > 0){ xmlHandle->stackPointer--; } return NX_OK; } return NX_OK; } - /*----------------------------------------------------------------------*/ -static mxml_node_t *findData(mxml_node_t * node) -{ +static mxml_node_t *findData(mxml_node_t *node){ mxml_node_t *baby = node; - - while ((baby = mxmlWalkNext(baby, node, MXML_DESCEND_FIRST)) != NULL) { - if (baby->type == MXML_OPAQUE || baby->type == MXML_CUSTOM) { + + while( (baby = mxmlWalkNext(baby,node,MXML_DESCEND_FIRST)) != NULL){ + if(baby->type == MXML_OPAQUE || baby->type == MXML_CUSTOM){ return baby; } } return NULL; } +/* we only havv to deal with non-character data here */ +NXstatus NXXputdatatable (NXhandle fid, const void *data){ + pXMLNexus xmlHandle = NULL; + mxml_node_t *userData = NULL; + mxml_node_t *current = NULL; + mxml_node_t *nodeRoot = NULL; + mxml_node_t *dataNodeRoot = NULL; + mxml_node_t *dataNode = NULL; + const char* name; + pNXDS dataset; + int i, offset, length; + xmlHandle = (pXMLNexus)fid; + assert(xmlHandle); + /* current points at the Idims node as done in NXXopendatatable */ + current = xmlHandle->stack[xmlHandle->stackPointer].current; + name = current->value.element.name; + /* we want to walk all Idata nodes and set name */ + nodeRoot = current->parent->parent; + dataNodeRoot = nodeRoot; + offset = 0; + for(i=0; dataNodeRoot != NULL; i++) + { + dataNodeRoot = mxmlFindElement(dataNodeRoot, nodeRoot, DATA_NODE_NAME, NULL, NULL, (i == 0 ? MXML_DESCEND_FIRST : MXML_NO_DESCEND) ); + if (dataNodeRoot != NULL) + { + dataNode = mxmlFindElement(dataNodeRoot,dataNodeRoot,name,NULL,NULL,MXML_DESCEND_FIRST); + if (dataNode != NULL) + { + userData = findData(dataNode); + assert(userData != NULL); + dataset = (pNXDS)userData->value.custom.data; + assert(dataset); + length = getNXDatasetByteLength(dataset); + memcpy(dataset->u.ptr,(char*)data + offset,length); + offset += length; + } + } + } + return NX_OK; +} + /*------------------------------------------------------------------------*/ -NXstatus NXXputdata(NXhandle fid, void *data) -{ +NXstatus NXXputdata (NXhandle fid, void *data){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; pNXDS dataset; - int i, length, type, rank, dim[NX_MAXRANK]; + int i, length, type, rank; + int64_t dim[NX_MAXRANK]; char *pPtr = NULL; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "No dataset open"); - return NX_ERROR; + if (xmlHandle->stack[xmlHandle->stackPointer].options & XMLSTACK_OPTION_TABLE) + { + return NXXputdatatable(fid,data); } + if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("No dataset open"); + return NX_ERROR; + } + current = xmlHandle->stack[xmlHandle->stackPointer].current; userData = findData(current); assert(userData != NULL); - if (userData->type == MXML_OPAQUE) { + if(userData->type == MXML_OPAQUE){ /* - Text data. We have to make sure that the text is \0 terminated. - Some language bindings do not ensure that this is the case. - */ - if (NXXgetinfo(fid, &rank, dim, &type) == NX_OK) { + Text data. We have to make sure that the text is \0 terminated. + Some language bindings do not ensure that this is the case. + */ + if(NXXgetinfo64(fid,&rank, dim, &type) == NX_OK){ length = 1; - for (i = 0; i < rank; i++) { - length *= dim[i]; + for(i=0; ivalue.custom.data; + dataset = (pNXDS)userData->value.custom.data; assert(dataset); length = getNXDatasetByteLength(dataset); - memcpy(dataset->u.ptr, data, length); + memcpy(dataset->u.ptr,data,length); } return NX_OK; } +NXstatus NXXgetdatatable (NXhandle fid, void *data){ + pXMLNexus xmlHandle = NULL; + mxml_node_t *userData = NULL; + mxml_node_t *current = NULL; + mxml_node_t *nodeRoot = NULL; + mxml_node_t *dataNodeRoot = NULL; + mxml_node_t *dataNode = NULL; + const char* name; + pNXDS dataset; + int i, offset, length; + xmlHandle = (pXMLNexus)fid; + assert(xmlHandle); + + /* current points at the Idims node as done in NXXopendatatable */ + current = xmlHandle->stack[xmlHandle->stackPointer].current; + name = current->value.element.name; + /* we want to walk all Idata nodes and set name */ + nodeRoot = current->parent->parent; + dataNodeRoot = nodeRoot; + offset = 0; + for(i=0; dataNodeRoot != NULL; i++) + { + dataNodeRoot = mxmlFindElement(dataNodeRoot, nodeRoot, DATA_NODE_NAME, NULL, NULL, (i == 0 ? MXML_DESCEND_FIRST : MXML_NO_DESCEND) ); + if (dataNodeRoot != NULL) + { + dataNode = mxmlFindElement(dataNodeRoot,dataNodeRoot,name,NULL,NULL,MXML_DESCEND_FIRST); + if (dataNode != NULL) + { + userData = findData(dataNode); + assert(userData != NULL); + dataset = (pNXDS)userData->value.custom.data; + assert(dataset); + length = getNXDatasetByteLength(dataset); + memcpy((char*)data + offset, dataset->u.ptr, length); + offset += length; + } + } + } + return NX_OK; +} + + /*------------------------------------------------------------------------*/ -NXstatus NXXgetdata(NXhandle fid, void *data) -{ +NXstatus NXXgetdata (NXhandle fid, void *data){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; pNXDS dataset; - int i, length, type, rank, dim[NX_MAXRANK]; + int i, length, type, rank; + int64_t dim[NX_MAXRANK]; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "No dataset open"); - return NX_ERROR; + if (xmlHandle->stack[xmlHandle->stackPointer].options & XMLSTACK_OPTION_TABLE) + { + return NXXgetdatatable(fid,data); } + if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("No dataset open"); + return NX_ERROR; + } + current = xmlHandle->stack[xmlHandle->stackPointer].current; userData = findData(current); assert(userData != NULL); - if (userData->type == MXML_OPAQUE) { + if(userData->type == MXML_OPAQUE){ /* - text data - */ - if (NXXgetinfo(fid, &rank, dim, &type) == NX_OK) { + text data + */ + if(NXXgetinfo64(fid,&rank, dim, &type) == NX_OK){ length = 1; - for (i = 0; i < rank; i++) { - length *= dim[i]; + for(i=0; ivalue.opaque, length); + strncpy((char *)data,userData->value.opaque,length); } else { - strcpy((char *) data, nxitrim(userData->value.opaque)); + strcpy((char *)data,nxitrim(userData->value.opaque)); } } else { - dataset = (pNXDS) userData->value.custom.data; + dataset = (pNXDS)userData->value.custom.data; assert(dataset); length = getNXDatasetByteLength(dataset); - memcpy(data, dataset->u.ptr, length); + memcpy(data,dataset->u.ptr,length); } return NX_OK; } - /*------------------------------------------------------------------------*/ -NXstatus NXXgetinfo(NXhandle fid, int *rank, int dimension[], int *iType) -{ +NXstatus NXXgetinfo64 (NXhandle fid, int *rank, + int64_t dimension[], int *iType){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; @@ -660,265 +945,271 @@ NXstatus NXXgetinfo(NXhandle fid, int *rank, int dimension[], int *iType) int myRank, i; const char *attr = NULL; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "No dataset open"); + if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("No dataset open"); return NX_ERROR; } - + current = xmlHandle->stack[xmlHandle->stackPointer].current; userData = findData(current); assert(userData != NULL); - if (userData->type == MXML_OPAQUE) { + if(userData->type == MXML_OPAQUE){ /* - text data - */ + text data + */ attr = mxmlElementGetAttr(current, TYPENAME); - if (attr == NULL) { + if(attr == NULL){ *rank = 1; *iType = NX_CHAR; - dimension[0] = strlen(userData->value.opaque); + dimension[0]= strlen(userData->value.opaque); } else { - analyzeDim(attr, rank, dimension, iType); - *iType = NX_CHAR; + *iType = translateTypeCode(attr); + analyzeDim(attr,rank,dimension,iType); + if (dimension[0] == -1) /* 1D strings are NX_CHAR not NX_CHAR[] so length will not be correct */ + { + dimension[0] = strlen(userData->value.opaque); + } + } - } else { - dataset = (pNXDS) userData->value.custom.data; + } else { + dataset = (pNXDS)userData->value.custom.data; assert(dataset); myRank = getNXDatasetRank(dataset); *rank = myRank; *iType = getNXDatasetType(dataset); - for (i = 0; i < myRank; i++) { - dimension[i] = getNXDatasetDim(dataset, i); + for(i = 0; i < myRank; i++){ + dimension[i] = getNXDatasetDim(dataset,i); } } return NX_OK; } - /*--------------------------------------------------------------------- clone the dataset and set the data pointer. This in order to use the addressing and type conversion implemented in nxdataset ----------------------------------------------------------------------*/ -static pNXDS makeSlabData(pNXDS dataset, void *data, int size[]) -{ +---------------------------------------------------------------------*/ +static pNXDS makeSlabData(pNXDS dataset, const void *data, const int64_t size[]){ pNXDS slabData = NULL; int rank, i; - - slabData = (pNXDS) malloc(sizeof(NXDS)); - if (slabData == NULL) { + + slabData = (pNXDS)malloc(sizeof(NXDS)); + if(slabData == NULL){ return NULL; } rank = getNXDatasetRank(dataset); slabData->rank = rank; - slabData->dim = (int *) malloc(rank * sizeof(int)); - for (i = 0; i < rank; i++) { + slabData->dim = (int64_t *)malloc(rank*sizeof(int64_t)); + for(i = 0; i < rank; i++){ slabData->dim[i] = size[i]; } slabData->type = getNXDatasetType(dataset); - slabData->u.ptr = data; + slabData->u.ptr = (void*)data; slabData->magic = dataset->magic; return slabData; -} - +} /*-------------------------------------------------------------------- This goes by recursion ----------------------------------------------------------------------*/ static void putSlabData(pNXDS dataset, pNXDS slabData, int dim, - int start[], int sourcePos[], int targetPos[]) -{ - int i, rank, length; + const int64_t start[], + int64_t sourcePos[], int64_t targetPos[]){ + int64_t i, rank, length; rank = getNXDatasetRank(slabData); - length = getNXDatasetDim(slabData, dim); - if (dim != rank - 1) { - for (i = 0; i < length; i++) { - targetPos[dim] = start[dim] + i; + length = getNXDatasetDim(slabData,dim); + if(dim != rank-1){ + for(i = 0; i < length; i++){ + targetPos[dim] = start[dim] +i; sourcePos[dim] = i; - putSlabData(dataset, slabData, dim + 1, start, sourcePos, targetPos); + putSlabData(dataset,slabData, dim+1,start, + sourcePos,targetPos); } } else { - for (i = 0; i < length; i++) { - targetPos[dim] = start[dim] + i; + for(i = 0; i < length; i++){ + targetPos[dim] = start[dim] +i; sourcePos[dim] = i; - putNXDatasetValue(dataset, targetPos, - getNXDatasetValue(slabData, sourcePos)); + putNXDatasetValue(dataset,targetPos, + getNXDatasetValue(slabData,sourcePos)); } } } - /*---------------------------------------------------------------------- This is in order to support unlimited dimensions along the first axis -----------------------------------------------------------------------*/ -static int checkAndExtendDataset(mxml_node_t * node, pNXDS dataset, - int start[], int size[]) -{ - int dim0, byteLength; +static int checkAndExtendDataset(mxml_node_t *node, pNXDS dataset, + const int64_t start[], const int64_t size[]){ + int64_t dim0, byteLength; void *oldData = NULL; char *typestring = NULL; dim0 = start[0] + size[0]; - if (dim0 > dataset->dim[0]) { + if(dim0 > dataset->dim[0]){ byteLength = getNXDatasetByteLength(dataset); oldData = dataset->u.ptr; dataset->dim[0] = dim0; dataset->u.ptr = malloc(getNXDatasetByteLength(dataset)); - if (dataset->u.ptr == NULL) { + if(dataset->u.ptr == NULL){ return 0; } - memset(dataset->u.ptr, 0, getNXDatasetByteLength(dataset)); - memcpy(dataset->u.ptr, oldData, byteLength); + memset(dataset->u.ptr,0,getNXDatasetByteLength(dataset)); + memcpy(dataset->u.ptr,oldData,byteLength); free(oldData); - typestring = - buildTypeString(dataset->type, dataset->rank, dataset->dim); - if (typestring != NULL) { - mxmlElementSetAttr(node, TYPENAME, typestring); + typestring = buildTypeString(dataset->type,dataset->rank,dataset->dim); + if(typestring != NULL){ + mxmlElementSetAttr(node,TYPENAME,typestring); free(typestring); } else { - NXIReportError(NXpData, "Failed to allocate typestring"); + NXReportError("Failed to allocate typestring"); return 0; } } return 1; } +NXstatus NXXputslabtable (NXhandle fid, const void *data, + const int64_t iStart[], const int64_t iSize[]){ + return NX_OK; +} /*----------------------------------------------------------------------*/ -NXstatus NXXputslab(NXhandle fid, void *data, int iStart[], int iSize[]) -{ - +NXstatus NXXputslab64 (NXhandle fid, void *data, + int64_t iStart[], int64_t iSize[]){ + pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; pNXDS dataset, slabData; - int sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK], status; + int64_t sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK]; + int status; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "No dataset open"); - return NX_ERROR; + if (xmlHandle->stack[xmlHandle->stackPointer].options & XMLSTACK_OPTION_TABLE) + { + return NXXputslabtable(fid,data,iStart,iSize); } + if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("No dataset open"); + return NX_ERROR; + } + current = xmlHandle->stack[xmlHandle->stackPointer].current; userData = findData(current); assert(userData != NULL); - if (userData->type == MXML_OPAQUE) { - NXIReportError(NXpData, - "This API does not support slabs on text data"); + if(userData->type == MXML_OPAQUE){ + NXReportError("This API does not support slabs on text data"); return NX_ERROR; } - dataset = (pNXDS) userData->value.custom.data; + dataset = (pNXDS)userData->value.custom.data; assert(dataset); - status = checkAndExtendDataset(current, dataset, iStart, iSize); - if (status == 0) { - NXIReportError(NXpData, "Out of memory extending dataset"); + status = checkAndExtendDataset(current,dataset,iStart,iSize); + if(status == 0){ + NXReportError("Out of memory extending dataset"); return NX_ERROR; } slabData = makeSlabData(dataset, data, iSize); - if (slabData == NULL) { - NXIReportError(NXpData, "Failed to allocate slab data"); + if(slabData == NULL){ + NXReportError("Failed to allocate slab data"); return NX_ERROR; } + - - putSlabData(dataset, slabData, 0, iStart, sourcePos, targetPos); + putSlabData(dataset,slabData,0,iStart,sourcePos,targetPos); free(slabData->dim); free(slabData); - + return NX_OK; } - /*-------------------------------------------------------------------- This goes by recursion ----------------------------------------------------------------------*/ static void getSlabData(pNXDS dataset, pNXDS slabData, int dim, - int start[], int sourcePos[], int targetPos[]) -{ - int i, rank, length; + const int64_t start[], + int64_t sourcePos[],int64_t targetPos[]){ + int64_t i, rank, length; rank = getNXDatasetRank(slabData); - length = getNXDatasetDim(slabData, dim); - if (dim != rank - 1) { - for (i = 0; i < length; i++) { - sourcePos[dim] = start[dim] + i; + length = getNXDatasetDim(slabData,dim); + if(dim != rank-1){ + for(i = 0; i < length; i++){ + sourcePos[dim] = start[dim] +i; targetPos[dim] = i; - getSlabData(dataset, slabData, dim + 1, start, sourcePos, targetPos); + getSlabData(dataset,slabData, dim+1,start, + sourcePos,targetPos); } } else { - for (i = 0; i < length; i++) { - sourcePos[dim] = start[dim] + i; + for(i = 0; i < length; i++){ + sourcePos[dim] = start[dim] +i; targetPos[dim] = i; - putNXDatasetValue(slabData, targetPos, - getNXDatasetValue(dataset, sourcePos)); + putNXDatasetValue(slabData,targetPos, + getNXDatasetValue(dataset,sourcePos)); } } } - /*----------------------------------------------------------------------*/ -NXstatus NXXgetslab(NXhandle fid, void *data, int iStart[], int iSize[]) -{ +NXstatus NXXgetslab64 (NXhandle fid, void *data, + const int64_t iStart[], const int64_t iSize[]){ pXMLNexus xmlHandle = NULL; mxml_node_t *userData = NULL; mxml_node_t *current = NULL; pNXDS dataset, slabData; - int sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK]; + int64_t sourcePos[NX_MAXRANK], targetPos[NX_MAXRANK]; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "No dataset open"); + if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("No dataset open"); return NX_ERROR; } - + current = xmlHandle->stack[xmlHandle->stackPointer].current; userData = findData(current); assert(userData != NULL); - if (userData->type == MXML_OPAQUE) { - NXIReportError(NXpData, - "This API does not support slabs on text data"); + if(userData->type == MXML_OPAQUE){ + NXReportError("This API does not support slabs on text data"); return NX_ERROR; } - dataset = (pNXDS) userData->value.custom.data; + dataset = (pNXDS)userData->value.custom.data; assert(dataset); slabData = makeSlabData(dataset, data, iSize); - if (slabData == NULL) { - NXIReportError(NXpData, "Failed to allocate slab data"); + if(slabData == NULL){ + NXReportError("Failed to allocate slab data"); return NX_ERROR; } - getSlabData(dataset, slabData, 0, iStart, sourcePos, targetPos); + getSlabData(dataset,slabData,0,iStart,sourcePos,targetPos); free(slabData->dim); free(slabData); - + return NX_OK; } - /*----------------------------------------------------------------------*/ -static NXstatus NXXsetnumberformat(NXhandle fid, int type, char *format) -{ +static NXstatus NXXsetnumberformat(NXhandle fid, + int type, char *format){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL; mxml_node_t *userData = NULL; pNXDS dataset; - - xmlHandle = (pXMLNexus) fid; + + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ current = xmlHandle->stack[xmlHandle->stackPointer].current; userData = findData(current); assert(userData != NULL); - if (userData->type == MXML_OPAQUE) { + if(userData->type == MXML_OPAQUE){ return NX_OK; } - dataset = (pNXDS) userData->value.custom.data; + dataset = (pNXDS)userData->value.custom.data; assert(dataset); - if (dataset->format != NULL) { + if(dataset->format != NULL){ free(dataset->format); } dataset->format = strdup(format); @@ -927,10 +1218,8 @@ static NXstatus NXXsetnumberformat(NXhandle fid, int type, char *format) } return NX_OK; } - /*============================ Attributes ============================*/ -static char *formatAttributeData(void *data, int datalen, int iType) -{ +static char *formatAttributeData(const void *data, int datalen, int iType){ int intData = 0; long iValue = -99999; double dValue = -1e38; @@ -938,187 +1227,191 @@ static char *formatAttributeData(void *data, int datalen, int iType) char *number; - if (iType == NX_CHAR) { + if(iType == NX_CHAR){ /* data may not be NULL terminated */ - number = (char *) malloc((datalen + 1) * sizeof(char)); + number = (char*)malloc((datalen+1) * sizeof(char)); memcpy(number, data, datalen * sizeof(char)); number[datalen] = '\0'; return number; } - number = (char *) malloc(132 * sizeof(char)); - if (!number) { - NXIReportError(NXpData, "Failed to allocate attribute number buffer"); + number = (char *)malloc(132*sizeof(char)); + if(!number){ + NXReportError("Failed to allocate attribute number buffer"); return NULL; } - - if (datalen > 1) { + + if(datalen > 1){ return NULL; } type[0] = '\0'; - switch (iType) { + switch(iType){ case NX_INT32: - iValue = ((int *) data)[0]; + iValue = ((int *)data)[0]; intData = 1; - strcpy(type, "NX_INT32:"); + strcpy(type,"NX_INT32:"); break; case NX_UINT32: - iValue = ((unsigned int *) data)[0]; + iValue = ((unsigned int *)data)[0]; intData = 1; - strcpy(type, "NX_UINT32:"); + strcpy(type,"NX_UINT32:"); break; case NX_INT16: - iValue = ((short *) data)[0]; + iValue = ((short *)data)[0]; intData = 1; - strcpy(type, "NX_INT16:"); + strcpy(type,"NX_INT16:"); break; case NX_UINT16: - iValue = ((unsigned short *) data)[0]; + iValue = ((unsigned short *)data)[0]; intData = 1; - strcpy(type, "NX_UINT16:"); + strcpy(type,"NX_UINT16:"); break; case NX_INT8: - iValue = (int) ((char *) data)[0]; + iValue = (int)((char *)data)[0]; intData = 1; - strcpy(type, "NX_INT8:"); + strcpy(type,"NX_INT8:"); break; case NX_UINT8: intData = 1; - iValue = (int) ((unsigned char *) data)[0]; - strcpy(type, "NX_UINT8:"); + iValue = (int)((unsigned char *)data)[0]; + strcpy(type,"NX_UINT8:"); break; case NX_FLOAT32: - dValue = ((float *) data)[0]; - strcpy(type, "NX_FLOAT32:"); + dValue = ((float *)data)[0]; + strcpy(type,"NX_FLOAT32:"); intData = 0; break; case NX_FLOAT64: - dValue = ((double *) data)[0]; - strcpy(type, "NX_FLOAT64:"); + dValue = ((double *)data)[0]; + strcpy(type,"NX_FLOAT64:"); intData = 0; break; } - if (intData) { - snprintf(number, 79, "%s%ld", type, iValue); + if(intData){ + snprintf(number,79,"%s%ld",type,iValue); } else { - snprintf(number, 79, "%s%f", type, dValue); + snprintf(number,79,"%s%f",type,dValue); } return number; } - /*---------------------------------------------------------------------*/ -NXstatus NXXputattr(NXhandle fid, CONSTCHAR * name, void *data, - int datalen, int iType) -{ +NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, void *data, + int datalen, int iType){ + char buffer[256]; pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL; char *numberData = NULL; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + if (!validNXName(name, 1)) + { + sprintf(buffer, "ERROR: invalid characters in attribute name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } current = xmlHandle->stack[xmlHandle->stackPointer].current; - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - if (strcmp(name, TYPENAME) == 0) { - NXIReportError(NXpData, - "type is a reserved attribute name, rejected"); - return NX_ERROR; + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + if(strcmp(name,TYPENAME) == 0){ + NXReportError("type is a reserved attribute name, rejected"); + return NX_ERROR; } } - numberData = formatAttributeData(data, datalen, iType); - if (numberData == NULL) { - NXIReportError(NXpData, "This API does not support non number arrays"); + numberData = formatAttributeData(data,datalen,iType); + if(numberData == NULL){ + NXReportError("This API does not support non number arrays"); return NX_ERROR; } else { - mxmlElementSetAttr(current, name, numberData); + mxmlElementSetAttr(current,name,numberData); free(numberData); } return NX_OK; } - /*--------------------------------------------------------------------------*/ -NXstatus NXXgetattr(NXhandle fid, char *name, - void *data, int *datalen, int *iType) -{ +NXstatus NXXgetattr (NXhandle fid, char *name, + void *data, int* datalen, int* iType){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL; const char *attribute = NULL; char error[1024]; - char *attData = NULL; - int iValue, nx_type; - float fValue; + const char *attData = NULL; + int nx_type; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); current = xmlHandle->stack[xmlHandle->stackPointer].current; - attribute = mxmlElementGetAttr(current, name); - if (!attribute) { - snprintf(error, 1023, "Attribute %s not found", name); - NXIReportError(NXpData, error); + attribute = mxmlElementGetAttr(current,name); + if(!attribute){ + snprintf(error,1023,"Attribute %s not found", name); + NXReportError(error); return NX_ERROR; } - nx_type = translateTypeCode((char *) attribute); - if (nx_type < 0) { + nx_type = translateTypeCode((char *)attribute); + if(nx_type < 0) { /* - no type code == text attribute - */ + no type code == text attribute + */ nx_type = NX_CHAR; } else { /* - We need to find the number after the type code. However, there is - the complication of the datatype type attribute ... - */ - if (strcmp(name, TYPENAME) == 0) { + We need to find the number after the type code. However, there is + the complication of the datatype type attribute ... + */ + if(strcmp(name,TYPENAME) == 0){ nx_type = NX_CHAR; } else { - attData = strchr(attribute, (int) ':'); - if (attData == NULL) { - NXIReportError(NXpData, "ERROR: bad attribute string, : missing"); - return NX_ERROR; + attData = strchr(attribute,(int)':'); + if(attData == NULL){ + NXReportError("ERROR: bad attribute string, : missing"); + return NX_ERROR; } attData++; } } *iType = nx_type; - switch (nx_type) { + switch(nx_type){ case NX_CHAR: - strncpy((char *) data, attribute, *datalen); - *datalen = strlen(attribute); + /* enforce NULL termination regardless of length of datalen */ + strncpy((char *)data, attribute, *datalen-1); + ((char*)data)[*datalen-1] = '\0'; + /* *datalen = strlen(attribute); */ + *datalen = strlen((char*)data); *iType = NX_CHAR; break; case NX_INT32: - ((int *) data)[0] = atoi(attData); + ((int *)data)[0] = atoi(attData); *datalen = 1; break; case NX_UINT32: - ((unsigned int *) data)[0] = atoi(attData); + ((unsigned int *)data)[0] = atoi(attData); *datalen = 1; break; case NX_INT16: - ((short *) data)[0] = atoi(attData); + ((short *)data)[0] = atoi(attData); *datalen = 1; break; case NX_UINT16: - ((unsigned short *) data)[0] = atoi(attData); + ((unsigned short *)data)[0] = atoi(attData); *datalen = 1; break; case NX_INT8: - ((char *) data)[0] = atoi(attData); + ((char *)data)[0] = atoi(attData); *datalen = 1; break; case NX_UINT8: - ((unsigned char *) data)[0] = atoi(attData); + ((unsigned char *)data)[0] = atoi(attData); *datalen = 1; break; case NX_FLOAT32: - ((float *) data)[0] = atof(attData); + ((float *)data)[0] = atof(attData); *datalen = 1; break; case NX_FLOAT64: - ((double *) data)[0] = atof(attData); + ((double *)data)[0] = atof(attData); *datalen = 1; break; } @@ -1126,102 +1419,158 @@ NXstatus NXXgetattr(NXhandle fid, char *name, return NX_OK; } -/*====================== search functions =================================*/ -NXstatus NXXgetnextentry(NXhandle fid, NXname name, - NXname nxclass, int *datatype) +/* find the next node, ignoring Idata */ +static mxml_node_t* find_node(mxml_node_t* node, int next) { + int done = 0; + mxml_node_t* parent_next = NULL; /* parent to use if we are in an Idims search */ + if (node == NULL) + { + return NULL; + } + if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DIMS_NODE_NAME) ) + { + parent_next = node->parent->next; + } + else + { + parent_next = NULL; + } + if (next) + { + if (node->next != NULL) + { + node = node->next; + } + else + { + node = parent_next; + } + } + while(node != NULL && !done) + { + if ( (node->parent != NULL) && !strcmp(node->parent->value.element.name, DIMS_NODE_NAME) ) + { + parent_next = node->parent->next; + } + else + { + parent_next = NULL; + } + if ( (node->type != MXML_ELEMENT) || !strcmp(node->value.element.name, DATA_NODE_NAME) ) + { + if (node->next != NULL) + { + node = node->next; + } + else + { + node = parent_next; + } + continue; + } + if (!strcmp(node->value.element.name, DIMS_NODE_NAME)) + { + node = node->child; + continue; + } + done = 1; + } + return node; +} + +/*====================== search functions =================================*/ +NXstatus NXXgetnextentry (NXhandle fid,NXname name, + NXname nxclass, int *datatype){ pXMLNexus xmlHandle = NULL; - mxml_node_t *next = NULL, *userData; + mxml_node_t *next = NULL, *userData, *node = NULL; int stackPtr; const char *target = NULL, *attname = NULL; pNXDS dataset; char pBueffel[256]; const char *linkName = NULL; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ /* - be nice to user: silently fix this problem - */ + be nice to user: silently fix this problem + */ NXXclosedata(fid); } stackPtr = xmlHandle->stackPointer; - if (xmlHandle->stack[stackPtr].currentChild == NULL) { + if(xmlHandle->stack[stackPtr].currentChild == NULL){ /* - initialization of search - */ - xmlHandle->stack[stackPtr].currentChild = - xmlHandle->stack[stackPtr].current->child; + initialization of search + */ + node = find_node(xmlHandle->stack[stackPtr].current->child, 0); } else { /* - proceed - */ - xmlHandle->stack[stackPtr].currentChild = - xmlHandle->stack[stackPtr].currentChild->next; + proceed + */ + node = find_node(xmlHandle->stack[stackPtr].currentChild, 1); } - next = xmlHandle->stack[stackPtr].currentChild; - if (next == NULL) { + xmlHandle->stack[stackPtr].currentChild = node; + next = node; + if(next == NULL){ return NX_EOD; } - if (strcmp(next->value.element.name, "NAPIlink") == 0) { - target = mxmlElementGetAttr(next, "target"); - linkName = mxmlElementGetAttr(next, "name"); - if (target == NULL) { - NXIReportError(NXpData, "Corrupted file, NAPIlink without target"); + if(strcmp(next->value.element.name,"NAPIlink") == 0){ + target = mxmlElementGetAttr(next,"target"); + linkName = mxmlElementGetAttr(next,"name"); + if(target == NULL){ + NXReportError("Corrupted file, NAPIlink without target"); return NX_ERROR; } - next = getLinkTarget(xmlHandle, target); - if (next == NULL) { - NXIReportError(NXpData, "Corrupted file, broken link"); + next = getLinkTarget(xmlHandle,target); + if(next == NULL){ + NXReportError("Corrupted file, broken link"); return NX_ERROR; } } - if (isDataNode(next)) { - strcpy(name, next->value.element.name); - strcpy(nxclass, "SDS"); + if(isDataNode(next)){ + strcpy(name,next->value.element.name); + strcpy(nxclass,"SDS"); userData = findData(next); - if (userData == NULL) { - snprintf(pBueffel, 255, "Corrupted file, userData for %s not found", - name); - NXIReportError(NXpData, pBueffel); + if(userData == NULL){ + snprintf(pBueffel,255,"Corrupted file, userData for %s not found", + name); + NXReportError(pBueffel); return NX_ERROR; } - if (userData->type == MXML_OPAQUE) { + if(userData->type == MXML_OPAQUE){ *datatype = NX_CHAR; } else { - dataset = (pNXDS) userData->value.custom.data; + dataset = (pNXDS)userData->value.custom.data; assert(dataset); *datatype = getNXDatasetType(dataset); } } else { - strcpy(nxclass, next->value.element.name); - attname = mxmlElementGetAttr(next, "name"); - strcpy(name, attname); + strcpy(nxclass,next->value.element.name); + attname = mxmlElementGetAttr(next,"name"); + strcpy(name,attname); } /* - this is for named links - */ - if (linkName != NULL) { - strcpy(name, linkName); + this is for named links + */ + if(linkName != NULL){ + strcpy(name,linkName); } return NX_OK; } - /*----------------------------------------------------------------------*/ -extern NXstatus NXXinitgroupdir(NXhandle fid) -{ +extern NXstatus NXXinitgroupdir(NXhandle fid){ pXMLNexus xmlHandle = NULL; int stackPtr; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "Cannot search datasets"); + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("Cannot search datasets"); return NX_ERROR; } @@ -1229,53 +1578,52 @@ extern NXstatus NXXinitgroupdir(NXhandle fid) xmlHandle->stack[stackPtr].currentChild = NULL; return NX_OK; } - /*-------------------------------------------------------------------------*/ -NXstatus NXXgetnextattr(NXhandle fid, NXname pName, - int *iLength, int *iType) -{ +NXstatus NXXgetnextattr (NXhandle fid, NXname pName, + int *iLength, int *iType){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL; int stackPtr, currentAtt, nx_type; - char *attVal; + char *attVal; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); stackPtr = xmlHandle->stackPointer; current = xmlHandle->stack[stackPtr].current; currentAtt = xmlHandle->stack[stackPtr].currentAttribute; - if (currentAtt >= current->value.element.num_attrs) { + if(currentAtt >= + current->value.element.num_attrs ){ xmlHandle->stack[stackPtr].currentAttribute = 0; return NX_EOD; } /* - hide group name attribute - */ - if (strcmp(current->value.element.attrs[currentAtt].name, "name") == 0 - && !isDataNode(current)) { + hide group name attribute + */ + if(strcmp(current->value.element.attrs[currentAtt].name,"name") == 0 + && !isDataNode(current) ){ xmlHandle->stack[stackPtr].currentAttribute++; - return NXXgetnextattr(fid, pName, iLength, iType); + return NXXgetnextattr(fid,pName,iLength,iType); } /* - hide type attribute - */ - if (strcmp(current->value.element.attrs[currentAtt].name, TYPENAME) == 0 - && isDataNode(current)) { + hide type attribute + */ + if(strcmp(current->value.element.attrs[currentAtt].name,TYPENAME) == 0 + && isDataNode(current)){ xmlHandle->stack[stackPtr].currentAttribute++; - return NXXgetnextattr(fid, pName, iLength, iType); + return NXXgetnextattr(fid,pName,iLength,iType); } - strcpy(pName, current->value.element.attrs[currentAtt].name); + strcpy(pName,current->value.element.attrs[currentAtt].name); attVal = current->value.element.attrs[currentAtt].value; - nx_type = translateTypeCode((char *) attVal); - if (nx_type < 0 || strcmp(pName, TYPENAME) == 0) { + nx_type = translateTypeCode((char *)attVal); + if(nx_type < 0 || strcmp(pName,TYPENAME) == 0){ /* - no type == NX_CHAR - */ + no type == NX_CHAR + */ *iLength = strlen(attVal); *iType = NX_CHAR; } else { @@ -1286,64 +1634,82 @@ NXstatus NXXgetnextattr(NXhandle fid, NXname pName, xmlHandle->stack[stackPtr].currentAttribute++; return NX_OK; } - /*-------------------------------------------------------------------------*/ -extern NXstatus NXXinitattrdir(NXhandle fid) -{ +extern NXstatus NXXinitattrdir(NXhandle fid){ pXMLNexus xmlHandle = NULL; int stackPtr; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); stackPtr = xmlHandle->stackPointer; xmlHandle->stack[stackPtr].currentAttribute = 0; return NX_OK; } - /*-------------------------------------------------------------------------*/ -NXstatus NXXgetgroupinfo(NXhandle fid, int *iN, - NXname pName, NXname pClass) -{ +NXstatus NXXgetgroupinfo (NXhandle fid, int *iN, + NXname pName, NXname pClass){ pXMLNexus xmlHandle = NULL; - mxml_node_t *child = NULL; + mxml_node_t *node = NULL, *child = NULL; mxml_node_t *current = NULL; const char *nameAtt = NULL; int childCount; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "No group open"); + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("No group open"); return NX_ERROR; - } + } current = xmlHandle->stack[xmlHandle->stackPointer].current; - nameAtt = mxmlElementGetAttr(current, "name"); - if (nameAtt != NULL) { - strcpy(pName, nameAtt); + nameAtt = mxmlElementGetAttr(current,"name"); + if(nameAtt != NULL){ + strcpy(pName,nameAtt); } - strcpy(pClass, current->value.element.name); + strcpy(pClass,current->value.element.name); +/* count all child nodes, but need to ignore DATA_NODE_NAME and + * descend into DIMS_NODE_NAME + */ childCount = 0; - child = current->child; - while (child != NULL) { - childCount++; - child = child->next; + node = current->child; + while(node != NULL) + { + if (!strcmp(node->value.element.name, DATA_NODE_NAME)) + { + ; /* names also exist in DIMS_NODE_NAME so do nothing here */ + } + else if (!strcmp(node->value.element.name, DIMS_NODE_NAME)) + { + child = node->child; + while(child != NULL) + { + /* not sure why this check is needed, but you double count otherwise */ + if (child->type == MXML_ELEMENT) + { + childCount++; + } + child = child->next; + } + } + else + { + childCount++; + } + node = node->next; } *iN = childCount; return NX_OK; } - /*----------------------------------------------------------------------*/ -NXstatus NXXgetattrinfo(NXhandle fid, int *iN) -{ +NXstatus NXXgetattrinfo (NXhandle fid, int *iN){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL; - int stackPtr, currentAtt; + int stackPtr, skip; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); stackPtr = xmlHandle->stackPointer; @@ -1351,33 +1717,31 @@ NXstatus NXXgetattrinfo(NXhandle fid, int *iN) current = xmlHandle->stack[stackPtr].current; /* - hide type and group name attributes - */ - if (!isDataNode(current)) { - *iN = current->value.element.num_attrs - 1; - return NX_OK; - } - if (mxmlElementGetAttr(current, TYPENAME) != NULL) { - *iN = current->value.element.num_attrs - 1; + hide type and group name attributes + */ + skip=0; + if(isDataNode(current)) { + /* data nodes may have type */ + if(mxmlElementGetAttr(current,TYPENAME) != NULL) skip=1; } else { - *iN = current->value.element.num_attrs; + /* group nodes (except root) have name */ + if(mxmlElementGetAttr(current,"name") != NULL) skip=1; } + *iN = current->value.element.num_attrs - skip; return NX_OK; } - /*================= Linking functions =================================*/ -static int countPathChars(mxml_node_t * path[], int stackPtr) -{ +static int countPathChars(mxml_node_t *path[], int stackPtr){ int count = 1; const char *name = NULL; - while (stackPtr >= 0) { - if (isDataNode(path[stackPtr])) { + while(stackPtr >= 0) { + if(isDataNode(path[stackPtr])){ count += strlen(path[stackPtr]->value.element.name); } else { - name = mxmlElementGetAttr(path[stackPtr], "name"); - if (name != NULL) { - count += strlen(name); + name = mxmlElementGetAttr(path[stackPtr],"name"); + if(name != NULL){ + count += strlen(name); } } stackPtr--; @@ -1385,60 +1749,55 @@ static int countPathChars(mxml_node_t * path[], int stackPtr) } return count; } - /*-------------------------------------------------------------------*/ -static char *buildPathString(mxml_node_t * path[], int stackPtr) -{ +static char *buildPathString(mxml_node_t *path[], int stackPtr){ int count = 0; const char *name = NULL; char *pathString = NULL; - count = countPathChars(path, stackPtr); - pathString = (char *) malloc((count + 10) * sizeof(char)); - if (pathString == NULL) { + count = countPathChars(path,stackPtr); + pathString = (char *)malloc((count+10)*sizeof(char)); + if(pathString == NULL){ return NULL; } - memset(pathString, 0, (count + 10) * sizeof(char)); + memset(pathString,0,(count+10)*sizeof(char)); - while (stackPtr >= 0) { - if (isDataNode(path[stackPtr])) { - strcat(pathString, "/"); - strcat(pathString, path[stackPtr]->value.element.name); + while(stackPtr >= 0) { + if(isDataNode(path[stackPtr])){ + strcat(pathString,"/"); + strcat(pathString,path[stackPtr]->value.element.name); } else { - name = mxmlElementGetAttr(path[stackPtr], "name"); - if (name != NULL) { - strcat(pathString, "/"); - strcat(pathString, name); + name = mxmlElementGetAttr(path[stackPtr],"name"); + if(name != NULL){ + strcat(pathString,"/"); + strcat(pathString,name); } } stackPtr--; } return pathString; } - /*--------------------------------------------------------------------*/ -static char *findLinkPath(mxml_node_t * node) -{ +static char *findLinkPath(mxml_node_t *node){ mxml_node_t **path = NULL; int stackPtr; mxml_node_t *current = NULL; - char *pathString = NULL, *result = NULL; - int count; + char *result = NULL; - path = (mxml_node_t **) malloc(NXMAXSTACK * sizeof(mxml_node_t *)); - if (path == NULL) { - NXIReportError(NXpData, "ERROR: out of memory follwoing link path"); + path = (mxml_node_t **)malloc(NXMAXSTACK*sizeof(mxml_node_t *)); + if(path == NULL){ + NXReportError("ERROR: out of memory following link path"); return NULL; } - memset(path, 0, NXMAXSTACK * sizeof(mxml_node_t *)); + memset(path,0,NXMAXSTACK*sizeof(mxml_node_t *)); /* - first path: walk up the tree untill NXroot is found - */ + first path: walk up the tree untill NXroot is found + */ current = node; stackPtr = 0; - while (current != NULL && - strcmp(current->value.element.name, "NXroot") != 0) { + while(current != NULL && + strcmp(current->value.element.name,"NXroot") != 0){ path[stackPtr] = current; stackPtr++; current = current->parent; @@ -1446,185 +1805,188 @@ static char *findLinkPath(mxml_node_t * node) stackPtr--; /* - path now contains the nodes to the root node in reverse order. - From this build the path string - */ - result = buildPathString(path, stackPtr); + path now contains the nodes to the root node in reverse order. + From this build the path string + */ + result = buildPathString(path,stackPtr); free(path); return result; } - /*--------------------------------------------------------------------*/ -NXstatus NXXgetdataID(NXhandle fid, NXlink * sRes) -{ +NXstatus NXXgetdataID (NXhandle fid, NXlink* sRes){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL; char *linkPath = NULL; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { + if(!isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ return NX_ERROR; - } + } current = xmlHandle->stack[xmlHandle->stackPointer].current; - + linkPath = findLinkPath(current); - if (!linkPath) { - NXIReportError(NXpData, "Failed to allocate link path string"); + if(!linkPath){ + NXReportError("Failed to allocate link path string"); return NX_ERROR; } - strncpy(sRes->targetPath, linkPath, 1023); + strncpy(sRes->targetPath,linkPath,1023); free(linkPath); return NX_OK; } - /*--------------------------------------------------------------------*/ -NXstatus NXXgetgroupID(NXhandle fid, NXlink * sRes) -{ +NXstatus NXXgetgroupID (NXhandle fid, NXlink* sRes){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL; char *linkPath = NULL; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "No group open"); + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("No group open"); return NX_ERROR; - } + } current = xmlHandle->stack[xmlHandle->stackPointer].current; - if (xmlHandle->stackPointer == 0) { + if(xmlHandle->stackPointer == 0){ return NX_ERROR; } linkPath = findLinkPath(current); - if (!linkPath) { - NXIReportError(NXpData, "Failed to allocate link path string"); + if(!linkPath){ + NXReportError("Failed to allocate link path string"); return NX_ERROR; } - strncpy(sRes->targetPath, linkPath, 1023); + strncpy(sRes->targetPath,linkPath,1023); free(linkPath); return NX_OK; } /*-----------------------------------------------------------------------*/ -NXstatus NXXprintlink(NXhandle fid, NXlink * sLink) -{ - pXMLNexus xmlHandle = NULL; - xmlHandle = (pXMLNexus) fid; - assert(xmlHandle); - - printf("XML link: target=\"%s\"\n", sLink->targetPath); - return NX_OK; -} + NXstatus NXXprintlink (NXhandle fid, NXlink* sLink) + { + pXMLNexus xmlHandle = NULL; + xmlHandle = (pXMLNexus)fid; + assert(xmlHandle); + printf("XML link: target=\"%s\"\n", sLink->targetPath); + return NX_OK; + } + /*-----------------------------------------------------------------------*/ -NXstatus NXXmakelink(NXhandle fid, NXlink * sLink) -{ +NXstatus NXXmakelink (NXhandle fid, NXlink* sLink){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL, *linkNode = NULL; mxml_node_t *linkedNode = NULL; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "No group to link to open"); + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("No group to link to open"); return NX_ERROR; - } + } current = xmlHandle->stack[xmlHandle->stackPointer].current; - linkNode = mxmlNewElement(current, "NAPIlink"); - if (!linkNode) { - NXIReportError(NXpData, "Failed to allocate new link element"); + linkNode = mxmlNewElement(current,"NAPIlink"); + if(!linkNode){ + NXReportError("Failed to allocate new link element"); return NX_ERROR; } - mxmlElementSetAttr(linkNode, "target", sLink->targetPath); - linkedNode = getLinkTarget(xmlHandle, sLink->targetPath); - if (linkedNode != NULL) { - mxmlElementSetAttr(linkedNode, "target", sLink->targetPath); + mxmlElementSetAttr(linkNode,"target",sLink->targetPath); + linkedNode = getLinkTarget(xmlHandle,sLink->targetPath); + if(linkedNode != NULL){ + mxmlElementSetAttr(linkedNode,"target",sLink->targetPath); } return NX_OK; } - + /*-----------------------------------------------------------------------*/ -NXstatus NXXmakenamedlink(NXhandle fid, CONSTCHAR * name, NXlink * sLink) -{ +NXstatus NXXmakenamedlink (NXhandle fid, CONSTCHAR *name, NXlink* sLink){ pXMLNexus xmlHandle = NULL; mxml_node_t *current = NULL, *linkNode = NULL; mxml_node_t *linkedNode = NULL; + char buffer[256]; - xmlHandle = (pXMLNexus) fid; + xmlHandle = (pXMLNexus)fid; assert(xmlHandle); + if (!validNXName(name, 0)) + { + sprintf(buffer, "ERROR: invalid characters in link name \"%s\"", name); + NXReportError(buffer); + return NX_ERROR; + } - if (isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)) { - NXIReportError(NXpData, "No group to link to open"); + if(isDataNode(xmlHandle->stack[xmlHandle->stackPointer].current)){ + NXReportError("No group to link to open"); return NX_ERROR; - } + } current = xmlHandle->stack[xmlHandle->stackPointer].current; - linkNode = mxmlNewElement(current, "NAPIlink"); - if (!linkNode) { - NXIReportError(NXpData, "Failed to allocate new link element"); + linkNode = mxmlNewElement(current,"NAPIlink"); + if(!linkNode){ + NXReportError("Failed to allocate new link element"); return NX_ERROR; } - mxmlElementSetAttr(linkNode, "target", sLink->targetPath); - mxmlElementSetAttr(linkNode, "name", name); - linkedNode = getLinkTarget(xmlHandle, sLink->targetPath); - if (linkedNode != NULL) { - mxmlElementSetAttr(linkedNode, "target", sLink->targetPath); + mxmlElementSetAttr(linkNode,"target",sLink->targetPath); + mxmlElementSetAttr(linkNode,"name",name); + linkedNode = getLinkTarget(xmlHandle,sLink->targetPath); + if(linkedNode != NULL){ + mxmlElementSetAttr(linkedNode,"target",sLink->targetPath); } return NX_OK; } - /*----------------------------------------------------------------------*/ -NXstatus NXXsameID(NXhandle fileid, NXlink * pFirstID, NXlink * pSecondID) -{ - if (strcmp(pFirstID->targetPath, pSecondID->targetPath) == 0) { +NXstatus NXXsameID (NXhandle fileid, NXlink* pFirstID, + NXlink* pSecondID){ + if(strcmp(pFirstID->targetPath,pSecondID->targetPath) == 0) { return NX_OK; } else { return NX_ERROR; } } - /*--------------------------------------------------------------------*/ -int NXXcompress(NXhandle fid, int comp) -{ - NXIReportError(NXpData, "NXcompress is deprecated, IGNORED"); +int NXXcompress(NXhandle fid, int comp){ + /* that will throw an exception in the Java API, errors have to be fatal */ + /* NXReportError("NXcompress is deprecated, IGNORED"); */ return NX_OK; } - /*----------------------------------------------------------------------*/ -void NXXassignFunctions(pNexusFunction fHandle) -{ - fHandle->nxclose = NXXclose; - fHandle->nxflush = NXXflush; - fHandle->nxmakegroup = NXXmakegroup; - fHandle->nxopengroup = NXXopengroup; - fHandle->nxclosegroup = NXXclosegroup; - fHandle->nxmakedata = NXXmakedata; - fHandle->nxcompmakedata = NXXcompmakedata; - fHandle->nxcompress = NXXcompress; - fHandle->nxopendata = NXXopendata; - fHandle->nxclosedata = NXXclosedata; - fHandle->nxputdata = NXXputdata; - fHandle->nxputattr = NXXputattr; - fHandle->nxputslab = NXXputslab; - fHandle->nxgetdataID = NXXgetdataID; - fHandle->nxmakelink = NXXmakelink; - fHandle->nxmakenamedlink = NXXmakenamedlink; - fHandle->nxgetdata = NXXgetdata; - fHandle->nxgetinfo = NXXgetinfo; - fHandle->nxgetnextentry = NXXgetnextentry; - fHandle->nxgetslab = NXXgetslab; - fHandle->nxgetnextattr = NXXgetnextattr; - fHandle->nxgetattr = NXXgetattr; - fHandle->nxgetattrinfo = NXXgetattrinfo; - fHandle->nxgetgroupID = NXXgetgroupID; - fHandle->nxgetgroupinfo = NXXgetgroupinfo; - fHandle->nxsameID = NXXsameID; - fHandle->nxinitgroupdir = NXXinitgroupdir; - fHandle->nxinitattrdir = NXXinitattrdir; - fHandle->nxsetnumberformat = NXXsetnumberformat; - fHandle->nxprintlink = NXXprintlink; +void NXXassignFunctions(pNexusFunction fHandle){ + fHandle->nxclose=NXXclose; + fHandle->nxreopen=NULL; + fHandle->nxflush=NXXflush; + fHandle->nxmakegroup=NXXmakegroup; + fHandle->nxopengroup=NXXopengroup; + fHandle->nxclosegroup=NXXclosegroup; + fHandle->nxmakedata64=NXXmakedata64; + fHandle->nxcompmakedata64=NXXcompmakedata64; + fHandle->nxcompress=NXXcompress; + fHandle->nxopendata=NXXopendata; + fHandle->nxclosedata=NXXclosedata; + fHandle->nxputdata=NXXputdata; + fHandle->nxputattr=NXXputattr; + fHandle->nxputslab64=NXXputslab64; + fHandle->nxgetdataID=NXXgetdataID; + fHandle->nxmakelink=NXXmakelink; + fHandle->nxmakenamedlink=NXXmakenamedlink; + fHandle->nxgetdata=NXXgetdata; + fHandle->nxgetinfo64=NXXgetinfo64; + fHandle->nxgetnextentry=NXXgetnextentry; + fHandle->nxgetslab64=NXXgetslab64; + fHandle->nxgetnextattr=NXXgetnextattr; + fHandle->nxgetattr=NXXgetattr; + fHandle->nxgetattrinfo=NXXgetattrinfo; + fHandle->nxgetgroupID=NXXgetgroupID; + fHandle->nxgetgroupinfo=NXXgetgroupinfo; + fHandle->nxsameID=NXXsameID; + fHandle->nxinitgroupdir=NXXinitgroupdir; + fHandle->nxinitattrdir=NXXinitattrdir; + fHandle->nxsetnumberformat=NXXsetnumberformat; + fHandle->nxprintlink=NXXprintlink; + fHandle->nxnativeexternallink=NULL; } + + + +#endif /*NXXML*/ diff --git a/nxxml.h b/nxxml.h index c7b8c1b7..ee7e9ece 100644 --- a/nxxml.h +++ b/nxxml.h @@ -17,56 +17,62 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * - * For further information, see + * For further information, see */ #ifndef NEXUSXML #define NEXUSXML -extern NXstatus NXXopen(CONSTCHAR * filename, - NXaccess access_method, NXhandle * pHandle); -extern NXstatus NXXclose(NXhandle * pHandle); -extern NXstatus NXXflush(NXhandle * pHandle); +extern NXstatus NXXopen(CONSTCHAR *filename, + NXaccess access_method, + NXhandle* pHandle); +extern NXstatus NXXclose(NXhandle* pHandle); +extern NXstatus NXXflush(NXhandle* pHandle); -NXstatus NXXmakegroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass); -NXstatus NXXopengroup(NXhandle fid, CONSTCHAR * name, CONSTCHAR * nxclass); -NXstatus NXXclosegroup(NXhandle fid); +NXstatus NXXmakegroup (NXhandle fid, CONSTCHAR *name, + CONSTCHAR *nxclass); +NXstatus NXXopengroup (NXhandle fid, CONSTCHAR *name, + CONSTCHAR *nxclass); +NXstatus NXXclosegroup (NXhandle fid); -NXstatus NXXcompmakedata(NXhandle fid, CONSTCHAR * name, - int datatype, - int rank, - int dimensions[], - int compress_type, int chunk_size[]); -NXstatus NXXmakedata(NXhandle fid, - CONSTCHAR * name, int datatype, - int rank, int dimensions[]); -NXstatus NXXopendata(NXhandle fid, CONSTCHAR * name); -NXstatus NXXclosedata(NXhandle fid); -NXstatus NXXputdata(NXhandle fid, void *data); -NXstatus NXXgetdata(NXhandle fid, void *data); -NXstatus NXXgetinfo(NXhandle fid, int *rank, int dimension[], int *iType); -NXstatus NXXputslab(NXhandle fid, void *data, int iStart[], int iSize[]); -NXstatus NXXgetslab(NXhandle fid, void *data, int iStart[], int iSize[]); -NXstatus NXXputattr(NXhandle fid, CONSTCHAR * name, void *data, - int datalen, int iType); -NXstatus NXXgetattr(NXhandle fid, char *name, - void *data, int *datalen, int *iType); +NXstatus NXXcompmakedata64 (NXhandle fid, CONSTCHAR *name, + int datatype, + int rank, + int64_t dimensions[], + int compress_type, int64_t chunk_size[]); +NXstatus NXXmakedata64 (NXhandle fid, + CONSTCHAR *name, int datatype, + int rank, int64_t dimensions[]); +NXstatus NXXopendata (NXhandle fid, CONSTCHAR *name); +NXstatus NXXclosedata (NXhandle fid); +NXstatus NXXputdata (NXhandle fid, void *data); +NXstatus NXXgetdata (NXhandle fid, void *data); +NXstatus NXXgetinfo64 (NXhandle fid, int *rank, + int64_t dimension[], int *iType); +NXstatus NXXputslab64 (NXhandle fid, void *data, + int64_t iStart[], int64_t iSize[]); +NXstatus NXXgetslab64 (NXhandle fid, void *data, + const int64_t iStart[], const int64_t iSize[]); +NXstatus NXXputattr (NXhandle fid, CONSTCHAR *name, void *data, + int datalen, int iType); +NXstatus NXXgetattr (NXhandle fid, char *name, + void *data, int* datalen, int* iType); -NXstatus NXXgetnextentry(NXhandle fid, NXname name, - NXname nxclass, int *datatype); -extern NXstatus NXXgetnextattr(NXhandle handle, - NXname pName, int *iLength, int *iType); -extern NXstatus NXXinitgroupdir(NXhandle handle); -extern NXstatus NXXinitattrdir(NXhandle handle); -extern NXstatus NXXgetattrinfo(NXhandle fid, int *iN); -extern NXstatus NXXgetgroupinfo(NXhandle fid, int *iN, - NXname pName, NXname pClass); +NXstatus NXXgetnextentry (NXhandle fid,NXname name, + NXname nxclass, int *datatype); +extern NXstatus NXXgetnextattr(NXhandle handle, + NXname pName, int *iLength, int *iType); +extern NXstatus NXXinitgroupdir(NXhandle handle); +extern NXstatus NXXinitattrdir(NXhandle handle); +extern NXstatus NXXgetattrinfo (NXhandle fid, int *iN); +extern NXstatus NXXgetgroupinfo (NXhandle fid, int *iN, + NXname pName, NXname pClass); -extern NXstatus NXXgetdataID(NXhandle fid, NXlink * sRes); -extern NXstatus NXXgetgroupID(NXhandle fid, NXlink * sRes); -extern NXstatus NXXmakelink(NXhandle fid, NXlink * sLink); -extern NXstatus NXXprintlink(NXhandle fid, NXlink * sLink); -extern NXstatus NXXsameID(NXhandle fileid, - NXlink * pFirstID, NXlink * pSecondID); +extern NXstatus NXXgetdataID (NXhandle fid, NXlink* sRes); +extern NXstatus NXXgetgroupID (NXhandle fid, NXlink* sRes); +extern NXstatus NXXmakelink (NXhandle fid, NXlink* sLink); +extern NXstatus NXXprintlink (NXhandle fid, NXlink* sLink); +extern NXstatus NXXsameID (NXhandle fileid, + NXlink* pFirstID, NXlink* pSecondID); void NXXassignFunctions(pNexusFunction fHandle); #endif diff --git a/protocol.c b/protocol.c index 824e5b8a..a6226c17 100644 --- a/protocol.c +++ b/protocol.c @@ -715,7 +715,7 @@ int SCWriteJSON_String(SConnection * pCon, char *pBuffer, int iOut) /* print it to client if error message */ if ((iOut == eError) || (iOut == eWarning)) { tmp_json = json_object_new_string(pBuffer); - iRet = SCDoSockWrite(pCon, json_object_to_json_string(tmp_json)); + iRet = SCDoSockWrite(pCon, (char *)json_object_to_json_string(tmp_json)); } } else { if ((my_object = mkJSON_Object(pCon, pBuffer, iOut)) == NULL) { @@ -724,10 +724,10 @@ int SCWriteJSON_String(SConnection * pCon, char *pBuffer, int iOut) tmp_json = json_object_new_string(errBuff); my_object = json_object_new_object(); json_object_object_add(my_object, "ERROR", tmp_json); - SCDoSockWrite(pCon, json_object_to_json_string(my_object)); + SCDoSockWrite(pCon, (char *)json_object_to_json_string(my_object)); iRet = 0; } else { - iRet = SCDoSockWrite(pCon, json_object_to_json_string(my_object)); + iRet = SCDoSockWrite(pCon, (char *)json_object_to_json_string(my_object)); } } if (tmp_json != NULL && !is_error(tmp_json)) diff --git a/reflist.c b/reflist.c index 83d6ddcc..19a9e78f 100644 --- a/reflist.c +++ b/reflist.c @@ -240,6 +240,10 @@ static void AddRowIntern(pSICSOBJ refl, double hkl[], double ang[], if(child != NULL){ UpdateHipadabaPar(child, MakeHdbFloat(ang[3]),NULL); } + child = child->next; + if(child != NULL){ + UpdateHipadabaPar(child, MakeHdbFloat(ang[4]),NULL); + } runObjFunction(refl, pCon, node); } /*----------------------------------------------------------------------*/ @@ -253,7 +257,7 @@ static int AddAnglesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { int i; - double hkl[3], ang[4]; + double hkl[3], ang[5]; memset(hkl,0,3*sizeof(double)); memset(ang,0,4*sizeof(double)); @@ -314,6 +318,12 @@ static int AddIndexesAnglesCmd(pSICSOBJ self, SConnection * pCon, } else if(node!= NULL) { UpdateHipadabaPar(node, v, pCon); } + node = node->next; + if(node != NULL && nPar > 7){ + UpdateHipadabaPar(node, par[7]->value, pCon); + } else if(node!= NULL) { + UpdateHipadabaPar(node, v, pCon); + } return runObjFunction(self, pCon, addrowNode); } @@ -427,7 +437,7 @@ static int SetAnglesCmd(pSICSOBJ self, SConnection * pCon, /* do angles */ v = MakeHdbFloat(.0); - for(i = 0; i < 4 && child != NULL; i++, child = child->next){ + for(i = 0; i < 5 && child != NULL; i++, child = child->next){ if(child != NULL){ UpdateHipadabaPar(child, par[i+1]->value, pCon); } @@ -497,6 +507,7 @@ pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics, AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "nu", usUser, MakeHdbFloat(.0)); cmd = AddSICSHdbPar(pNew->objectNode, "seta", usUser, @@ -508,6 +519,7 @@ pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics, AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "nu", usUser, MakeHdbFloat(.0)); cmd = AddSICSHdbPar(pNew->objectNode, "addax", usUser, @@ -521,6 +533,7 @@ pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics, AddSICSHdbPar(cmd, "om", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "chi", usUser, MakeHdbFloat(.0)); AddSICSHdbPar(cmd, "phi", usUser, MakeHdbFloat(.0)); + AddSICSHdbPar(cmd, "nu", usUser, MakeHdbFloat(.0)); cmd = AddSICSHdbPar(pNew->objectNode, "show", usUser, @@ -620,7 +633,7 @@ int SetRefAngles(pSICSOBJ refl, int idx, double ang[]) /* skip over hkl */ for(i = 0; i < 3; i++, child = child->next){} /* set angles */ - for(i = 0; i < 4; i++, child = child->next){ + for(i = 0; i < 5; i++, child = child->next){ if(child != NULL){ UpdateHipadabaPar(child, MakeHdbFloat(ang[i]), NULL); } @@ -681,7 +694,7 @@ int GetRefAngles(pSICSOBJ refl, int idx, double ang[]) /* skip hkl */ for(i = 0; i < 3; i++, child = child->next){} /* do angles */ - for(i = 0; i < 4 && child != NULL; i++, child = child->next){ + for(i = 0; i < 5 && child != NULL; i++, child = child->next){ ang[i] = child->value.v.doubleValue; } return 1; @@ -704,7 +717,7 @@ int GetRefAnglesID(pSICSOBJ refl, char *id, double ang[]) /* skip hkl */ for(i = 0; i < 3; i++, child = child->next){} /* do angles */ - for(i = 0; i < 4 && child != NULL; i++, child = child->next){ + for(i = 0; i < 5 && child != NULL; i++, child = child->next){ ang[i] = child->value.v.doubleValue; } return 1; diff --git a/scriptcontext.c b/scriptcontext.c index f2751521..3862fa26 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -430,7 +430,7 @@ static char *SctActionHandler(void *actionData, char *lastReply, * Sometimes one wishes to call multiple scripts in succession * before returning into I/O. Such scripts then do not set the * send property. The loop is taking care of this. Not more - * then 10 scripts can be changed in this way. + * then 10 scripts can be chained in this way. */ for (i = 0; i < 10; i++) { /* diff --git a/sicshipadaba.c b/sicshipadaba.c index f77872eb..954e4902 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -454,11 +454,17 @@ int formatNameValue(Protocol protocol, char *name, char *value, /*----------------------------------------------------------------------------*/ static int sendZippedNodeData(pHdb node, hdbValue newValue, SConnection * pCon) { - int i, *iData = NULL; + int i, *iData = NULL, zip = 1; char *path = NULL; double sum = 0; + char value[80]; path = GetHipadabaPath(node); + if (GetHdbProperty(node, "transfer", value, 80) == 1) { + if(strstr(value,"bin") != NULL) { + zip = 0; + } + } switch (newValue.dataType) { case HIPINTAR: case HIPINTVARAR: @@ -474,10 +480,14 @@ static int sendZippedNodeData(pHdb node, hdbValue newValue, SConnection * pCon) } memset(iData, 0, newValue.arrayLength * sizeof(int)); for (i = 0; i < newValue.arrayLength; i++) { - sum += (double)newValue.v.intArray[i]; +/* sum += (double)newValue.v.intArray[i]; */ iData[i] = htonl(newValue.v.intArray[i]); } - SCWriteZipped(pCon, path, iData, newValue.arrayLength * sizeof(int)); + if(zip == 1){ + SCWriteZipped(pCon, path, iData, newValue.arrayLength * sizeof(int)); + } else { + SCWriteBinary(pCon, path, iData, newValue.arrayLength * sizeof(int)); + } free(iData); /* printf("Wrote zipped data %s, sum %lf\n", path, sum); */ break; @@ -498,8 +508,12 @@ static int sendZippedNodeData(pHdb node, hdbValue newValue, SConnection * pCon) sum+= newValue.v.floatArray[i]; iData[i] = htonl((int) (newValue.v.floatArray[i] * 65536.)); } - SCWriteZipped(pCon, path, iData, newValue.arrayLength * sizeof(int)); + if(zip == 1) { + SCWriteZipped(pCon, path, iData, newValue.arrayLength * sizeof(int)); /* printf("Wrote zipped data %s, sum %lf\n", path, sum); */ + } else { + SCWriteBinary(pCon, path, iData, newValue.arrayLength * sizeof(int)); + } free(iData); break; default: @@ -600,7 +614,7 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData, * if transfer = zip always transfer data in zipped form */ if (GetHdbProperty(node, "transfer", value, 80) == 1) { - if (strstr(value, "zip") != NULL) { + if (strstr(value, "zip") != NULL || strstr(value,"bin") != NULL) { status = sendZippedNodeData(node, *(mm->v), cbInfo->pCon); free(pPath); DeleteDynString(result); @@ -672,9 +686,9 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData, char buffer[1024]; pDynString result = NULL; Protocol protocol = normal_protocol; - int outCode; pHdbIDMessage idm = NULL; pHdbPtrMessage cmm = NULL; + int outCode; pHdbTreeChangeMessage tm = NULL; SConnection *tstCon = NULL; @@ -714,7 +728,7 @@ static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData, result = CreateDynString(128, 128); if (result == NULL) { SCWrite(cbInfo->pCon, "ERROR: out of memory in TreeChangeCallback", - outCode); + eError); return hdbAbort; } path = GetHipadabaPath(node); @@ -2908,7 +2922,7 @@ static int AutoNotifyHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { pHdb node = NULL; - int id, status; + int id, status, recurse = 1; if (argc < 3) { SCWrite(pCon, "ERROR: need path and id in order to add notify", @@ -2923,7 +2937,11 @@ static int AutoNotifyHdbNode(SConnection * pCon, SicsInterp * pSics, id = atoi(argv[2]); - status = InstallSICSNotify(node, pCon, id, 1); + if(argc > 3) { + recurse = atoi(argv[3]); + } + + status = InstallSICSNotify(node, pCon, id, recurse); if (status == 1) { SCSendOK(pCon); } diff --git a/simidx.c b/simidx.c index 33de098a..b8874f1e 100644 --- a/simidx.c +++ b/simidx.c @@ -617,39 +617,6 @@ static int findSolutionsForTriplet(int triplet[3], int testRight) return 1; } -/*------------------------------------------------------------- - * If the system is right handed the determinat of the - * matrix having the indices as columns must be positive. - * As I have only two vectors, I simulate the third by - * using the nromal on the other two. - -------------------------------------------------------------*/ -static int testDuoRightHandedness(int r1, int r1idx, int r2, int r2idx) -{ - MATRIX T; - double vol; - int r3, r3idx; - - T = mat_creat(3, 3, ZERO_MATRIX); - if (T == NULL) { - return 0; - } - T[0][0] = reflections[r1].indices[r1idx].h; - T[1][0] = reflections[r1].indices[r1idx].k; - T[2][0] = reflections[r1].indices[r1idx].l; - T[0][1] = reflections[r2].indices[r2idx].h; - T[1][1] = reflections[r2].indices[r2idx].k; - T[2][1] = reflections[r2].indices[r2idx].l; - T[0][2] = reflections[r3].indices[r3idx].h; - T[1][2] = reflections[r3].indices[r3idx].k; - T[2][2] = reflections[r3].indices[r3idx].l; - vol = mat_det(T); - mat_free(T); - if (vol > .0) { - return 1; - } else { - return 0; - } -} /*--------------------------------------------------------------*/ static int findSolutionsForDuett(int triplet[3]) diff --git a/simindex.c b/simindex.c index a9ad9518..97aa4b19 100644 --- a/simindex.c +++ b/simindex.c @@ -112,7 +112,7 @@ static int RunIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, int i, j, status, err; pSingleDiff diffi; pSICSOBJ reflist; - double ang[4], z1[3]; + double ang[5], z1[3]; IndexSolution is; MATRIX ub; pHdb nSol = NULL; @@ -265,7 +265,7 @@ static int IndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { int i, j; - double ang[4], hkl[3]; + double ang[5], hkl[3]; const double *ub; pSICSOBJ reflist = NULL; pSingleDiff diffi = NULL; diff --git a/singlenb.c b/singlenb.c index b20cd986..2a05e14f 100644 --- a/singlenb.c +++ b/singlenb.c @@ -40,7 +40,7 @@ static int checkTheta(pSingleDiff self, double *stt) } /*-----------------------------------------------------------------------*/ -static int checkNormalBeam(double om, double *gamma, double nu, +int checkNormalBeam(double om, double *gamma, double nu, double fSet[4], pSingleDiff self) { int iTest; diff --git a/singlex.c b/singlex.c index 10b238f6..05319d31 100644 --- a/singlex.c +++ b/singlex.c @@ -25,6 +25,7 @@ #include "singelbi.h" #include "singlenb.h" #include "singletas.h" +#include "singlebinb.h" #include "lld.h" #include "fourlib.h" @@ -225,6 +226,7 @@ static int findModeIndex(char *mode) "bi", "nb", "tas", + "binb", NULL }; int count = 0; @@ -292,6 +294,19 @@ static hdbCallbackReturn SetModeCB(pHdb node, void *userData, priv->mode = Tas; initializeSingleTas(priv->diffractometer); return hdbContinue; + case BiNB: + if (priv->stt == NULL || priv->nu == NULL || priv->om == NULL + || priv->chi == NULL || priv->phi == NULL) { + if (pCon != NULL) { + SCWrite(pCon, "ERROR: required motor for BINB not configured", + eError); + } + return hdbAbort; + } + priv->mode = BiNB; + initializeSingleBINB(priv->diffractometer); + return hdbContinue; + default: if (set->callData != NULL) { pCon = set->callData; diff --git a/singlex.h b/singlex.h index 30646319..5cda343e 100644 --- a/singlex.h +++ b/singlex.h @@ -35,7 +35,7 @@ double SXGetLambda(); pSICSOBJ SXGetReflectionList(); typedef enum { - Bisecting, NB, Tas + Bisecting, NB, Tas, BiNB, } SingleXModes; SingleXModes SXGetMode(); diff --git a/sllinux_def b/sllinux_def index a97f1d5e..31af4a94 100644 --- a/sllinux_def +++ b/sllinux_def @@ -9,5 +9,5 @@ MFLAGS=-f makefile_linux$(DUMMY) -HDFROOT=/afs/psi.ch/project/sinq/sl5 +HDFROOT=/afs/psi.ch/project/sinq/sl6 TCLINC=. \ No newline at end of file diff --git a/stdscan.c b/stdscan.c index c177c245..616a18d5 100644 --- a/stdscan.c +++ b/stdscan.c @@ -558,16 +558,27 @@ int prepareDataFile(pScanData self) { char *pPtr = NULL; char pBueffel[512]; + Tcl_Interp *pTcl; + const char *val = NULL; - /* allocate a new data file */ - pPtr = ScanMakeFileName(pServ->pSics, self->pCon); - if (!pPtr) { - SCWrite(self->pCon, - "ERROR: cannot allocate new data filename, Scan aborted", - eLogError); - self->pCon = NULL; - self->pSics = NULL; - return 0; + pTcl = InterpGetTcl(pServ->pSics); + val = Tcl_GetVar(pTcl,"simMode",TCL_GLOBAL_ONLY); + if(val != NULL){ + if(strstr(val,"2") != NULL){ + pPtr = strdup("sicssim.scn"); + } + } else { + + /* allocate a new data file */ + pPtr = ScanMakeFileName(pServ->pSics, self->pCon); + if (!pPtr) { + SCWrite(self->pCon, + "ERROR: cannot allocate new data filename, Scan aborted", + eLogError); + self->pCon = NULL; + self->pSics = NULL; + return 0; + } } snprintf(pBueffel, 511, "Writing data file: %s ...", pPtr); SCWrite(self->pCon, pBueffel, eLog); diff --git a/tasdrive.c b/tasdrive.c index fcdb3cbe..95bf979a 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -563,6 +563,8 @@ static int checkMotors(ptasMot self, SConnection * pCon) if(status == HWIdle || status == OKOK || status == HWFault || status == HWPosFault){ busy[i] = 0; } + } else { + busy[i] = 0; } } } diff --git a/test/DataNumber b/test/DataNumber index 1d6489e6..00ce41bb 100644 --- a/test/DataNumber +++ b/test/DataNumber @@ -1,3 +1,3 @@ - 332 + 340 NEVER, EVER modify or delete this file You'll risk eternal damnation and a reincarnation as a cockroach! diff --git a/trace.c b/trace.c index cd8d2e91..9d249d94 100644 --- a/trace.c +++ b/trace.c @@ -192,7 +192,9 @@ void traceprint(char *sub, char *id, char *data) { if(log != NULL && filter(sub,id)){ strrepc(data,'\n',':'); - fprintf(log,"%s:%s:%lf:%s\n", sub,id,DoubleTime(),data); + strrepc(sub,':','@'); + strrepc(id,':','@'); + fprintf(log,"%s:%s:%lf:%s\n",sub,id,DoubleTime(),data); } } /*-----------------------------------------------------------------*/ diff --git a/ubcalc.c b/ubcalc.c index 3c3146be..41c64eac 100644 --- a/ubcalc.c +++ b/ubcalc.c @@ -145,7 +145,7 @@ static int updateUBCALC(pUBCALC self, SConnection * pCon, char *id1, char *id2, char *id3) { const double *cell; - double hkl[3], angles[4]; + double hkl[3], angles[5]; pSICSOBJ refList; cell = SXGetCell();