From 1247dcdb8282662213d4a50022ea043d84d00a33 Mon Sep 17 00:00:00 2001 From: koennecke Date: Fri, 27 May 2005 11:58:05 +0000 Subject: [PATCH] - Switched to NAPI-3.0 with XML support - Fixed exeman to write files by default into the first directory in batchpath - Fixed a bug in nxdict which prevented it from handling attributes containing :/ properly - Removed junk files - Fixed a bug in hklscan.c which made it dump core - Added XML support to nxscript.c - Added support for writing NeXus-XML data files to tasub --- exeman.c | 15 +- hklscan.c | 2 +- make_gen | 10 +- makefile_slinux | 4 +- napi.c | 416 ++++++++--- napi.h | 86 ++- napi.tex | 1850 ----------------------------------------------- napi4.c | 98 ++- napi4.h | 9 +- napi45.c | 630 ---------------- napi5.c | 87 ++- napi5.h | 6 +- napif.f | 274 ------- napif.inc | 47 -- nxdataset.c | 299 ++++++++ nxdataset.h | 69 ++ nxdict.c | 63 +- nxio.c | 550 ++++++++++++++ nxio.h | 45 ++ nxscript.c | 90 +++ scan.c | 3 + scan.tex | 4 + scan.w | 4 + stdscan.c | 8 +- stdscan.h | 12 +- tasdrive.c | 3 +- tasscanub.c | 98 +++ 27 files changed, 1805 insertions(+), 2977 deletions(-) delete mode 100644 napi.tex delete mode 100644 napi45.c delete mode 100644 napif.f delete mode 100644 napif.inc create mode 100644 nxdataset.c create mode 100644 nxdataset.h create mode 100644 nxio.c create mode 100644 nxio.h diff --git a/exeman.c b/exeman.c index b04fe6bf..7478090c 100644 --- a/exeman.c +++ b/exeman.c @@ -391,6 +391,7 @@ static int appendLine(pExeMan self, SConnection *pCon, static int uploadSave(pExeMan self, SConnection *pCon, int argc, char *argv[]){ int status; + char pPath[256], *pPtr; if(SCGetRights(pCon) > usUser){ SCWrite(pCon,"ERROR: no permission to save buffers",eError); @@ -404,7 +405,19 @@ static int uploadSave(pExeMan self, SConnection *pCon, SCWrite(pCon,"ERROR: no upload buffer to save exists",eError); return 0; } - status = exeBufSave(self->uploadBuffer,argv[2]); + if(argv[2][0] != '/') { + pPtr = self->batchPath; + pPtr = stptok(pPtr,pPath,131,":"); + if(strlen(pPath) + 1 + strlen(argv[2]) <= 256){ + strcat(pPath,"/"); + strcat(pPath,argv[2]); + } else { + strncpy(pPath,argv[2],255); + } + } else { + strncpy(pPath,argv[2],131); + } + status = exeBufSave(self->uploadBuffer,pPath); if(status == 0){ SCWrite(pCon,"ERROR: failed to save exe buffer, destroyed...",eError); } diff --git a/hklscan.c b/hklscan.c index ffa12325..883fc6de 100644 --- a/hklscan.c +++ b/hklscan.c @@ -208,7 +208,7 @@ pVar = (pVarEntry)pPtr; if(pVar) { - sprintf(pItem," %-7.2f",pVar->fData[i]); + sprintf(pItem," %-7.2f",GetScanVarPos(pVar,i)); strcat(pLine,pItem); } } diff --git a/make_gen b/make_gen index ad60dade..f04b3d15 100644 --- a/make_gen +++ b/make_gen @@ -11,9 +11,9 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ sicsexit.o costa.o task.o $(FORTIFYOBJ)\ macro.o ofac.o obpar.o obdes.o drive.o status.o intserv.o \ devexec.o mumo.o mumoconf.o selector.o selvar.o fupa.o lld.o \ - lld_blob.o strrepl.o lin2ang.o fomerge.o\ - script.o o2t.o alias.o napi.o nxdata.o stringdict.o sdynar.o\ - histmem.o histdriv.o histsim.o interface.o callback.o \ + lld_blob.o strrepl.o lin2ang.o fomerge.o napi4.o napi5.o \ + script.o o2t.o alias.o napi.o nxdata.o stringdict.o sdynar.o \ + histmem.o histdriv.o histsim.o interface.o callback.o nxio.o \ event.o emon.o evcontroller.o evdriver.o simev.o perfmon.o \ danu.o nxdict.o varlog.o stptok.o nread.o trigd.o cell.o\ scan.o fitcenter.o telnet.o token.o wwildcard.o hklmot.o\ @@ -23,10 +23,10 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ simchop.o choco.o chadapter.o trim.o scaldate.o tasub.o\ hklscan.o xytable.o exebuf.o exeman.o ubfour.o ubcalc.o\ circular.o maximize.o sicscron.o scanvar.o tasublib.o\ - d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o\ + d_sign.o d_mod.o tcldrivable.o stdscan.o diffscan.o nxxml.o\ synchronize.o definealias.o oscillate.o tasdrive.o \ hmcontrol.o userscan.o rs232controller.o lomax.o tasscanub.o \ - fourlib.o motreg.o motreglist.o anticollider.o \ + fourlib.o motreg.o motreglist.o anticollider.o nxdataset.o \ s_rnge.o sig_die.o gpibcontroller.o $(NIOBJ) \ hmdata.o nxscript.o tclintimpl.o sicsdata.o diff --git a/makefile_slinux b/makefile_slinux index 37382d79..e5303ae1 100644 --- a/makefile_slinux +++ b/makefile_slinux @@ -14,7 +14,7 @@ NILIB=$(SINQDIR)/linux/lib/cib.o include sllinux_def CC = gcc -CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 $(NI) \ +CFLAGS = -I$(HDFROOT)/include -DHDF4 -DHDF5 -DNXXML $(NI) \ -Ipsi/hardsup -I. \ -fwritable-strings -DCYGNUS -DNONINTF -g $(DFORTIFY) \ -Wall -Wno-unused -Wno-comment -Wno-switch @@ -26,7 +26,7 @@ SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \ LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\ -ltcl8.3 $(HDFROOT)/lib/libhdf5.a \ $(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \ - $(HDFROOT)/lib/libjpeg.a -lsz -ldl -lz -lm -lc + $(HDFROOT)/lib/libjpeg.a -lsz -ldl -lz -lmxml -lm -lc include make_gen diff --git a/napi.c b/napi.c index b7410d6b..98777341 100644 --- a/napi.c +++ b/napi.c @@ -23,48 +23,16 @@ ----------------------------------------------------------------------------*/ -static const char* rscid = "$Id: napi.c,v 1.9 2005/03/08 11:11:51 zolliker Exp $"; /* Revision interted by CVS */ +static const char* rscid = "$Id: napi.c,v 1.10 2005/05/27 11:58:05 koennecke Exp $"; /* Revision interted by CVS */ +#include #include #include #include #include +#include #include "napi.h" -/* - * We need to include CALLING_STYLE in the function pointer definition - * or else we get a type mismatch on Win32 - */ - typedef struct { - NXhandle *pNexusData; - NXstatus (CALLING_STYLE *nxclose)(NXhandle* pHandle); - NXstatus (CALLING_STYLE *nxflush)(NXhandle* pHandle); - NXstatus (CALLING_STYLE *nxmakegroup) (NXhandle handle, CONSTCHAR *name, char* NXclass); - NXstatus (CALLING_STYLE *nxopengroup) (NXhandle handle, CONSTCHAR *name, char* NXclass); - NXstatus (CALLING_STYLE *nxclosegroup)(NXhandle handle); - NXstatus (CALLING_STYLE *nxmakedata) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); - NXstatus (CALLING_STYLE *nxcompmakedata) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]); - NXstatus (CALLING_STYLE *nxcompress) (NXhandle handle, int compr_type); - NXstatus (CALLING_STYLE *nxopendata) (NXhandle handle, CONSTCHAR* label); - NXstatus (CALLING_STYLE *nxclosedata)(NXhandle handle); - NXstatus (CALLING_STYLE *nxputdata)(NXhandle handle, void* data); - NXstatus (CALLING_STYLE *nxputattr)(NXhandle handle, CONSTCHAR* name, void* data, int iDataLen, int iType); - NXstatus (CALLING_STYLE *nxputslab)(NXhandle handle, void* data, int start[], int size[]); - NXstatus (CALLING_STYLE *nxgetdataID)(NXhandle handle, NXlink* pLink); - NXstatus (CALLING_STYLE *nxmakelink)(NXhandle handle, NXlink* pLink); - NXstatus (CALLING_STYLE *nxgetdata)(NXhandle handle, void* data); - NXstatus (CALLING_STYLE *nxgetinfo)(NXhandle handle, int* rank, int dimension[], int* datatype); - NXstatus (CALLING_STYLE *nxgetnextentry)(NXhandle handle, NXname name, NXname nxclass, int* datatype); - NXstatus (CALLING_STYLE *nxgetslab)(NXhandle handle, void* data, int start[], int size[]); - NXstatus (CALLING_STYLE *nxgetnextattr)(NXhandle handle, NXname pName, int *iLength, int *iType); - NXstatus (CALLING_STYLE *nxgetattr)(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); - NXstatus (CALLING_STYLE *nxgetattrinfo)(NXhandle handle, int* no_items); - NXstatus (CALLING_STYLE *nxgetgroupID)(NXhandle handle, NXlink* pLink); - NXstatus (CALLING_STYLE *nxgetgroupinfo)(NXhandle handle, int* no_items, NXname name, NXname nxclass); - NXstatus (CALLING_STYLE *nxsameID)(NXhandle handle, NXlink* pFirstID, NXlink* pSecondID); - NXstatus (CALLING_STYLE *nxinitgroupdir)(NXhandle handle); - NXstatus (CALLING_STYLE *nxinitattrdir)(NXhandle handle); - } NexusFunction, *pNexusFunction; static int iFortifyScope; /*------------------------------------------------------------------------ @@ -81,6 +49,23 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) } return NX_ERROR; } +/*-----------------------------------------------------------------------*/ +static NXstatus NXisXML(CONSTCHAR *filename) +{ + FILE *fd = NULL; + char line[132]; + + fd = fopen(filename,"r"); + if(fd) { + fgets(line,131,fd); + fclose(fd); + if(strstr(line,"?xml") != NULL){ + return NX_OK; + } + } + return NX_ERROR; +} +/*-------------------------------------------------------------------------*/ /*---------------------------------------------------------------------*/ @@ -97,7 +82,8 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) /*---------------------------------------------------------------------*/ - NX_EXTERNAL void CALLING_STYLE NXMSetError(void *pData, void (*NewError)(void *pD, char *text)) + NX_EXTERNAL void CALLING_STYLE NXMSetError(void *pData, + void (*NewError)(void *pD, char *text)) { NXpData = pData; NXIReportError = NewError; @@ -109,34 +95,75 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) #ifdef HDF4 #include "napi4.h" #endif - +#ifdef NXXML +#include "nxxml.h" +#endif /* ---------------------------------------------------------------------- Definition of NeXus API ---------------------------------------------------------------------*/ - - +static int determineFileType(CONSTCHAR *filename) +{ + FILE *fd = NULL; + int iRet, fapl; + NXhandle handle; + + /* + 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){ + return 2; + } +#endif +#ifdef HDF4 + iRet=Hishdf((const char*)filename); + if( iRet > 0){ + return 1; + } +#endif +#ifdef NXXML + iRet = NXisXML(filename); + if(iRet == NX_OK){ + return 3; + } +#endif + /* + file type not recognized + */ + return 0; +} +/*-----------------------------------------------------------------------*/ NXstatus CALLING_STYLE NXopen(CONSTCHAR *filename, NXaccess am, NXhandle *gHandle) { int hdf_type=0; int iRet=0; NXhandle hdf5_handle; NXhandle hdf4_handle; + NXhandle xmlHandle; pNexusFunction fHandle; NXstatus retstat; + char error[1024]; /* configure fortify iFortifyScope = Fortify_EnterScope(); Fortify_CheckAllMemory(); */ - + *gHandle = NULL; 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 */ if (am==NXACC_CREATE) { /* HDF4 will be used ! */ hdf_type=1; @@ -146,21 +173,25 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) } else if (am==NXACC_CREATE5) { /* HDF5 will be used ! */ hdf_type=2; + } else if (am==NXACC_CREATEXML) { + /* XML will be used ! */ + hdf_type=3; } else { - /* check file type hdf4/hdf5 for reading */ -#ifdef HDF5 - iRet=H5Fis_hdf5((const char*)filename); -#endif - if (iRet>0) { - hdf_type=2; - } else { -#ifdef HDF4 - iRet=Hishdf((const char*)filename); -#endif - if (iRet>0) { - hdf_type=1; - } + /* 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); + return NX_ERROR; } + if(iRet == 0){ + snprintf(error,1023,"failed to detrmine filetype for %s ", + filename); + NXIReportError(NXpData,error); + return NX_ERROR; + } + hdf_type = iRet; } if (hdf_type==1) { /* HDF4 type */ @@ -171,36 +202,11 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) return retstat; } fHandle->pNexusData=hdf4_handle; - 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->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; + NX4assignFunctions(fHandle); *gHandle = fHandle; #else - NXIReportError (NXpData,"ERROR: Attempt to create HDF4 file when not linked with HDF4"); + NXIReportError (NXpData, + "ERROR: Attempt to create HDF4 file when not linked with HDF4"); *gHandle = NULL; retstat = NX_ERROR; #endif /* HDF4 */ @@ -214,46 +220,41 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) return retstat; } fHandle->pNexusData=hdf5_handle; - 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->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; + NX5assignFunctions(fHandle); *gHandle = fHandle; #else - NXIReportError (NXpData,"ERROR: Attempt to create HDF5 file when not linked with HDF5"); + NXIReportError (NXpData, + "ERROR: Attempt to create HDF5 file when not linked with HDF5"); *gHandle = NULL; retstat = NX_ERROR; #endif /* HDF5 */ return retstat; + } else if(hdf_type == 3){ + /* + XML type + */ +#ifdef NXXML + retstat = NXXopen(filename,am,&xmlHandle); + if(retstat != NX_OK){ + free(fHandle); + return retstat; + } + fHandle->pNexusData=xmlHandle; + NXXassignFunctions(fHandle); + *gHandle = fHandle; +#else + NXIReportError (NXpData, + "ERROR: Attempt to create XML file when not linked with XML"); + *gHandle = NULL; + retstat = NX_ERROR; +#endif } else { NXIReportError (NXpData, "ERROR: Format not readable by this NeXus library"); *gHandle = NULL; return NX_ERROR; } + return NX_OK; } /* ------------------------------------------------------------------------- */ @@ -277,7 +278,7 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) /*-----------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NXmakegroup (NXhandle fid, CONSTCHAR *name, char *nxclass) + NXstatus CALLING_STYLE NXmakegroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { pNexusFunction pFunc = (pNexusFunction)fid; return pFunc->nxmakegroup(pFunc->pNexusData, name, nxclass); @@ -285,7 +286,7 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) /*------------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NXopengroup (NXhandle fid, CONSTCHAR *name, char *nxclass) + NXstatus CALLING_STYLE NXopengroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { pNexusFunction pFunc = (pNexusFunction)fid; return pFunc->nxopengroup(pFunc->pNexusData, name, nxclass); @@ -386,8 +387,20 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) pNexusFunction pFunc = (pNexusFunction)fid; return pFunc->nxmakelink(pFunc->pNexusData, sLink); } + /* --------------------------------------------------------------------*/ + NXstatus CALLING_STYLE 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; + } + return NXopengrouppath(fid,target_path); + } /*----------------------------------------------------------------------*/ NXstatus CALLING_STYLE NXflush(NXhandle *pHandle) @@ -547,6 +560,25 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) pNexusFunction pFunc = (pNexusFunction)fid; return pFunc->nxinitattrdir(pFunc->pNexusData); } + /*-------------------------------------------------------------------------*/ + + NXstatus CALLING_STYLE NXsetnumberformat (NXhandle fid, + int type, char *format) + { + pNexusFunction pFunc = (pNexusFunction)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; + } + } /*-------------------------------------------------------------------------*/ @@ -556,6 +588,7 @@ NXstatus CALLING_STYLE NXsetcache(long newVal) pNexusFunction pFunc = (pNexusFunction)fid; return pFunc->nxinitgroupdir(pFunc->pNexusData); } + /*------------------------------------------------------------------------ Implementation of NXopenpath. --------------------------------------------------------------------------*/ @@ -742,6 +775,42 @@ static NXstatus stepOneUp(NXhandle hfil, char *name) NXIReportError (NXpData, pBueffel); return NX_ERROR; } +/*--------------------------------------------------------------------*/ +static NXstatus stepOneGroupUp(NXhandle hfil, char *name) +{ + int status, datatype; + NXname name2, xclass; + 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; + } + + 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); + } + } + } + snprintf(pBueffel,255,"ERROR: NXopenpath cannot step into %s",name); + NXIReportError (NXpData, pBueffel); + return NX_ERROR; +} /*---------------------------------------------------------------------*/ NXstatus CALLING_STYLE NXopenpath(NXhandle hfil, CONSTCHAR *path) { @@ -779,6 +848,115 @@ NXstatus CALLING_STYLE NXopenpath(NXhandle hfil, CONSTCHAR *path) } return NX_OK; } +/*---------------------------------------------------------------------*/ +NXstatus CALLING_STYLE 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"); + return NX_ERROR; + } + + pPtr = moveDown(hfil,(char *)path,&status); + if(status != NX_OK) + { + NXIReportError (NXpData, + "ERROR: NXopendata failed to move down in hierarchy"); + return status; + } + + while(run == 1) + { + pPtr = extractNextPath(pPtr, pathElement); + status = stepOneGroupUp(hfil,pathElement); + if(status == NX_ERROR) + { + return status; + } + if(pPtr == NULL || status == NX_EOD) + { + run = 0; + } + } + 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; +#ifdef USE_FTIME + 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"; + } + 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) + ); + } + else + { + strcpy(time_buffer, "1970-01-01 00:00:00+0000"); + } + return time_buffer; +} /*---------------------------------------------------------------------- F77 - API - Support - Routines ----------------------------------------------------------------------*/ @@ -907,3 +1085,17 @@ NXstatus CALLING_STYLE NXopenpath(NXhandle hfil, CONSTCHAR *path) { return NXputattr(fid, name, data, *pDatalen, *pIType); } + + + /* + * implement snprintf when it is not available + */ + 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; + } diff --git a/napi.h b/napi.h index 7e40ac5e..edf04a2d 100644 --- a/napi.h +++ b/napi.h @@ -21,7 +21,7 @@ For further information, see - $Id: napi.h,v 1.7 2004/11/17 10:50:16 cvs Exp $ + $Id: napi.h,v 1.8 2005/05/27 11:58:05 koennecke Exp $ ----------------------------------------------------------------------------*/ @@ -29,7 +29,7 @@ #define NEXUSAPI /* NeXus HDF45 */ -#define NEXUS_VERSION "2.1.0" /* major.minor.patch */ +#define NEXUS_VERSION "3.0.0" /* major.minor.patch */ #define CONSTCHAR const char @@ -43,11 +43,18 @@ # define NX_EXTERNAL #endif +#ifdef _WIN32 +#define snprintf nxisnprintf + +extern int nxisnprintf(char* buffer, int len, const char* format, ... ); + +#endif + typedef void* NXhandle; /* really a pointer to a NexusFile structure */ typedef int NXstatus; typedef char NXname[128]; -typedef enum {NXACC_READ=1, NXACC_RDWR=2, NXACC_CREATE=3, NXACC_CREATE4=4, NXACC_CREATE5=5} NXaccess; +typedef enum {NXACC_READ=1, NXACC_RDWR=2, NXACC_CREATE=3, NXACC_CREATE4=4, NXACC_CREATE5=5, NXACC_CREATEXML=6} NXaccess; typedef struct { char *iname; @@ -90,6 +97,7 @@ typedef struct { #define NX_FLOAT64 6 #define NX_INT8 20 #define NX_UINT8 21 +#define NX_BOOLEAN NX_UINT #define NX_INT16 22 #define NX_UINT16 23 #define NX_INT32 24 @@ -112,17 +120,19 @@ typedef struct { #include #endif -typedef struct { -#ifdef HDF4 - int32 iTag; /* HDF4 variable */ - int32 iRef; /* HDF4 variable */ +#ifndef HDF4 +typedef int int32; #endif +typedef struct { + int32 iTag; /* HDF4 variable */ + int32 iRef; /* HDF4 variable */ #ifdef HDF5 char iTag5[1024]; /* HDF5 variable */ char iRef5[1024]; /* HDF5 variable */ char iRefd[1024]; /* HDF5 variable */ -#endif +#endif + char targetPath[1024]; /* XML path */ } NXlink; @@ -146,6 +156,7 @@ typedef struct { # define NXmakegroup MANGLE(nximakegroup) # define NXopengroup MANGLE(nxiopengroup) # define NXopenpath MANGLE(nxiopenpath) +# define NXopengrouppath MANGLE(nxiopengrouppath) # define NXclosegroup MANGLE(nxiclosegroup) # define NXmakedata MANGLE(nximakedata) # define NXcompmakedata MANGLE(nxicompmakedata) @@ -157,6 +168,7 @@ typedef struct { # define NXputattr MANGLE(nxiputattr) # define NXgetdataID MANGLE(nxigetdataid) # define NXmakelink MANGLE(nximakelink) +# define NXopensourcegroup MANGLE(nxiopensourcegroup) # define NXmalloc MANGLE(nximalloc) # define NXfree MANGLE(nxifree) # define NXflush MANGLE(nxiflush) @@ -174,6 +186,7 @@ typedef struct { # define NXsameID MANGLE(nxisameid) # define NXinitgroupdir MANGLE(nxiinitgroupdir) # define NXinitattrdir MANGLE(nxiinitattrdir) +# define NXsetnumberformat MANGLE(nxisetnumberformat) # define NXsetcache MANGLE(nxisetcache) /* FORTRAN helpers - for NeXus internal use only */ # define NXfopen MANGLE(nxifopen) @@ -217,6 +230,7 @@ typedef struct { # define NXmakegroup MANGLE(NXIMAKEGROUP) # define NXopengroup MANGLE(NXIOPENGROUP) # define NXopenpath MANGLE(NXIOPENPATH) +# define NXopengrouppath MANGLE(NXIOPENGROUPPATH) # define NXclosegroup MANGLE(NXICLOSEGROUP) # define NXmakedata MANGLE(NXIMAKEDATA) # define NXcompress MANGLE(NXICOMPRESS) @@ -237,10 +251,12 @@ typedef struct { # define NXgetnextentry MANGLE(NXIGETNEXTENTRY) # define NXgetattrinfo MANGLE(NXIGETATTRINFO) # define NXinitattrdir MANGLE(NXIINITATTRDIR) +# define NXsetnumberformat MANGLE(NXISETNUMBERFORMAT) # define NXgetnextattr MANGLE(NXIGETNEXTATTR) # define NXgetgroupID MANGLE(NXIGETGROUPID) # define NXgetdataID MANGLE(NXIGETDATAID) # define NXmakelink MANGLE(NXIMAKELINK) +# define NXopensourcegroup MANGLE(NXIOPENSOURCEGROUP) # define NXmalloc MANGLE(NXIMALLOC) # define NXfree MANGLE(NXIFREE) /* FORTRAN helpers - for NeXus internal use only */ @@ -267,9 +283,10 @@ NX_EXTERNAL NXstatus CALLING_STYLE NXopen(CONSTCHAR * filename, NXaccess access NX_EXTERNAL NXstatus CALLING_STYLE NXclose(NXhandle* pHandle); NX_EXTERNAL NXstatus CALLING_STYLE NXflush(NXhandle* pHandle); -NX_EXTERNAL NXstatus CALLING_STYLE NXmakegroup (NXhandle handle, CONSTCHAR *name, char* NXclass); -NX_EXTERNAL NXstatus CALLING_STYLE NXopengroup (NXhandle handle, CONSTCHAR *name, char* NXclass); +NX_EXTERNAL NXstatus CALLING_STYLE NXmakegroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); +NX_EXTERNAL NXstatus CALLING_STYLE NXopengroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); NX_EXTERNAL NXstatus CALLING_STYLE NXopenpath (NXhandle handle, CONSTCHAR *path); +NX_EXTERNAL NXstatus CALLING_STYLE NXopengrouppath (NXhandle handle, CONSTCHAR *path); NX_EXTERNAL NXstatus CALLING_STYLE NXclosegroup(NXhandle handle); @@ -285,6 +302,7 @@ NX_EXTERNAL NXstatus CALLING_STYLE NXputslab(NXhandle handle, void* data, int s NX_EXTERNAL NXstatus CALLING_STYLE NXgetdataID(NXhandle handle, NXlink* pLink); NX_EXTERNAL NXstatus CALLING_STYLE NXmakelink(NXhandle handle, NXlink* pLink); +NX_EXTERNAL NXstatus CALLING_STYLE NXopensourcegroup(NXhandle handle); NX_EXTERNAL NXstatus CALLING_STYLE NXgetdata(NXhandle handle, void* data); NX_EXTERNAL NXstatus CALLING_STYLE NXgetinfo(NXhandle handle, int* rank, int dimension[], int* datatype); @@ -300,22 +318,64 @@ NX_EXTERNAL NXstatus CALLING_STYLE NXsameID(NXhandle handle, NXlink* pFirstID, NX_EXTERNAL NXstatus CALLING_STYLE NXinitgroupdir(NXhandle handle); NX_EXTERNAL NXstatus CALLING_STYLE NXinitattrdir(NXhandle handle); +NX_EXTERNAL NXstatus CALLING_STYLE NXsetnumberformat(NXhandle handle, + int type, char *format); NX_EXTERNAL NXstatus CALLING_STYLE NXmalloc(void** data, int rank, int dimensions[], int datatype); NX_EXTERNAL NXstatus CALLING_STYLE NXfree(void** data); /*----------------------------------------------------------------------- - A non Nexus standard function to set an error handler -*/ + NAPI internals +------------------------------------------------------------------------*/ NX_EXTERNAL void CALLING_STYLE NXMSetError(void *pData, void (*ErrFunc)(void *pD, char *text)); -NX_EXTERNAL void CALLING_STYLE NXNXNXReportError(void *pData,char *text); +extern void (*NXIReportError)(void *pData,char *text); +extern void *NXpData; + /* another special function for setting the default cache size for HDF-5 */ NX_EXTERNAL NXstatus CALLING_STYLE NXsetcache(long newVal); +/* + * We need to include CALLING_STYLE in the function pointer definition + * or else we get a type mismatch on Win32 + */ + typedef struct { + NXhandle *pNexusData; + NXstatus (CALLING_STYLE *nxclose)(NXhandle* pHandle); + NXstatus (CALLING_STYLE *nxflush)(NXhandle* pHandle); + NXstatus (CALLING_STYLE *nxmakegroup) (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); + NXstatus (CALLING_STYLE *nxopengroup) (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); + NXstatus (CALLING_STYLE *nxclosegroup)(NXhandle handle); + NXstatus (CALLING_STYLE *nxmakedata) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); + NXstatus (CALLING_STYLE *nxcompmakedata) (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[], int comp_typ, int bufsize[]); + NXstatus (CALLING_STYLE *nxcompress) (NXhandle handle, int compr_type); + NXstatus (CALLING_STYLE *nxopendata) (NXhandle handle, CONSTCHAR* label); + NXstatus (CALLING_STYLE *nxclosedata)(NXhandle handle); + NXstatus (CALLING_STYLE *nxputdata)(NXhandle handle, void* data); + NXstatus (CALLING_STYLE *nxputattr)(NXhandle handle, CONSTCHAR* name, void* data, int iDataLen, int iType); + NXstatus (CALLING_STYLE *nxputslab)(NXhandle handle, void* data, int start[], int size[]); + NXstatus (CALLING_STYLE *nxgetdataID)(NXhandle handle, NXlink* pLink); + NXstatus (CALLING_STYLE *nxmakelink)(NXhandle handle, NXlink* pLink); + NXstatus (CALLING_STYLE *nxgetdata)(NXhandle handle, void* data); + NXstatus (CALLING_STYLE *nxgetinfo)(NXhandle handle, int* rank, int dimension[], int* datatype); + NXstatus (CALLING_STYLE *nxgetnextentry)(NXhandle handle, NXname name, NXname nxclass, int* datatype); + NXstatus (CALLING_STYLE *nxgetslab)(NXhandle handle, void* data, int start[], int size[]); + NXstatus (CALLING_STYLE *nxgetnextattr)(NXhandle handle, NXname pName, int *iLength, int *iType); + NXstatus (CALLING_STYLE *nxgetattr)(NXhandle handle, char* name, void* data, int* iDataLen, int* iType); + NXstatus (CALLING_STYLE *nxgetattrinfo)(NXhandle handle, int* no_items); + NXstatus (CALLING_STYLE *nxgetgroupID)(NXhandle handle, NXlink* pLink); + NXstatus (CALLING_STYLE *nxgetgroupinfo)(NXhandle handle, int* no_items, NXname name, NXname nxclass); + NXstatus (CALLING_STYLE *nxsameID)(NXhandle handle, NXlink* pFirstID, NXlink* pSecondID); + NXstatus (CALLING_STYLE *nxinitgroupdir)(NXhandle handle); + NXstatus (CALLING_STYLE *nxinitattrdir)(NXhandle handle); + NXstatus (CALLING_STYLE *nxsetnumberformat)(NXhandle handle, + int type,char *format); + } NexusFunction, *pNexusFunction; + /*---------------------*/ + extern long nx_cacheSize; #ifdef __cplusplus } #endif /* __cplusplus */ diff --git a/napi.tex b/napi.tex deleted file mode 100644 index 74d08343..00000000 --- a/napi.tex +++ /dev/null @@ -1,1850 +0,0 @@ -% Copyleft (c) 1997 by Mark Koennecke at PSI, Switzerland. -% -% -% This software is distributed in the hope that it will be useful, -% but WITHOUT ANY WARRANTY; without even the implied warranty of -% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -% GNU General Public License for more details. -% -% You may already have a copy of the GNU General Public License; if -% not, write to the Free Software Foundation, Inc., 675 Mass Ave, -% Cambridge, MA 02139, USA. -% - -\documentclass[12pt]{article} -\usepackage[dvips] - -\setlength{\oddsidemargin}{-.1in} -\setlength{\evensidemargin}{0in} -\setlength{\topmargin}{0in} -\addtolength{\topmargin}{-\headheight} -\addtolength{\topmargin}{-\headsep} -\setlength{\textheight}{8.9in} -\setlength{\textwidth}{6.2in} -\setlength{\marginparwidth}{0.5in} - -\begin{document} -\title{The NeXus Application Programmer's Interface} - -\author{Mark K\"onnecke\\ - Labor f\"ur Neutronenstreuung\\ - Paul Scherrer Institut\\ - CH-5232 Villigen PSI\\ - Switzerland\\ - Mark.Koennecke@psi.ch \\ - Przemek K\l{}osowski\\ - U. of Maryland \& NIST \\ - przemek.klosowski@nist.gov -} - -} - -\maketitle -\tableofcontents - -\vskip.3in -\centerline{\large\bf Abstract} -\vskip.2in -\begin{center} -\parbox{.8\textwidth}{ - There is a proposed portable data exchange format for neutron and - X-ray scattering communities, NeXus (described in a separate - publication). The present document supplements the NeXus proposal, - by defining a simplified, NeXus-compliant programming interface for - reading and writing NeXus files. -} -\end{center} - -\section{Introduction} -\label{chap:intro} - -This file defines an Application Programmer's Interface (API) to HDF -library as used for the NeXus data format. It encapsulates a subset of -HDF and provides some helper routines to simplify creating and reading -NeXus data files. - -The API is designed to be modal; there is a hidden state that -determines which groups and datasets (Vgroups and SDSes) are open at -any given moment, and subsequent operations are implicitly performed -on these entities. This cuts down the number of parameters to pass -around in API calls, at the cost of forcing certain pre-approved {\em -mode d'emploi}. This mode d'emploi will be familiar to most: it is very -similar to navigating a directory hierarchy. In our case HDF--VGroups are -the directories, which can hold other directories and data items which are -restricted to being HDF--scientific data sets (SDS). - -The API comprises the following functional groups: - -\begin{enumerate} -\item General initialization and shutdown: opening and closing the file, - creating or opening an existing group or dataset, and closing them. -\item Reading and writing data and attributes to previously opened datasets. -\item Routines to obtain meta-data and to iterate over component datasets and attributes. -\item Handling of linking and group hierarchy. -\end{enumerate} - - - -\section{Implementation} - -\subsection{Data Structures} -The approach used in this version is to maintain a datastructure for each -open file. This datastructure will hold a stack of Vgroups traversed and -will thus allow stepping back and forth in the NeXus file structure. The -stack is implemented using an array. The datastructure looks like this: -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap1} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ typedef struct __NexusFile {@\\ -\mbox{}\verb@ int iNXID;@\\ -\mbox{}\verb@ int32 iVID;@\\ -\mbox{}\verb@ int32 iSID;@\\ -\mbox{}\verb@ int32 iCurrentVG;@\\ -\mbox{}\verb@ int32 iCurrentSDS;@\\ -\mbox{}\verb@ int32 iStack[NXMAXSTACK];@\\ -\mbox{}\verb@ int iStackPtr; @\\ -\mbox{}\verb@ int iNDir;@\\ -\mbox{}\verb@ int iCurDir;@\\ -\mbox{}\verb@ int *iRefDir;@\\ -\mbox{}\verb@ int *iTagDir;@\\ -\mbox{}\verb@ } NexusFile, *pNexusFile;@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -The fields in more detail: \begin{itemize} -\item iNXID is a test value against memory corruption. -\item iVID is the file ID to use for the Vgroup interface. -\item iSID is the file ID to use for the SDS interface. -\item iCurrentVG is the ID of the current open Vgroup. Is 0, if there is - no Vgroup open. -\item iCurrentSDS is the ID of the current open SDS. Is 0, if there is - no SDS open. -\item iStack is the stack array. -\item iStackPtr is the pointer to the current Vgroup in iStack. -\item iNDir, iCurDir, iRefDir, iTagDir are data fields used during an -directory search with NXgetnextentry. They are: -\begin{itemize} -\item iNDir: number of directory entries. -\item iCurDir current directory entry. -\item iRefDir array of reference numbers. -\item iTagDir array of tag numbers. - -\end{itemize} -\end{itemize} - -The other datastructure used is NXlink. It encapsulates all information -necessary to do a link between Vgroups and SDS's. This is easy: - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap2} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ typedef struct {@\\ -\mbox{}\verb@ int32 iTag;@\\ -\mbox{}\verb@ int32 iRef;@\\ -\mbox{}\verb@ } NXlink;@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -Before diving into code, it may be helpful to highlight a few pecularities -of the HDF interface which help confuse the code. The first is, that there -is no single ID to refer to a given file. The Vgroup interface and the SDS -interface use two different ID's which have to be initialised at file -opening and used apropriatetly. - -The other feature is the plethora of integer ID's associated with each -HDF--object. First there is something called a reference ID which seems to -be an ID which identifies an object within an HDF file. Coming with it there -is a tag, which denotes the type of the object. When things need to be done -to an object, HDF requires to attach or open the object. These calls usually -return another ID which can than be used furtheron. This becomes invalid -once you close the object again. So much bookeeping is needed to keep track -of all these ID's. \label{ididid} - - - -\subsection{General initialization and shutdown} -\label{ss:gen} - - -The routines in this group are for opening and closing the NeXus/HDF file, -creating or opening an existing group or dataset, and closing them. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap3} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@NXhandle NXopen(char * filename, NXaccess access_method);@\\ -\mbox{}\verb@NXstatus NXclose(NXhandle fileid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@NXstatus NXmakegroup (NXhandle fileid, char* Vgroup, char* NXclass);@\\ -\mbox{}\verb@NXstatus NXopengroup (NXhandle fileid, char* Vgroup, char* NXclass);@\\ -\mbox{}\verb@NXstatus NXclosegroup(NXhandle fileid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@NXstatus NXmakedata (NXhandle fileid, char* label, int datatype, int rank, int dim[]);@\\ -\mbox{}\verb@NXstatus NXopendata (NXhandle fileid, char* label);@\\ -\mbox{}\verb@NXstatus NXclosedata(NXhandle fileid);@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXopen} -NXopen opens the HDF--file filename and creates and initialises a NexusFile -structure. The returned handle is actually the pointer to this structure. -This danger of this aproach is, that somebody might try arithemetic on the -handle and thereby corrupt the system. In order to test for this the -NexusFile structure contains the NXID field which can be checked against a -predefined value. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap4} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXhandle NXopen(char *filename, NXaccess am)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pNew = NULL;@\\ -\mbox{}\verb@ char pBuffer[512];@\\ -\mbox{}\verb@ int iRet;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* get memory */@\\ -\mbox{}\verb@ pNew = (pNexusFile)malloc(sizeof(NexusFile));@\\ -\mbox{}\verb@ if(!pNew)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData, "ERROR: no memory to create File datastructure");@\\ -\mbox{}\verb@ return NULL;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ memset(pNew,0,sizeof(NexusFile));@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* start SDS interface */@\\ -\mbox{}\verb@ pNew->iSID = SDstart(filename,am);@\\ -\mbox{}\verb@ if(pNew->iSID <= 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: cannot open file: %s",filename);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ free(pNew);@\\ -\mbox{}\verb@ return NULL;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* otherwise we try to create the file two times which makes HDF@\\ -\mbox{}\verb@ Trow up on us.@\\ -\mbox{}\verb@ */@\\ -\mbox{}\verb@ if(am == NXACC_CREATE)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ am = NXACC_RDWR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* start Vgroup API */@\\ -\mbox{}\verb@ pNew->iVID = Hopen(filename,am,100);@\\ -\mbox{}\verb@ if(pNew->iVID <= 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: cannot open file: %s",filename);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ free(pNew);@\\ -\mbox{}\verb@ return NULL;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ iRet = Vstart(pNew->iVID);@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot initalise Vgroup interface");@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ pNew->iNXID = NXSIGNATURE;@\\ -\mbox{}\verb@ pNew->iStack[0] = 0; /* root! */@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ return (NXhandle)pNew; @\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXclose} -NXclose closes an Nexus file and deletes all associated datastructures from -memory. The handle fileid will no longer be valid after this. -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap5} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXclose(NXhandle fid)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile = NULL;@\\ -\mbox{}\verb@ int iRet; @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* close links into vGroups or SDS */@\\ -\mbox{}\verb@ if(pFile->iCurrentVG != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ Vdetach(pFile->iCurrentVG);@\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDendaccess(pFile->iCurrentSDS);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: ending access to SDS");@\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* close the SDS and Vgroup API's */@\\ -\mbox{}\verb@ Vend(pFile->iVID);@\\ -\mbox{}\verb@ iRet = SDend(pFile->iSID);@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot close SDS interface");@\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ iRet = Hclose(pFile->iVID);@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot close HDF file");@\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* release memory */@\\ -\mbox{}\verb@ NXIKillDir(pFile);@\\ -\mbox{}\verb@ free(pFile);@\\ -\mbox{}\verb@ return NX_OK; @\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXmakegroup} -NXmakegroup creates a new Vgroup at the current level in the Vgroup -hierarchy. The new Vgroup will have the name Vgroup and have the class -descriptor NXclass. This call does not open the new group automatically. -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap6} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXmakegroup(NXhandle fid, char *name, char *class)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int32 iNew, iRet;@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ pFile = NXIassert(fid); @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* create and configure the group */@\\ -\mbox{}\verb@ iNew = Vattach(pFile->iVID,-1,"w"); @\\ -\mbox{}\verb@ if(iNew < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF could not create Vgroup");@\\ -\mbox{}\verb@ return NX_ERROR; @\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ Vsetname(iNew,name);@\\ -\mbox{}\verb@ Vsetclass(iNew,class);@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* insert it into the hierarchy, when apropriate */@\\ -\mbox{}\verb@ if(pFile->iCurrentVG != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = Vinsert(pFile->iCurrentVG,iNew);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ Vdetach(iNew);@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF failed to insert Vgroup");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXopengroup} -NXopengroup opens an existing Vgroup for writing and reading data to it. -This routine maintains the Vgroup stack. There are several possible -situations. The first is that we are at root level (iCurrentVG = 0). The -vGroup must be found and attatched to. Than the Stack has to be incremented. -The next situation is, that we are already in a Vgroup. Than we have to find -the new Vgroup, detach the current Vgroup and attach to the new one, thereby -incrementing the stack. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap7} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*------------------------------------------------------------------------*/@\\ -\mbox{}\verb@ NXstatus NXopengroup(NXhandle fid, char *name, char *class)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int32 iNew, iRef;@\\ -\mbox{}\verb@ char pBuffer[256];@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ iRef = NXIFindVgroup(pFile,name,class);@\\ -\mbox{}\verb@ if(iRef < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: Vgroup %s, class %s NOT found",name,class);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* are we at root level ? */@\\ -\mbox{}\verb@ if(pFile->iCurrentVG == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pFile->iCurrentVG = Vattach(pFile->iVID,iRef,"w");@\\ -\mbox{}\verb@ if(pFile->iCurrentVG < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: cannot attach to vGroup %s",name);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ pFile->iStackPtr++;@\\ -\mbox{}\verb@ pFile->iStack[pFile->iStackPtr] = iRef;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ Vdetach(pFile->iCurrentVG);@\\ -\mbox{}\verb@ pFile->iStackPtr++;@\\ -\mbox{}\verb@ pFile->iStack[pFile->iStackPtr] = iRef;@\\ -\mbox{}\verb@ pFile->iCurrentVG = Vattach(pFile->iVID,@\\ -\mbox{}\verb@ pFile->iStack[pFile->iStackPtr],@\\ -\mbox{}\verb@ "w");@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ NXIKillDir(pFile);@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXclosegroup} -NXclosegroup closes an open Vgroup and travels one back in the Vgroup -hierarchy. The usual hassle with the tons of different indices again. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap8} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXclosegroup(NXhandle fid)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* first catch the trivial case: we are at root and cannot get @\\ -\mbox{}\verb@ deeper into a negative directory hierarchy (anti-directory)@\\ -\mbox{}\verb@ */@\\ -\mbox{}\verb@ if(pFile->iCurrentVG = 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIKillDir(pFile);@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else /* Sighhh. Some work to do */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* close the current VG and decrement stack */@\\ -\mbox{}\verb@ Vdetach(pFile->iCurrentVG);@\\ -\mbox{}\verb@ pFile->iStackPtr--;@\\ -\mbox{}\verb@ if(pFile->iStackPtr <= 0) /* we hit root */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pFile->iStackPtr = 0;@\\ -\mbox{}\verb@ pFile->iCurrentVG = 0;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* attach to the lower Vgroup */@\\ -\mbox{}\verb@ pFile->iCurrentVG = Vattach(pFile->iVID,@\\ -\mbox{}\verb@ pFile->iStack[pFile->iStackPtr],@\\ -\mbox{}\verb@ "w");@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ NXIKillDir(pFile);@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXmakedata} -NXmakedata creates a new scientific datset. As argument it takes the usual filehandle, -Than there is an integer denoting the datatype. This needs to be one of the -HDF defined type identifiers. Commonly used types are: DFNT\_FLOAT for 32 bit -floats, DFNT\_INT32 for 32-bit integers, DFNT\_UINT8 for unsigned bytes (or -characters). rank is the dimensionality of the data. The parameter dims is -an integer array which has rank values. Each value denotes the length of the -data in the dimensions. Note that this function does not open a dataset. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap9} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXmakedata(NXhandle fid, char *name, int datatype, int rank, @\\ -\mbox{}\verb@ int dimensions[])@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int32 iNew;@\\ -\mbox{}\verb@ char pBuffer[256];@\\ -\mbox{}\verb@ int i, iRet;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* do some argument checking */@\\ -\mbox{}\verb@ if( (datatype != DFNT_FLOAT32) && (datatype != DFNT_FLOAT64) &&@\\ -\mbox{}\verb@ (datatype != DFNT_INT8) && (datatype != DFNT_UINT8) &&@\\ -\mbox{}\verb@ (datatype != DFNT_INT16) && (datatype != DFNT_UINT16) &&@\\ -\mbox{}\verb@ (datatype != DFNT_INT32) && (datatype != DFNT_UINT32))@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: unknown datatype specified for SDS %s",@\\ -\mbox{}\verb@ name);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(rank <= 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: invalid rank specified for SDS %s",@\\ -\mbox{}\verb@ name);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ for(i = 0; i < rank; i++)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ if(dimensions[i] <= 0 )@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,@\\ -\mbox{}\verb@ "ERROR: invalid dimension %d, value %d given for SDS %s",@\\ -\mbox{}\verb@ i,dimensions[i], name);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* behave nicely, if there is still an SDS open */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ SDendaccess(pFile->iCurrentSDS);@\\ -\mbox{}\verb@ pFile->iCurrentSDS = 0;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* dataset creation */@\\ -\mbox{}\verb@ iNew = SDcreate(pFile->iSID,name,datatype,rank,dimensions);@\\ -\mbox{}\verb@ if(iNew < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: cannot create SDS %s, check argumenst",@\\ -\mbox{}\verb@ name);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR; @\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ /* link into Vgroup, if in one */@\\ -\mbox{}\verb@ if(pFile->iCurrentVG != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = Vaddtagref(pFile->iCurrentVG,DFTAG_SDG,SDidtoref(iNew));@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ iRet = SDendaccess(iNew);@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot end access to SDS");@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXopendata} -NXopendata opens a scientific data set for further manipulation, i.e. reading -and writing of data or getting information about it. The scientific dataset -must exist. -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap10} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXopendata(NXhandle fid, char *name)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int32 iNew; @\\ -\mbox{}\verb@ char pBuffer[256];@\\ -\mbox{}\verb@ int iRet;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* first find the reference number of the SDS */@\\ -\mbox{}\verb@ iNew = NXIFindSDS(fid,name);@\\ -\mbox{}\verb@ if(iNew < 0) @\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: SDS %s not found at this level",name);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* be nice: properly close the old open SDS silently if there is@\\ -\mbox{}\verb@ still an SDS open.@\\ -\mbox{}\verb@ */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDendaccess(pFile->iCurrentSDS);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = 1;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot end access to SDS");@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* clear pending attribute directories first */@\\ -\mbox{}\verb@ NXIKillDir(pFile);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* open the SDS */@\\ -\mbox{}\verb@ iNew = SDreftoindex(pFile->iSID, iNew);@\\ -\mbox{}\verb@ pFile->iCurrentSDS = SDselect(pFile->iSID,iNew);@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF error opening SDS");@\\ -\mbox{}\verb@ pFile->iCurrentSDS = 0;@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXclosedata} -NXclosedata ends the access to the currently active scientific dataset. -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap11} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXclosedata(NXhandle fid)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int iRet;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDendaccess(pFile->iCurrentSDS);@\\ -\mbox{}\verb@ pFile->iCurrentSDS = 0;@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot end access to SDS");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open --> nothing to do");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ NXIKillDir(pFile); /* for attribute data */@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsection{Reading and writing} -\label{ss:rw} - -Routines to read and write data and attributes to previously opened datasets: - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap12} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@NXstatus NXgetdata(NXhandle fileid, void* data);@\\ -\mbox{}\verb@NXstatus NXgetslab(NXhandle fileid, void* data, int start[], int size[]);@\\ -\mbox{}\verb@NXstatus NXgetattr(NXhandle fileid, char* name, char* data, int datalen);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@NXstatus NXputdata(NXhandle fileid, void* data);@\\ -\mbox{}\verb@NXstatus NXputslab(NXhandle fileid, void* data, int start[], int size[]);@\\ -\mbox{}\verb@NXstatus NXputattr(NXhandle fileid, char* name, char* data, int datalen);@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -Please note, that all data reading and writing routines require that the -scientific dataset has been opened beforehand with NXopenadata. - -\subsubsection{NXgetdata} -NXgetdata reads data from the currently open scientific data set into -data. Please note, that memory overwrite occurs if the caller has not -allocated enough memory to hold all the data available. There are functions -in the section \ref{ss:meta} which allow to inquire the data size first. - -Note as well that the scientific dataset must have been opened with -NXopendata before this function can succeed. Before it can do its job, -NXgetdata has to get dimension information first. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap13} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXgetdata(NXhandle fid, void *data)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int32 iStart[MAX_VAR_DIMS], iEnd[MAX_VAR_DIMS];@\\ -\mbox{}\verb@ NXname pBuffer;@\\ -\mbox{}\verb@ int32 iRank, iAtt, iType;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* check if there is an SDS open */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* first read dimension information */@\\ -\mbox{}\verb@ memset(iStart,0,MAX_VAR_DIMS*sizeof(int32));@\\ -\mbox{}\verb@ SDgetinfo(pFile->iCurrentSDS,pBuffer,&iRank,iEnd,&iType,&iAtt);@\\ -\mbox{}\verb@ /* actually read */@\\ -\mbox{}\verb@ SDreaddata(pFile->iCurrentSDS,iStart,NULL,iEnd,data);@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXgetslab} -NXgetslab reads a subset of the data in the current scientific data set. -The start dimensions to read from are specified in iStart, the end in iEnd. -The caller is responsable for allocation enough memory for data. -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap14} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXgetslab(NXhandle fid, void *data, int iStart[], int iEnd[])@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* check if there is an SDS open */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* actually read */@\\ -\mbox{}\verb@ SDreaddata(pFile->iCurrentSDS,iStart,NULL,iEnd,data);@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXgetattr} -HDF has the concept of attributes. This is additional data which goes with -usually an SDS. Such attributes are used to denotes axis, units etc. The -other class of attributes are global attributes. This function reads such -attributes. If an SDS is open, it reads the attributes associated with the SDS, else -the it tries to find a global attribute. The data read is transfered to -data, but maximum datalen bytes. The caller is responsible for allocating at -least datalen bytes for data. In order to enable this scheme, NXgetattr -has to read the first into an internal temporary buffer before it copies the -data to the datat buffer provided. And discards with the temporary buffer. -Note that searching for attributes is handled differently if attributes at -global level are searched compared to searching attributes in an SDS. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap15} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXgetattr(NXhandle fid, char *name, char *data, int datalen)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int32 iNew;@\\ -\mbox{}\verb@ void *pData = NULL;@\\ -\mbox{}\verb@ int32 iLen, iType, iRet;@\\ -\mbox{}\verb@ char pBuffer[256];@\\ -\mbox{}\verb@ NXname pNam; @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* find attribute */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* SDS attribute */@\\ -\mbox{}\verb@ iNew = SDfindattr(pFile->iCurrentSDS,name);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* global attribute */@\\ -\mbox{}\verb@ iNew = SDfindattr(pFile->iSID,name);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(iNew < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: attribute %s not found",name);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* get more info, allocate temporary data space */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDattrinfo(pFile->iCurrentSDS,iNew,pNam,&iType,&iLen);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDattrinfo(pFile->iSID,iNew,pNam,&iType,&iLen);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: HDF could not read attribute info");@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ iLen = iLen*DFKNTsize(iType); @\\ -\mbox{}\verb@ pData = (void *)malloc(iLen);@\\ -\mbox{}\verb@ if(!pData)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: allocating memory in NXgetattr");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ memset(pData,0,iLen);@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* finally read the data */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDreadattr(pFile->iCurrentSDS,iNew,pData);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDreadattr(pFile->iSID,iNew,pData);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pBuffer,"ERROR: HDF could not read attribute data");@\\ -\mbox{}\verb@ NXIReportError(NXpData,pBuffer);@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* copy data to caller */@\\ -\mbox{}\verb@ memset(data,0,datalen);@\\ -\mbox{}\verb@ if(datalen < iLen)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iLen = datalen - 1;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ memcpy(data,pData,iLen);@\\ -\mbox{}\verb@ free(pData);@\\ -\mbox{}\verb@ return NX_OK; @\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXputdata} -NXputdata copies data into the currently open scientific data set in the -HDF file. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap16} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXputdata(NXhandle fid, void *data)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int32 iStart[MAX_VAR_DIMS], iEnd[MAX_VAR_DIMS], iStride[MAX_VAR_DIMS];@\\ -\mbox{}\verb@ NXname pBuffer;@\\ -\mbox{}\verb@ int32 iRank, iAtt, iType, iRet, i;@\\ -\mbox{}\verb@ char pError[512];@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* check if there is an SDS open */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* first read dimension information */@\\ -\mbox{}\verb@ memset(iStart,0,MAX_VAR_DIMS*sizeof(int32));@\\ -\mbox{}\verb@ SDgetinfo(pFile->iCurrentSDS,pBuffer,&iRank,iEnd,&iType,&iAtt);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* initialise stride to 1 */@\\ -\mbox{}\verb@ for(i = 0; i < iRank; i++)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iStride[i] = 1;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* actually write */@\\ -\mbox{}\verb@ iRet = SDwritedata(pFile->iCurrentSDS,iStart,iStride,iEnd,data);@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sprintf(pError,"ERROR: failure to write data to %s",pBuffer);@\\ -\mbox{}\verb@ NXIReportError(NXpData,pError);@\\ -\mbox{}\verb@ return NX_ERROR; @\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXputslab} -NXputslab writes an subset of data as specified by iStart to iEnd into the -currently open SDS. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap17} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXputslab(NXhandle fid, void *data, int iStart[], int iEnd[])@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int iRet;@\\ -\mbox{}\verb@ int iStride[MAX_VAR_DIMS], i;@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* check if there is an SDS open */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* initialise stride to 1 */@\\ -\mbox{}\verb@ for(i = 0; i < MAX_VAR_DIMS; i++)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iStride[i] = 1;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* actually write */@\\ -\mbox{}\verb@ iRet = SDwritedata(pFile->iCurrentSDS,iStart,iStride,iEnd,data);@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: writing slab failed");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXputattr} -Nxputattr puts an attribute into an Nexus file.If an SDS is open, the SDS -will get the attribute. If not, a global attribute will be generated. -Attributes are name = value pairs. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap18} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXputattr(NXhandle fid, char *name, char *data, int datalen)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int iRet;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS != 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* SDS attribute */@\\ -\mbox{}\verb@ iRet = SDsetattr(pFile->iCurrentSDS,name,DFNT_UINT8,@\\ -\mbox{}\verb@ datalen,data);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* global attribute */@\\ -\mbox{}\verb@ iRet = SDsetattr(pFile->iSID,name,DFNT_UINT8,@\\ -\mbox{}\verb@ datalen, data);@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDf failed to store attribute ");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsection{Meta-data} -\label{ss:meta} - -Routines to obtain meta-data and to iterate over component datasets and attributes. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap19} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@NXstatus NXgetinfo (NXhandle fileid, int* rank, int dimension[], int* datatype);@\\ -\mbox{}\verb@NXstatus NXgetnextentry (NXhandle fileid, NXname name, NXname class, int* datatype);@\\ -\mbox{}\verb@NXstatus NXgetnextattr(NXhandle fileid, NXname pName, int *iLength, int *iType);@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXgetinfo} -NXgetinfo gets information about an SDS. rank is the dimesionality of the -data, dimension will contain the size of the data in each dimension and -datatype results to one of the HDF--datatypes. The SDS has to be open in -order for this routine to work. -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap20} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXgetinfo(NXhandle fid, int *rank,int dimension[], int *iType)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ NXname pBuffer;@\\ -\mbox{}\verb@ int32 iAtt;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* check if there is an SDS open */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: no SDS open");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* read information */@\\ -\mbox{}\verb@ SDgetinfo(pFile->iCurrentSDS,pBuffer,rank,dimension,iType,&iAtt);@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXgetnextentry} -NXgetnextentry implements a directory search facility on the current Vgroup -level. The first call will initialize Vgroup searching facilities and return -information on the first data item in the list. Subsequent calls will yield -information about the next item in the Vgroup. If the end of the list is -reached, NXgetentry will return NX\_EOD. Before, the usual NX\_ERROR or NX\_OK -are returned. Information returned is different for each type of data. For -Vgroups the name and class of the Vgroup will be returned, iType will be 0. -For scientific data sets, the name field will be the name, class will be SDS -and iType will denote the number type of the scientific data set. For types -not known to Nexus (but to HDF) both name and class will be set to -"UNKNOWN". - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap21} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ int NXgetnextentry(NXhandle fid, NXname name, NXname class, int *datatype)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int iRet; @\\ -\mbox{}\verb@ int32 iTemp, iD1, iD2, iA;@\\ -\mbox{}\verb@ int32 iDim[MAX_VAR_DIMS];@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* first case to check for: no directory entry */@\\ -\mbox{}\verb@ if(pFile->iRefDir == NULL)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = NXIInitDir(pFile);@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData, @\\ -\mbox{}\verb@ "ERROR: no memory to store directory info");@\\ -\mbox{}\verb@ return -1;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* next case: end of directory */@\\ -\mbox{}\verb@ if(pFile->iCurDir >= pFile->iNDir)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIKillDir(pFile);@\\ -\mbox{}\verb@ return NX_EOD;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* next case: we have data! suppy it and increment counter */@\\ -\mbox{}\verb@ if(pFile->iCurrentVG == 0) /* root level */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iTemp = Vattach(pFile->iVID,pFile->iRefDir[pFile->iCurDir],@\\ -\mbox{}\verb@ "r");@\\ -\mbox{}\verb@ if(iTemp < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot attach to Vgroup");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ Vgetname(iTemp,name);@\\ -\mbox{}\verb@ Vgetclass(iTemp,class);@\\ -\mbox{}\verb@ *datatype = DFTAG_VG;@\\ -\mbox{}\verb@ pFile->iCurDir++;@\\ -\mbox{}\verb@ Vdetach(iTemp);@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else /* in Vgroup */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ if(pFile->iTagDir[pFile->iCurDir] == DFTAG_VG) /* Vgroup */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iTemp = Vattach(pFile->iVID,pFile->iRefDir[pFile->iCurDir],@\\ -\mbox{}\verb@ "r");@\\ -\mbox{}\verb@ if(iTemp < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot attach to Vgroup");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ Vgetname(iTemp,name);@\\ -\mbox{}\verb@ Vgetclass(iTemp,class);@\\ -\mbox{}\verb@ *datatype = DFTAG_VG;@\\ -\mbox{}\verb@ pFile->iCurDir++;@\\ -\mbox{}\verb@ Vdetach(iTemp);@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else if( (pFile->iTagDir[pFile->iCurDir] == DFTAG_SDG) ||@\\ -\mbox{}\verb@ (pFile->iTagDir[pFile->iCurDir] == DFTAG_NDG) )@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iTemp = SDreftoindex(pFile->iSID, @\\ -\mbox{}\verb@ pFile->iRefDir[pFile->iCurDir]);@\\ -\mbox{}\verb@ iTemp = SDselect(pFile->iSID,iTemp);@\\ -\mbox{}\verb@ SDgetinfo(iTemp,name,&iA,iDim,&iD1, &iD2);@\\ -\mbox{}\verb@ strcpy(class,"SDS");@\\ -\mbox{}\verb@ *datatype = iD1;@\\ -\mbox{}\verb@ SDendaccess(iTemp);@\\ -\mbox{}\verb@ pFile->iCurDir++;@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else /* unidentified */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ strcpy(name,"UNKNOWN");@\\ -\mbox{}\verb@ strcpy(class,"UNKNOWN");@\\ -\mbox{}\verb@ pFile->iCurDir++;@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ return NX_ERROR; /* not reached */@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXgetnextattr} -NXgetnextattr works very much like NXgetnextentry except, that it works on -SDS attributes and not on Vgroup entries. This function allows to scan the -names of attributes available. iLength will be filled with the length of the -attributes data in byte. iType will be filled with the HDF type of the -attribute. Be warned: this routine returns global attributes when no SDS is -currently open. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap22} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\ -\mbox{}\verb@ NXstatus NXgetnextattr(NXhandle fileid, NXname pName, @\\ -\mbox{}\verb@ int *iLength, int *iType)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ int iRet;@\\ -\mbox{}\verb@ int32 iPType, iCount;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fileid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* first check if we have to start a new attribute search */@\\ -\mbox{}\verb@ if(pFile->iNDir == 0) @\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = NXIInitAttDir(pFile);@\\ -\mbox{}\verb@ if(iRet == NX_ERROR)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* are we done ? */@\\ -\mbox{}\verb@ if(pFile->iCurDir >= pFile->iNDir)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIKillDir(pFile);@\\ -\mbox{}\verb@ return NX_EOD;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* well, there must be data to copy */@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS == 0) /* global attribute */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDattrinfo(pFile->iSID,pFile->iCurDir, pName, &iPType,&iCount); @\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDattrinfo(pFile->iCurrentSDS,pFile->iCurDir,@\\ -\mbox{}\verb@ pName, &iPType,&iCount);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot read attribute info");@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ *iLength = iCount*DFKNTsize(iPType);@\\ -\mbox{}\verb@ *iType = iPType;@\\ -\mbox{}\verb@ pFile->iCurDir++;@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsection{ Handling of linking and group hierarchy} -\label{ss:link} - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap23} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@NXlink NXgetgroupID(NXhandle fileid);@\\ -\mbox{}\verb@NXlink NXgetdataID(NXhandle fileid);@\\ -\mbox{}\verb@NXstatus NXmakelink(NXhandle fileid, NXlink link);@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{ NXgetgroupID} -NXgetgroupID retrieves the ID and tag of the currently open -Vgroup in an NXlink strcuture. In case of an error the iTag field of this -structure will contain NX\_ERROR. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap24} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXlink NXgetgroupID(NXhandle fileid)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ NXlink sRes;@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ pFile = NXIassert(fileid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ if(pFile->iCurrentVG == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sRes.iTag = NX_ERROR;@\\ -\mbox{}\verb@ return sRes;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sRes.iTag = DFTAG_VG;@\\ -\mbox{}\verb@ sRes.iRef = pFile->iCurrentVG;@\\ -\mbox{}\verb@ return sRes;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ /* not reached */@\\ -\mbox{}\verb@ sRes.iTag = NX_ERROR;@\\ -\mbox{}\verb@ return sRes;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{NXgetdataID} -NXgetdataID retrieves the tag and reference number of the current data -object. Returns NX\_ERROR if none is open. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap25} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXlink NXgetdataID(NXhandle fid)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@ NXlink sRes;@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ if(pFile->iCurrentSDS == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sRes.iTag = NX_ERROR;@\\ -\mbox{}\verb@ return sRes;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ sRes.iTag = DFTAG_SDS;@\\ -\mbox{}\verb@ sRes.iRef = SDidtoref(pFile->iCurrentSDS);@\\ -\mbox{}\verb@ return sRes;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ sRes.iTag = NX_ERROR;@\\ -\mbox{}\verb@ return sRes; /* not reached */@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{ NXlink} -NXlink links a Vgroup or SDS into a Vgroup. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap26} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ NXstatus NXmakelink(NXhandle fid, NXlink sLink)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pFile;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ if(pFile->iCurrentVG == 0) /* root level, can not link here */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ if(sLink.iTag == DFTAG_VG)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ Vinsert(pFile->iCurrentVG,sLink.iRef);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else @\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ Vaddtagref(pFile->iCurrentVG, sLink.iTag,sLink.iRef);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsection{Internal routines} -There are a couple of internal Nexus API routines which are declared -static and are not visible outside of the module. First a few -defines. - - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap27} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@#include @\\ -\mbox{}\verb@#include @\\ -\mbox{}\verb@#include @\\ -\mbox{}\verb@#include "fortify.h"@\\ -\mbox{}\verb@#include "napi.h"@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@#define NXMAXSTACK 50@\\ -\mbox{}\verb@#define NXSIGNATURE 959697@\\ -\mbox{}\verb@@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -MAXSTACK denotes the maximum depth of Vgroup stacking permissible. If there -are problems, feel free to increase this value and recompile. 50 is probably -fairly generous. - -NXSIGNATURE is just the signature which the Nexus API will check for on -handles in order to prevent against tampering with the handles. - -NXMAXNAME is the number of characters permitted for names and Vgroup names. - -The internal function NXIassert will convert a filehandle to a pointer -to a NexusFile datastructure. Furthermore, it will check the signature and -throw an assertion, when the signature does not match. - - -\subsubsection{NX error handling} - -As each piece of non trivial software the Nexus API needs a error handling -policy. The policy implemented is as follows: The NX routines terminate when -an invalid NXhandle has been specified. This is a serious programmer error. -In any other case the NX routines are meant to complain, recover and present -an NX-ERROR return to the higher level code. That code is than responsible -to deal with the problem. The problem left is error reporting. This is done -througout the code by a call to NXIReportError. This function takes as first -parameter a pointer to void and as next parameter the string with the -complaint. The default implementation of NXIReportError will print to -stdout. However, there are environments where this strategy is not feasible -because stdout is supported only in a very strange way. Think about -operating system like MS-Windows, MAC-OS (going to die anyway) or other -windowing systems. In order to cater for this there is an inofficial support -function which allows to set both a pointer to a datastructure and a new -function for error reporting. This is called NXMSetError. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap28} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*---------------------------------------------------------------------*/@\\ -\mbox{}\verb@ static void NXNXNXReportError(void *pData, char *string)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ printf("%s \n",string);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@/*---------------------------------------------------------------------*/@\\ -\mbox{}\verb@ static void *NXpData = NULL;@\\ -\mbox{}\verb@ static void (*NXIReportError)(void *pData, char *string) =@\\ -\mbox{}\verb@ NXNXNXReportError;@\\ -\mbox{}\verb@/*---------------------------------------------------------------------*/@\\ -\mbox{}\verb@ void NXMSetError(void *pData, void (*NewError)(void *pD, char *text))@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXpData = pData;@\\ -\mbox{}\verb@ NXIReportError = NewError;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap29} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*--------------------------------------------------------------------*/@\\ -\mbox{}\verb@ static pNexusFile NXIassert(NXhandle fid)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile pRes;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ assert(fid);@\\ -\mbox{}\verb@ pRes = (pNexusFile)fid;@\\ -\mbox{}\verb@ assert(pRes->iNXID == NXSIGNATURE);@\\ -\mbox{}\verb@ return pRes;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{ Object finding dunctions} - -Routines for finding objects in an HDF file have to cope with two quirks in -the HDF interface. The first is that the root level is no Vgroup. This -implies that the root level is searched for objects using different routines -than searching for objects in a Vgroup. The last one uses, of course, Vgroup -interface routines. - -Finding routines have to cope with the plethora of different integer -ID's for any given HDF object. See \ref{ididid} for more details. - - -NXIFindVgroup searches the current Vgroup level in the file for the -occurence of a Vgroup with a specified name and of a specified class. If no -suitable Vgroup can be found NIXFinfVgroup returns -1, else the ID of the -Vgroup. -NXIFindVgroup has to cope with the plethora of different integer -ID's for any give Vgroup. There is the Vgroup ID, than there is the -reference number which can be obtained by Vgettagref and which can refer to -any object in the HDF file. Additionally there is a Tag which denotes the -type of the object. - - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap30} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*----------------------------------------------------------------------*/@\\ -\mbox{}\verb@ static int32 NXIFindVgroup(pNexusFile pFile, char *name, char *class)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ int32 iNew, iRef, iTag;@\\ -\mbox{}\verb@ int iN, i;@\\ -\mbox{}\verb@ int32 *pArray = NULL;@\\ -\mbox{}\verb@ NXname pText;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ assert(pFile);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ if(pFile->iCurrentVG == 0) /* root level */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* get the number and ID's of all lone Vgroups in the file */@\\ -\mbox{}\verb@ iN = Vlone(pFile->iVID,NULL,0);@\\ -\mbox{}\verb@ pArray = (int32 *)malloc(iN*sizeof(int32));@\\ -\mbox{}\verb@ if(!pArray)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: out of memory in NXIFindVgroup");@\\ -\mbox{}\verb@ return -1;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ Vlone(pFile->iVID,pArray,iN);@\\ -\mbox{}\verb@ @\\ -\mbox{}\verb@ /* loop and check */@\\ -\mbox{}\verb@ for(i = 0; i < iN; i++)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iNew = Vattach(pFile->iVID,pArray[i],"r");@\\ -\mbox{}\verb@ Vgetname(iNew, pText);@\\ -\mbox{}\verb@ if(strcmp(pText,name) == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ Vgetclass(iNew,pText);@\\ -\mbox{}\verb@ if(strcmp(pText,class) == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* found !*/@\\ -\mbox{}\verb@ Vdetach(iNew);@\\ -\mbox{}\verb@ iNew = pArray[i];@\\ -\mbox{}\verb@ free(pArray);@\\ -\mbox{}\verb@ return iNew;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ Vdetach(iNew);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ /* nothing found */@\\ -\mbox{}\verb@ free(pArray); @\\ -\mbox{}\verb@ return -1; @\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@ else /* case in Vgroup */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iN = Vntagrefs(pFile->iCurrentVG);@\\ -\mbox{}\verb@ for(i = 0; i < iN; i++)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ Vgettagref(pFile->iCurrentVG,i,&iTag, &iRef);@\\ -\mbox{}\verb@ if(iTag == DFTAG_VG)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iNew = Vattach(pFile->iVID,iRef,"r");@\\ -\mbox{}\verb@ Vgetname(iNew, pText);@\\ -\mbox{}\verb@ if(strcmp(pText,name) == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ Vgetclass(iNew,pText);@\\ -\mbox{}\verb@ if(strcmp(pText,class) == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* found !*/@\\ -\mbox{}\verb@ Vdetach(iNew);@\\ -\mbox{}\verb@ return iRef;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ Vdetach(iNew);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ } /* end for */ @\\ -\mbox{}\verb@ } /* end else */ @\\ -\mbox{}\verb@ /* not found */@\\ -\mbox{}\verb@ return -1;@\\ -\mbox{}\verb@ } @\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -NXIFindSDS searches the current Vgroup level for an SDS name. It returns -the reference ID of the SDS when found and -1 when no SDS of this name can -be found on this level. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap31} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ static int32 NXIFindSDS(NXhandle fid, char *name)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ pNexusFile self;@\\ -\mbox{}\verb@ int32 iNew, iRet, iTag, iRef;@\\ -\mbox{}\verb@ int32 i, iN, iA, iD1, iD2;@\\ -\mbox{}\verb@ NXname pNam;@\\ -\mbox{}\verb@ int32 iDim[MAX_VAR_DIMS];@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ self = NXIassert(fid);@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ /* root level search */@\\ -\mbox{}\verb@ if(self->iCurrentVG == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ i = SDfileinfo(self->iSID,&iN,&iA);@\\ -\mbox{}\verb@ if(i < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData, "ERROR: failure to read file information");@\\ -\mbox{}\verb@ return -1;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ for(i = 0; i < iN; i++)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iNew = SDselect(self->iSID,i);@\\ -\mbox{}\verb@ SDgetinfo(iNew,pNam,&iA,iDim,&iD2, &iD2);@\\ -\mbox{}\verb@ if(strcmp(pNam,name) == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDidtoref(iNew);@\\ -\mbox{}\verb@ SDendaccess(iNew);@\\ -\mbox{}\verb@ return iRet;@\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ SDendaccess(iNew);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ /* not found */@\\ -\mbox{}\verb@ return -1;@\\ -\mbox{}\verb@ }/* end root level */@\\ -\mbox{}\verb@ else /* search in a Vgroup */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iN = Vntagrefs(self->iCurrentVG);@\\ -\mbox{}\verb@ for(i = 0; i < iN; i++)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ Vgettagref(self->iCurrentVG,i,&iTag, &iRef);@\\ -\mbox{}\verb@ if( (iTag == DFTAG_SDG) || (iTag == DFTAG_NDG) || @\\ -\mbox{}\verb@ (iTag == DFTAG_SDS) )@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iNew = SDreftoindex(self->iSID, iRef);@\\ -\mbox{}\verb@ iNew = SDselect(self->iSID,iNew);@\\ -\mbox{}\verb@ SDgetinfo(iNew,pNam,&iA,iDim,&iD2, &iD2);@\\ -\mbox{}\verb@ if(strcmp(pNam,name) == 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ SDendaccess(iNew);@\\ -\mbox{}\verb@ return iRef;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ SDendaccess(iNew);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ } /* end for */ @\\ -\mbox{}\verb@ } /* end Vgroup */@\\ -\mbox{}\verb@ /* we get here, only if nothing found */@\\ -\mbox{}\verb@ return -1; @\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\subsubsection{Helper routines for directory search} -NXIInitDir initialises the directory data fields in the Nexus File structure -for a subsequent directory request. Please note, that at root level only -Vgroups will be searched. When searching SDS's at root level, all SDS's in -the whole -file seem to be returned. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap32} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ static int NXIInitDir(pNexusFile self)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ int i;@\\ -\mbox{}\verb@ int32 iTag, iRef;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ if(self->iCurrentVG == 0) /* root level */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* get the number and ID's of all lone Vgroups in the file */@\\ -\mbox{}\verb@ self->iNDir = Vlone(self->iVID,NULL,0);@\\ -\mbox{}\verb@ self->iRefDir = (int32 *)malloc(self->iNDir*sizeof(int32));@\\ -\mbox{}\verb@ if(!self->iRefDir)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: out of memory in NXIInitDir");@\\ -\mbox{}\verb@ return -1;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ Vlone(self->iVID,self->iRefDir,self->iNDir);@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ /* Vgroup level */@\\ -\mbox{}\verb@ self->iNDir = Vntagrefs(self->iCurrentVG);@\\ -\mbox{}\verb@ self->iRefDir = (int32 *)malloc(self->iNDir*sizeof(int32));@\\ -\mbox{}\verb@ self->iTagDir = (int32 *)malloc(self->iNDir*sizeof(int32));@\\ -\mbox{}\verb@ if( (!self->iRefDir) || (!self->iTagDir))@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: out of memory in NXIInitDir");@\\ -\mbox{}\verb@ return -1;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ for(i = 0; i < self->iNDir; i++)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ Vgettagref(self->iCurrentVG,i,&iTag, &iRef);@\\ -\mbox{}\verb@ self->iRefDir[i] = iRef;@\\ -\mbox{}\verb@ self->iTagDir[i] = iTag;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ } @\\ -\mbox{}\verb@ self->iCurDir = 0;@\\ -\mbox{}\verb@ return 1;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -NXIKillDir removes all data associated with a directory search from - memory. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap33} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@ static void NXIKillDir(pNexusFile self)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ if(self->iRefDir)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ free(self->iRefDir);@\\ -\mbox{}\verb@ self->iRefDir = NULL;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(self->iTagDir)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ free(self->iTagDir);@\\ -\mbox{}\verb@ self->iTagDir = NULL;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ self->iCurDir = 0;@\\ -\mbox{}\verb@ self->iNDir = 0;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -NXIInitAttDir will initialise the counters for reading either SDS or global -attribute data. - -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap34} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*-------------------------------------------------------------------------*/@\\ -\mbox{}\verb@ static int NXIInitAttDir(pNexusFile pFile)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ int iRet;@\\ -\mbox{}\verb@ int32 iData, iAtt, iRank, iType;@\\ -\mbox{}\verb@ int32 iDim[MAX_VAR_DIMS];@\\ -\mbox{}\verb@ NXname pNam;@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ pFile->iCurDir = 0;@\\ -\mbox{}\verb@ if(pFile->iCurrentSDS != 0) /* SDS level */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDgetinfo(pFile->iCurrentSDS,pNam, &iRank, iDim,&iType, @\\ -\mbox{}\verb@ &iAtt); @\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ else /* global level */@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ iRet = SDfileinfo(pFile->iSID,&iData,&iAtt); @\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ if(iRet < 0)@\\ -\mbox{}\verb@ {@\\ -\mbox{}\verb@ NXIReportError(NXpData,"ERROR: HDF cannot read attribute numbers");@\\ -\mbox{}\verb@ pFile->iNDir = 0;@\\ -\mbox{}\verb@ return NX_ERROR;@\\ -\mbox{}\verb@ }@\\ -\mbox{}\verb@ pFile->iNDir = iAtt;@\\ -\mbox{}\verb@ return NX_OK;@\\ -\mbox{}\verb@ }@\\ -\end{list} -\vspace{-1ex} -\footnotesize\addtolength{\baselineskip}{-1ex} -\end{minipage}\\[4ex] -\end{flushleft} -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap35} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*---------------------------------------------------------------------------@\\ -\mbox{}\verb@ Nexus API header file@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ copyleft: Mark Koennecke, March 1997 at LNS,PSI, Switzerland@\\ -\mbox{}\verb@ Przemek Klosowski, U. of Maryland & NIST, USA @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ No warranties of any kind taken.@\\ -\mbox{}\verb@----------------------------------------------------------------------------*/@\\ -\mbox{}\verb@#ifndef NEXUSAPI@\\ -\mbox{}\verb@#define NEXUSAPI@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@#include @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@typedef enum {NXACC_READ = DFACC_READ, @\\ -\mbox{}\verb@ NXACC_RDWR = DFACC_RDWR, @\\ -\mbox{}\verb@ NXACC_CREATE = DFACC_CREATE } NXaccess;@\\ -\mbox{}\verb@typedef void * NXhandle;@\\ -\mbox{}\verb@typedef int NXstatus;@\\ -\mbox{}\verb@typedef char NXname[VGNAMELENMAX];@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@#define NX_OK 1@\\ -\mbox{}\verb@#define NX_ERROR 0@\\ -\mbox{}\verb@#define NX_EOD -1@\\ -\mbox{}\verb@/*-------------------------------------------------------------------------@\\ -\mbox{}\verb@ HDF Datatype values for datatype parameters @\\ -\mbox{}\verb@ in the Nexus API@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ DFNT_FLOAT32 32 bit float@\\ -\mbox{}\verb@ DFNT_FLOAT64 64 nit float == double@\\ -\mbox{}\verb@ DFNT_INT8 8 bit integer ==char, byte@\\ -\mbox{}\verb@ DFNT_UINT8 8 bit unsigned integer@\\ -\mbox{}\verb@ DFNT_INT16 16 bit integer@\\ -\mbox{}\verb@ DFNT_UINT16 16 bit unsigned integer@\\ -\mbox{}\verb@ DFNT_INT32 32 bit integer@\\ -\mbox{}\verb@ DFNT_UINT32 32 bit unsigned integer@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ This list is a edited version of the one found in the HDF header file@\\ -\mbox{}\verb@ htndefs.h. That source will always be the real reference, this is@\\ -\mbox{}\verb@ documented here for your convenience.@\\ -\mbox{}\verb@--------------------------------------------------------------------------*/ @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@/*-----------------------------------------------------------------------@\\ -\mbox{}\verb@ A non Nexus standars function to set an error handler @\\ -\mbox{}\verb@*/@\\ -\mbox{}\verb@ void NXMSetError(void *pData, void (*ErrFunc)(void *pD, char *text));@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@#endif@\\ -\mbox{}\verb@@\\ -\end{list} -\vspace{-2ex} -\end{minipage}\\[4ex] -\end{flushleft} -\begin{flushleft} \small -\begin{minipage}{\linewidth} \label{scrap36} -\vspace{-1ex} -\begin{list}{}{} \item -\mbox{}\verb@@\\ -\mbox{}\verb@/*---------------------------------------------------------------------------@\\ -\mbox{}\verb@ Nexus API implementation file.@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ For documentation see the Napi.tex file which comes with this @\\ -\mbox{}\verb@ distribution.@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ copyleft: Mark Koennecke@\\ -\mbox{}\verb@ Labor fuer Neutronenstreuung@\\ -\mbox{}\verb@ Paul Scherrer Institut@\\ -\mbox{}\verb@ CH-5232 Villigen-PSI@\\ -\mbox{}\verb@ Switzerland@\\ -\mbox{}\verb@ Mark.Koenencke@{\tt @}\verb@psi.ch@\\ -\mbox{}\verb@ Przemek Klosowski@\\ -\mbox{}\verb@ U. of Maryland & NIST @\\ -\mbox{}\verb@ przemek.klosowski@{\tt @}\verb@nist.gov @\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ no warranties of any kind, whether explicit or implied, taken.@\\ -\mbox{}\verb@ Distributed under the GNU copyleft license as documented elsewhere.@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ March 1997@\\ -\mbox{}\verb@@\\ -\mbox{}\verb@ Version: 1.0@\\ -\mbox{}\verb@----------------------------------------------------------------------------*/@\\ -\end{list} -\vspace{-2ex} -\end{minipage}\\[4ex] -\end{flushleft} -\end{document} diff --git a/napi4.c b/napi4.c index 4da84b52..45974ee1 100644 --- a/napi4.c +++ b/napi4.c @@ -20,6 +20,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For further information, see + + $Id: napi4.c,v 1.4 2005/05/27 11:58:06 koennecke Exp $ ----------------------------------------------------------------------------*/ #include @@ -27,6 +29,11 @@ #include #include +#include "napi.h" +#include "napi4.h" + +extern void *NXpData; + typedef struct __NexusFile { struct iStack { int32 *iRefDir; @@ -45,8 +52,7 @@ int iStackPtr; char iAccess[2]; } NexusFile, *pNexusFile; - - + /*--------------------------------------------------------------------*/ static pNexusFile NXIassert(NXhandle fid) @@ -61,7 +67,7 @@ /* --------------------------------------------------------------------- */ - static int32 NXIFindVgroup (pNexusFile pFile, char *name, char *nxclass) + static int32 NXIFindVgroup (pNexusFile pFile, CONSTCHAR *name, CONSTCHAR *nxclass) { int32 iNew, iRef, iTag; int iN, i; @@ -285,8 +291,28 @@ 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)); + } + } /* ---------------------------------------------------------------------- Definition of NeXus API @@ -294,7 +320,8 @@ ---------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NX4open(CONSTCHAR *filename, NXaccess am, NXhandle* pHandle) + NXstatus CALLING_STYLE NX4open(CONSTCHAR *filename, NXaccess am, + NXhandle* pHandle) { pNexusFile pNew = NULL; char pBuffer[512], time_buffer[64]; @@ -331,9 +358,11 @@ /* * get time in ISO 8601 format */ + +/* #ifdef NEED_TZSET tzset(); -#endif /* NEED_TZSET */ +#endif time(&timer); #ifdef USE_FTIME ftime(&timeb_struct); @@ -349,8 +378,10 @@ NXIReportError(NXpData, "Your gmtime() function does not work ... timezone information will be incorrect\n"); gmt_offset = 0; } -#endif /* USE_FTIME */ +#endif time_info = localtime(&timer); +*/ + time_info = NULL; if (time_info != NULL) { if (gmt_offset < 0) { time_format = "%04d-%02d-%02d %02d:%02d:%02d-%02d%02d"; @@ -505,7 +536,7 @@ /*-----------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NX4makegroup (NXhandle fid, CONSTCHAR *name, char *nxclass) + NXstatus CALLING_STYLE NX4makegroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { pNexusFile pFile; int32 iNew, iRet; @@ -549,7 +580,7 @@ /*------------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NX4opengroup (NXhandle fid, CONSTCHAR *name, char *nxclass) + NXstatus CALLING_STYLE NX4opengroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { pNexusFile pFile; int32 iRef; @@ -1130,7 +1161,7 @@ } iType = type; if (iRet < 0) { - NXIReportError (NXpData, "ERROR: HDf failed to store attribute "); + NXIReportError (NXpData, "ERROR: HDF failed to store attribute "); return NX_ERROR; } return NX_OK; @@ -1208,6 +1239,7 @@ } else { sRes->iTag = DFTAG_NDG; sRes->iRef = SDidtoref (pFile->iCurrentSDS); + NXIbuildPath(pFile,sRes->targetPath,1024); return NX_OK; } sRes->iTag = NX_ERROR; @@ -1221,14 +1253,24 @@ NXstatus CALLING_STYLE NX4makelink (NXhandle fid, NXlink* sLink) { pNexusFile pFile; - int32 iVG, iRet; + 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); + Vaddtagref(pFile->iCurrentVG, sLink->iTag, sLink->iRef); + if(sLink->iTag == DFTAG_SDG || sLink->iTag == DFTAG_NDG || + sLink->iTag == DFTAG_SDS) + { + dataID = SDreftoindex(pFile->iSID,sLink->iRef); + dataID = SDselect(pFile->iSID,dataID); + length = strlen(sLink->targetPath); + SDsetattr(dataID,name,type,length,sLink->targetPath); + SDendaccess(dataID); + } return NX_OK; } @@ -1687,6 +1729,7 @@ } else { sRes->iTag = DFTAG_VG; sRes->iRef = VQueryref(pFile->iCurrentVG); + NXIbuildPath(pFile,sRes->targetPath,1024); return NX_OK; } /* not reached */ @@ -1765,3 +1808,34 @@ 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->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; +} diff --git a/napi4.h b/napi4.h index 733544d4..927d58a8 100644 --- a/napi4.h +++ b/napi4.h @@ -1,6 +1,7 @@ #define NXSIGNATURE 959697 -#include "napi4.c" +#include "napi.h" +/* #include "napi4.c" */ /* * HDF4 interface @@ -10,8 +11,8 @@ NX_EXTERNAL NXstatus CALLING_STYLE NX4open(CONSTCHAR *filename, NXaccess access NX_EXTERNAL NXstatus CALLING_STYLE NX4close(NXhandle* pHandle); NX_EXTERNAL NXstatus CALLING_STYLE NX4flush(NXhandle* pHandle); -NX_EXTERNAL NXstatus CALLING_STYLE NX4makegroup (NXhandle handle, CONSTCHAR* Vgroup, char* NXclass); -NX_EXTERNAL NXstatus CALLING_STYLE NX4opengroup (NXhandle handle, CONSTCHAR* Vgroup, char* NXclass); +NX_EXTERNAL NXstatus CALLING_STYLE NX4makegroup (NXhandle handle, CONSTCHAR* Vgroup, CONSTCHAR* NXclass); +NX_EXTERNAL NXstatus CALLING_STYLE NX4opengroup (NXhandle handle, CONSTCHAR* Vgroup, CONSTCHAR* NXclass); NX_EXTERNAL NXstatus CALLING_STYLE NX4closegroup(NXhandle handle); NX_EXTERNAL NXstatus CALLING_STYLE NX4makedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); @@ -40,4 +41,6 @@ NX_EXTERNAL NXstatus CALLING_STYLE NX4getnextattr(NXhandle handle, NXname pName NX_EXTERNAL NXstatus CALLING_STYLE NX4getgroupID(NXhandle handle, NXlink* pLink); NX_EXTERNAL NXstatus CALLING_STYLE NX4getdataID(NXhandle handle, NXlink* pLink); NX_EXTERNAL NXstatus CALLING_STYLE NX4makelink(NXhandle handle, NXlink* pLink); +void NX4assignFunctions(pNexusFunction fHandle); + diff --git a/napi45.c b/napi45.c deleted file mode 100644 index a80e9322..00000000 --- a/napi45.c +++ /dev/null @@ -1,630 +0,0 @@ -#include -#include -#include -#include -#include "fortify.h" -#include "napi.h" - - typedef struct { - NXhandle *pNexusData; - NXstatus (*nxclose)(NXhandle* pHandle); - NXstatus (*nxflush)(NXhandle* pHandle); - NXstatus (*nxmakegroup) (NXhandle handle, CONSTCHAR *name, char* NXclass); - NXstatus (*nxopengroup) (NXhandle handle, CONSTCHAR *name, char* 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 (*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 (*nxinitgroupdir)(NXhandle handle); - NXstatus (*nxinitattrdir)(NXhandle handle); - } NexusFunction, *pNexusFunction; - - static int iFortifyScope; -/*------------------------------------------------------------------------ - HDF-5 cache size special stuff - -------------------------------------------------------------------------*/ -static long cacheSize = 1024000; /* 1MB, HDF-5 default */ - -NXstatus CALLING_STYLE NXsetcache(long newVal) -{ - if(newVal > 0) - { - cacheSize = newVal; - return NX_OK; - } - return NX_ERROR; -} - - - /*---------------------------------------------------------------------*/ - - static void NXNXNXReportError(void *pData, char *string) - { - printf("%s \n",string); - } - - /*---------------------------------------------------------------------*/ - - void *NXpData = NULL; - void (*NXIReportError)(void *pData, char *string) = NXNXNXReportError; - - /*---------------------------------------------------------------------*/ - - void CALLING_STYLE NXMSetError(void *pData, void (*NewError)(void *pD, char *text)) - { - NXpData = pData; - NXIReportError = NewError; - } - -#ifdef HDF5 -#include "napi5.h" -#endif -#ifdef HDF4 -#include "napi4.h" -#endif - - - /* ---------------------------------------------------------------------- - - Definition of NeXus API - - ---------------------------------------------------------------------*/ - - - NXstatus CALLING_STYLE NXopen(CONSTCHAR *filename, NXaccess am, NXhandle *gHandle) - { - int hdf_type=0; - int iRet=0; - NXhandle hdf5_handle; - NXhandle hdf4_handle; - pNexusFunction fHandle; - - /* configure fortify - iFortifyScope = Fortify_EnterScope(); - Fortify_CheckAllMemory(); - */ - - fHandle = (pNexusFunction)malloc(sizeof(NexusFunction)); - if (fHandle == NULL) { - NXIReportError (NXpData,"ERROR: no memory to create Function structure"); - return NX_ERROR; - } - if (am==NXACC_CREATE || am == NXACC_CREATE4) { - /* HDF4 will be used ! */ - hdf_type=1; - } else if (am==NXACC_CREATE5) { - /* HDF5 will be used ! */ - hdf_type=2; - } else { - /* check file type hdf4/hdf5 for reading */ -#ifdef HDF5 - iRet=H5Fis_hdf5((const char*)filename); -#endif - if (iRet>0) { - hdf_type=2; - } else { -#ifdef HDF4 - iRet=Hishdf(filename); -#endif - if (iRet>0) { - hdf_type=1; - } - } - } - if (hdf_type==1) { - /* HDF4 type */ -#ifdef HDF4 - iRet = NX4open(filename,am,&hdf4_handle); - fHandle->pNexusData=hdf4_handle; - 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->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->nxinitgroupdir=NX4initgroupdir; - fHandle->nxinitattrdir=NX4initattrdir; -#endif - } else if (hdf_type==2) { - /* HDF5 type */ -#ifdef HDF5 - iRet = NX5open(filename,am,&hdf5_handle); - fHandle->pNexusData=hdf5_handle; - 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->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->nxinitgroupdir=NX5initgroupdir; - fHandle->nxinitattrdir=NX5initattrdir; -#endif - } else { - NXIReportError (NXpData,"ERROR: Format couldn't be handled!"); - *gHandle = NULL; - return NX_ERROR; - } - if(iRet == NX_OK) - { - *gHandle = fHandle; - return NX_OK; - } - else - { - free(fHandle); - return iRet; - } - } - -/* ------------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXclose (NXhandle *fid) - { - NXhandle hfil; - int status; - - pNexusFunction pFunc=NULL; - pFunc = (pNexusFunction)*fid; - hfil = pFunc->pNexusData; - status = pFunc->nxclose(&hfil); - pFunc->pNexusData = hfil; - free(pFunc); - /* - Fortify_CheckAllMemory(); - */ - return status; - } - - /*-----------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXmakegroup (NXhandle fid, CONSTCHAR *name, char *nxclass) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxmakegroup(pFunc->pNexusData, name, nxclass); - } - - /*------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXopengroup (NXhandle fid, CONSTCHAR *name, char *nxclass) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxopengroup(pFunc->pNexusData, name, nxclass); - } - - /* ------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXclosegroup (NXhandle fid) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxclosegroup(pFunc->pNexusData); - } - - /* --------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXmakedata (NXhandle fid, CONSTCHAR *name, int datatype, - int rank, int dimensions[]) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxmakedata(pFunc->pNexusData, name, datatype, rank, dimensions); - } - - - /* --------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXcompmakedata (NXhandle fid, CONSTCHAR *name, int datatype, - int rank, int dimensions[],int compress_type, int chunk_size[]) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxcompmakedata (pFunc->pNexusData, name, datatype, rank, dimensions, compress_type, chunk_size); - } - - - /* --------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXcompress (NXhandle fid, int compress_type) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxcompress (pFunc->pNexusData, compress_type); - } - - - /* --------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXopendata (NXhandle fid, CONSTCHAR *name) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxopendata(pFunc->pNexusData, name); - } - - - /* ----------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXclosedata (NXhandle fid) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxclosedata(pFunc->pNexusData); - } - - /* ------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXputdata (NXhandle fid, void *data) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxputdata(pFunc->pNexusData, data); - } - - /* ------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXputattr (NXhandle fid, CONSTCHAR *name, void *data, - int datalen, int iType) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxputattr(pFunc->pNexusData, name, data, datalen, iType); - } - - /* ------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXputslab (NXhandle fid, void *data, int iStart[], int iSize[]) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxputslab(pFunc->pNexusData, data, iStart, iSize); - } - - /* ------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXgetdataID (NXhandle fid, NXlink* sRes) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxgetdataID(pFunc->pNexusData, sRes); - } - - - /* ------------------------------------------------------------------- */ - - NXstatus CALLING_STYLE NXmakelink (NXhandle fid, NXlink* sLink) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxmakelink(pFunc->pNexusData, sLink); - } - - - /*----------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXflush(NXhandle *pHandle) - { - NXhandle hfil; - int status; - - pNexusFunction pFunc=NULL; - pFunc = (pNexusFunction)*pHandle; - hfil = pFunc->pNexusData; - status = pFunc->nxflush(&hfil); - pFunc->pNexusData = hfil; - return status; - } - - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXmalloc (void** data, int rank, int dimensions[], int datatype) - { - int i; - size_t size = 1; - *data = NULL; - for(i=0; inxgetnextentry(pFunc->pNexusData, name, nxclass, datatype); - } - - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXgetdata (NXhandle fid, void *data) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxgetdata(pFunc->pNexusData, data); - } - - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXgetinfo (NXhandle fid, int *rank, int dimension[], int *iType) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxgetinfo(pFunc->pNexusData, rank, dimension, iType); - } - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXgetslab (NXhandle fid, void *data, int iStart[], int iSize[]) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxgetslab(pFunc->pNexusData, data, iStart, iSize); - } - - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXgetnextattr (NXhandle fileid, NXname pName, - int *iLength, int *iType) - { - pNexusFunction pFunc = (pNexusFunction)fileid; - return pFunc->nxgetnextattr(pFunc->pNexusData, pName, iLength, iType); - } - - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXgetattr (NXhandle fid, char *name, void *data, int* datalen, int* iType) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxgetattr(pFunc->pNexusData, name, data, datalen, iType); - } - - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXgetattrinfo (NXhandle fid, int *iN) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxgetattrinfo(pFunc->pNexusData, iN); - } - - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXgetgroupID (NXhandle fileid, NXlink* sRes) - { - pNexusFunction pFunc = (pNexusFunction)fileid; - return pFunc->nxgetgroupID(pFunc->pNexusData, sRes); - } - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXgetgroupinfo (NXhandle fid, int *iN, NXname pName, NXname pClass) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxgetgroupinfo(pFunc->pNexusData, iN, pName, pClass); - } - - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXinitattrdir (NXhandle fid) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxinitattrdir(pFunc->pNexusData); - } - - - /*-------------------------------------------------------------------------*/ - - NXstatus CALLING_STYLE NXinitgroupdir (NXhandle fid) - { - pNexusFunction pFunc = (pNexusFunction)fid; - return pFunc->nxinitgroupdir(pFunc->pNexusData); - } -/*---------------------------------------------------------------------- - F77 - API - Support - Routines - ----------------------------------------------------------------------*/ - /* - * We store the whole of the NeXus file in the array - that way - * we can just pass the array name to C as it will be a valid - * NXhandle. We could store the NXhandle value in the FORTRAN array - * instead, but that would mean writing far more wrappers - */ - NXstatus CALLING_STYLE 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)); - } - 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 CALLING_STYLE 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 CALLING_STYLE 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 CALLING_STYLE 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; - } -/* - * Reverse dimensions array as FORTRAN is column major, C row major - */ - 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; - } - - - NXstatus CALLING_STYLE 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; - } -/* - * 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]; - } - ret = NXcompmakedata(fid, name, *pDatatype, *pRank, - reversed_dimensions,*compression_type, reversed_chunk); - free(reversed_dimensions); - free(reversed_chunk); - return ret; - } -/*-----------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NXfcompress(NXhandle fid, int *compr_type) - { - return NXcompress(fid,*compr_type); - } -/*-----------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NXfputattr(NXhandle fid, char *name, void *data, - int *pDatalen, int *pIType) - { - return NXputattr(fid, name, data, *pDatalen, *pIType); - } diff --git a/napi5.c b/napi5.c index 6d8c0330..29dd38d5 100644 --- a/napi5.c +++ b/napi5.c @@ -27,10 +27,8 @@ #include #include -/* #include "napi.h" #include "napi5.h" -*/ extern void *NXpData; @@ -114,7 +112,8 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); ---------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NX5open(CONSTCHAR *filename, NXaccess am, NXhandle* pHandle) + NXstatus CALLING_STYLE NX5open(CONSTCHAR *filename, NXaccess am, + NXhandle* pHandle) { hid_t attr1,aid1, aid2; pNexusFile5 pNew = NULL; @@ -128,11 +127,7 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); unsigned int vers_major, vers_minor, vers_release, am1 ; hid_t fapl; int mdc_nelmts; -#ifdef H5_WANT_H5_V1_4_COMPAT - unsigned int rdcc_nelmts; -#else - size_t rdcc_nelmts; -#endif + unsigned long rdcc_nelmts; size_t rdcc_nbytes; double rdcc_w0; @@ -395,7 +390,7 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); /*-----------------------------------------------------------------------*/ - NXstatus CALLING_STYLE NX5makegroup (NXhandle fid, CONSTCHAR *name, char *nxclass) + NXstatus CALLING_STYLE NX5makegroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { pNexusFile5 pFile; hid_t iRet; @@ -451,7 +446,7 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); return strstr(member_name, attr_name) ? 1 : 0; } - NXstatus CALLING_STYLE NX5opengroup (NXhandle fid, CONSTCHAR *name, char *nxclass) + NXstatus CALLING_STYLE NX5opengroup (NXhandle fid, CONSTCHAR *name, CONSTCHAR *nxclass) { pNexusFile5 pFile; @@ -870,6 +865,8 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); /* ------------------------------------------------------------------- */ + + NXstatus CALLING_STYLE NX5putdata (NXhandle fid, void *data) { pNexusFile5 pFile; @@ -1090,7 +1087,8 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); if(pFile->iCurrentD <= 0){ return NX_ERROR; } - strcpy(sRes->iRef5,pFile->name_ref); + strcpy(sRes->iRef5,"/"); + strcat(sRes->iRef5,pFile->name_ref); strcpy(sRes->iRefd,pFile->iCurrentLD); return NX_OK; } @@ -1101,10 +1099,11 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); { pNexusFile5 pFile; /* int iRet; */ - herr_t status; + herr_t status, dataID, aid1, aid2, attID; int size_type; char buffer[1024]; - + char name[] = "target"; + pFile = NXI5assert (fid); if (pFile->iCurrentG == 0) { /* root level, can not link here */ return NX_ERROR; @@ -1132,6 +1131,36 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); strcat(sLink->iTag5,sLink->iRefd); } status = H5Glink(pFile->iFID, H5G_LINK_HARD, sLink->iRef5, sLink->iTag5); + if(size_type > 0) + { + dataID = H5Dopen(pFile->iFID,sLink->iRef5); + /* + remove old attribute if existing + */ + 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->iRef5)); + attID = H5Acreate(dataID,name,aid1,aid2,H5P_DEFAULT); + if(attID < 0) + { + return NX_OK; + } + H5Awrite(attID,aid1,sLink->iRef5); + H5Tclose(aid1); + H5Sclose(aid2); + H5Aclose(attID); + H5Dclose(dataID); + } return NX_OK; } @@ -2070,3 +2099,35 @@ NXstatus CALLING_STYLE NX5closegroup (NXhandle fid); NXI5KillDir (fid); 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->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; + +} diff --git a/napi5.h b/napi5.h index 69a39ea7..5c4b6664 100644 --- a/napi5.h +++ b/napi5.h @@ -1,7 +1,6 @@ #define NX5SIGNATURE 959695 #include -#include "napi5.c" /* HDF5 interface */ @@ -9,8 +8,8 @@ NX_EXTERNAL NXstatus CALLING_STYLE NX5open(CONSTCHAR *filename, NXaccess access NX_EXTERNAL NXstatus CALLING_STYLE NX5close(NXhandle* pHandle); NX_EXTERNAL NXstatus CALLING_STYLE NX5flush(NXhandle* pHandle); -NX_EXTERNAL NXstatus CALLING_STYLE NX5makegroup (NXhandle handle, CONSTCHAR *name, char* NXclass); -NX_EXTERNAL NXstatus CALLING_STYLE NX5opengroup (NXhandle handle, CONSTCHAR *name, char* NXclass); +NX_EXTERNAL NXstatus CALLING_STYLE NX5makegroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); +NX_EXTERNAL NXstatus CALLING_STYLE NX5opengroup (NXhandle handle, CONSTCHAR *name, CONSTCHAR* NXclass); NX_EXTERNAL NXstatus CALLING_STYLE NX5closegroup(NXhandle handle); NX_EXTERNAL NXstatus CALLING_STYLE NX5makedata (NXhandle handle, CONSTCHAR* label, int datatype, int rank, int dim[]); @@ -40,6 +39,7 @@ NX_EXTERNAL NXstatus CALLING_STYLE NX5getgroupinfo(NXhandle handle, int* no_ite NX_EXTERNAL NXstatus CALLING_STYLE NX5initgroupdir(NXhandle handle); NX_EXTERNAL NXstatus CALLING_STYLE 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); diff --git a/napif.f b/napif.f deleted file mode 100644 index 9b9c127c..00000000 --- a/napif.f +++ /dev/null @@ -1,274 +0,0 @@ -C---------------------------------------------------------------------------- -C NeXus - Neutron & X-ray Common Data Format -C -C API Fortran Interface -C -C $Id: napif.f,v 1.1 2000/02/07 10:38:58 cvs Exp $ -C -C Copyright (C) 1997, Freddie Akeroyd -C ISIS Facility, Rutherford Appleton Laboratory, UK -C -C See NAPI.C for further details -C -C 22/2/98 - Correct an NXfclose problem (free() of FORTRAN memory) -C 97/7/30 - Initial Release -C 97/7/31 - Correct NXPUTATTR/NXGETATTR and make 'implicit none' clean -C 97/8/7 - Update interface -C---------------------------------------------------------------------------- - -C *** Return length of a string, ignoring trailing blanks - INTEGER FUNCTION TRUELEN(STRING) - CHARACTER*(*) STRING - DO TRUELEN=LEN(STRING),1,-1 - IF (STRING(TRUELEN:TRUELEN) .NE. ' ') RETURN - ENDDO - TRUELEN = 0 - END - -C *** Convert FORTRAN string STRING into NULL terminated C string ISTRING - SUBROUTINE EXTRACT_STRING(ISTRING, LENMAX, STRING) - CHARACTER*(*) STRING - INTEGER I,ILEN,TRUELEN,LENMAX - BYTE ISTRING(LENMAX) - EXTERNAL TRUELEN - ILEN = TRUELEN(STRING) -C WRITE(6,*)'TRUELEN: ', ILEN - IF (ILEN .GE. LENMAX) THEN - WRITE(6,9000) LENMAX, ILEN+1 - RETURN - ENDIF - DO I=1,ILEN - ISTRING(I) = ICHAR(STRING(I:I)) - ENDDO - ISTRING(ILEN+1) = 0 - RETURN - 9000 FORMAT('NAPIF: String too long - buffer needs increasing from ', - + i4,' to at least ',i4) - END - -C *** Convert NULL terminated C string ISTRING to FORTRAN string STRING - SUBROUTINE REPLACE_STRING(STRING, ISTRING) - BYTE ISTRING(*) - CHARACTER*(*) STRING - INTEGER I - STRING = ' ' - DO I=1,LEN(STRING) - IF (ISTRING(I) .EQ. 0) RETURN - STRING(I:I) = CHAR(ISTRING(I)) - ENDDO - WRITE(6,9010) LEN(STRING) - RETURN - 9010 FORMAT('NAPIF: String truncated - buffer needs to be > ', I4) - END - -C *** Wrapper routines for NXAPI interface - INTEGER FUNCTION NXOPEN(FILENAME, ACCESS_METHOD, FILEID) - CHARACTER*(*) FILENAME - BYTE IFILENAME(256) - INTEGER ACCESS_METHOD - INTEGER FILEID(*),NXIFOPEN - EXTERNAL NXIFOPEN - CALL EXTRACT_STRING(IFILENAME, 256, FILENAME) - NXOPEN = NXIFOPEN(IFILENAME, ACCESS_METHOD, FILEID) - END - - INTEGER FUNCTION NXCLOSE(FILEID) - INTEGER FILEID(*),NXIFCLOSE - EXTERNAL NXIFCLOSE - NXCLOSE = NXIFCLOSE(FILEID) - END - - INTEGER FUNCTION NXMAKEGROUP(FILEID, VGROUP, NXCLASS) - INTEGER FILEID(*),NXIMAKEGROUP - CHARACTER*(*) VGROUP, NXCLASS - BYTE IVGROUP(256), INXCLASS(256) - EXTERNAL NXIMAKEGROUP - CALL EXTRACT_STRING(IVGROUP, 256, VGROUP) - CALL EXTRACT_STRING(INXCLASS, 256, NXCLASS) - NXMAKEGROUP = NXIMAKEGROUP(FILEID, IVGROUP, INXCLASS) - END - - INTEGER FUNCTION NXOPENGROUP(FILEID, VGROUP, NXCLASS) - INTEGER FILEID(*),NXIOPENGROUP - CHARACTER*(*) VGROUP, NXCLASS - BYTE IVGROUP(256), INXCLASS(256) - EXTERNAL NXIOPENGROUP - CALL EXTRACT_STRING(IVGROUP, 256, VGROUP) - CALL EXTRACT_STRING(INXCLASS, 256, NXCLASS) - NXOPENGROUP = NXIOPENGROUP(FILEID, IVGROUP, INXCLASS) - END - - INTEGER FUNCTION NXCLOSEGROUP(FILEID) - INTEGER FILEID(*),NXICLOSEGROUP - EXTERNAL NXICLOSEGROUP - NXCLOSEGROUP = NXICLOSEGROUP(FILEID) - END - - INTEGER FUNCTION NXMAKEDATA(FILEID, LABEL, DATATYPE, RANK, DIM) - INTEGER FILEID(*), DATATYPE, RANK, DIM(*), NXIFMAKEDATA - CHARACTER*(*) LABEL - BYTE ILABEL(256) - EXTERNAL NXIFMAKEDATA - CALL EXTRACT_STRING(ILABEL, 256, LABEL) - NXMAKEDATA = NXIFMAKEDATA(FILEID, ILABEL, DATATYPE, RANK, DIM) - END - - INTEGER FUNCTION NXOPENDATA(FILEID, LABEL) - INTEGER FILEID(*),NXIOPENDATA - CHARACTER*(*) LABEL - BYTE ILABEL(256) - EXTERNAL NXIOPENDATA - CALL EXTRACT_STRING(ILABEL, 256, LABEL) - NXOPENDATA = NXIOPENDATA(FILEID, ILABEL) - END - - INTEGER FUNCTION NXCLOSEDATA(FILEID) - INTEGER FILEID(*),NXICLOSEDATA - EXTERNAL NXICLOSEDATA - NXCLOSEDATA = NXICLOSEDATA(FILEID) - END - - INTEGER FUNCTION NXGETDATA(FILEID, DATA) - INTEGER FILEID(*), DATA(*),NXIGETDATA - EXTERNAL NXIGETDATA - NXGETDATA = NXIGETDATA(FILEID, DATA) - END - - INTEGER FUNCTION NXGETSLAB(FILEID, DATA, START, SIZE) - INTEGER FILEID(*), DATA(*), START(*), SIZE(*) - INTEGER NXIGETSLAB - EXTERNAL NXIGETSLAB - NXGETSLAB = NXIGETSLAB(FILEID, DATA, START, SIZE) - END - - INTEGER FUNCTION NXIFGETCHARATTR(FILEID, INAME, DATA, - + DATALEN, TYPE) - INTEGER MAX_DATALEN,NX_ERROR - INTEGER FILEID(*), DATALEN, TYPE - PARAMETER(MAX_DATALEN=1024,NX_ERROR=0) - CHARACTER*(*) DATA - BYTE IDATA(MAX_DATALEN) - BYTE INAME(*) - INTEGER NXIGETATTR - EXTERNAL NXIGETATTR - IF (DATALEN .GE. MAX_DATALEN) THEN - WRITE(6,9020) DATALEN, MAX_DATALEN - NXIFGETCHARATTR=NX_ERROR - RETURN - ENDIF - NXIFGETCHARATTR = NXIGETATTR(FILEID, INAME, IDATA, DATALEN, TYPE) - IF (NXIFGETCHARATTR .NE. NX_ERROR) THEN - CALL REPLACE_STRING(DATA, IDATA) - ENDIF - RETURN - 9020 FORMAT('NXgetattr: asked for attribute size ', I4, - + ' with buffer size only ', I4) - END - - INTEGER FUNCTION NXGETATTR(FILEID, NAME, DATA, DATALEN, TYPE) - INTEGER FILEID(*),DATALEN,TYPE,NX_CHAR - PARAMETER(NX_CHAR=4) - CHARACTER*(*) NAME, DATA - BYTE INAME(256) - INTEGER NXIGETATTR, NXIFGETCHARATTR - EXTERNAL NXIGETATTR, NXIFGETCHARATTR - CALL EXTRACT_STRING(INAME, 256, NAME) - IF ((TYPE .EQ. NX_CHAR) .OR. (TYPE .EQ. NX_UINT8)) THEN - NXGETATTR = NXIFGETCHARATTR(FILEID, INAME, DATA, - + DATALEN, TYPE) - ELSE - NXGETATTR = NXIGETATTR(FILEID, INAME, DATA, DATALEN, TYPE) - ENDIF - END - - INTEGER FUNCTION NXPUTDATA(FILEID, DATA) - INTEGER FILEID(*), DATA(*), NXIPUTDATA - EXTERNAL NXIPUTDATA - NXPUTDATA = NXIPUTDATA(FILEID, DATA) - END - - INTEGER FUNCTION NXPUTSLAB(FILEID, DATA, START, SIZE) - INTEGER FILEID(*), DATA(*), START(*), SIZE(*) - INTEGER NXIPUTSLAB - EXTERNAL NXIPUTSLAB - NXPUTSLAB = NXIPUTSLAB(FILEID, DATA, START, SIZE) - END - - INTEGER FUNCTION NXIFPUTCHARATTR(FILEID, INAME, DATA, - + DATALEN, TYPE) - INTEGER FILEID(*), DATALEN, TYPE - BYTE INAME(*) - CHARACTER*(*) DATA - BYTE IDATA(1024) - INTEGER NXIFPUTATTR - EXTERNAL NXIFPUTATTR - CALL EXTRACT_STRING(IDATA, 1024, DATA) - NXIFPUTCHARATTR = NXIFPUTATTR(FILEID, INAME, IDATA, DATALEN, TYPE) - END - - INTEGER FUNCTION NXPUTATTR(FILEID, NAME, DATA, DATALEN, TYPE) - INTEGER FILEID(*), DATALEN, TYPE, NX_CHAR - PARAMETER(NX_CHAR=4) - CHARACTER*(*) NAME, DATA - BYTE INAME(256) - INTEGER NXIFPUTATTR, NXIFPUTCHARATTR - EXTERNAL NXIFPUTATTR, NXIFPUTCHARATTR - CALL EXTRACT_STRING(INAME, 256, NAME) - IF ((TYPE .EQ. NX_CHAR) .OR. (TYPE .EQ. NX_UINT8)) THEN - NXPUTATTR = NXIFPUTCHARATTR(FILEID, INAME, DATA, - + DATALEN, TYPE) - ELSE - NXPUTATTR = NXIFPUTATTR(FILEID, INAME, DATA, DATALEN, TYPE) - ENDIF - END - - INTEGER FUNCTION NXGETINFO(FILEID, RANK, DIM, DATATYPE) - INTEGER FILEID(*), RANK, DIM(*), DATATYPE - INTEGER I, J, NXIGETINFO - EXTERNAL NXIGETINFO - NXGETINFO = NXIGETINFO(FILEID, RANK, DIM, DATATYPE) -C *** Reverse dimension array as C is ROW major, FORTRAN column major - DO I = 1, RANK/2 - J = DIM(I) - DIM(I) = DIM(RANK-I+1) - DIM(RANK-I+1) = J - ENDDO - END - - INTEGER FUNCTION NXGETNEXTENTRY(FILEID, NAME, CLASS, DATATYPE) - INTEGER FILEID(*), DATATYPE - CHARACTER*(*) NAME, CLASS - BYTE INAME(256), ICLASS(256) - INTEGER NXIGETNEXTENTRY - EXTERNAL NXIGETNEXTENTRY - NXGETNEXTENTRY = NXIGETNEXTENTRY(FILEID, INAME, ICLASS, DATATYPE) - CALL REPLACE_STRING(NAME, INAME) - CALL REPLACE_STRING(CLASS, ICLASS) - END - - INTEGER FUNCTION NXGETNEXTATTR(FILEID, PNAME, ILENGTH, ITYPE) - INTEGER FILEID(*), ILENGTH, ITYPE, NXIGETNEXTATTR - CHARACTER*(*) PNAME - BYTE IPNAME(1024) - EXTERNAL NXIGETNEXTATTR - NXGETNEXTATTR = NXIGETNEXTATTR(FILEID, IPNAME, ILENGTH, ITYPE) - CALL REPLACE_STRING(PNAME, IPNAME) - END - - INTEGER FUNCTION NXGETGROUPID(FILEID, LINK) - INTEGER FILEID(*), LINK(*), NXIGETGROUPID - EXTERNAL NXIGETGROUPID - NXGETGROUPID = NXIGETGROUPID(FILEID, LINK) - END - - INTEGER FUNCTION NXGETDATAID(FILEID, LINK) - INTEGER FILEID(*), LINK(*), NXIGETDATAID - EXTERNAL NXIGETDATAID - NXGETDATAID = NXIGETDATAID(FILEID, LINK) - END - - INTEGER FUNCTION NXMAKELINK(FILEID, LINK) - INTEGER FILEID(*), LINK(*), NXIMAKELINK - EXTERNAL NXIMAKELINK - NXMAKELINK = NXIMAKELINK(FILEID, LINK) - END diff --git a/napif.inc b/napif.inc deleted file mode 100644 index 07e27deb..00000000 --- a/napif.inc +++ /dev/null @@ -1,47 +0,0 @@ -C---------------------------------------------------------------------------- -C NeXus - Neutron & X-ray Common Data Format -C -C API Fortran Interface Definitions -C -C $Id: napif.inc,v 1.1 2000/02/07 10:38:58 cvs Exp $ -C -C Copyright (C) 1997, Freddie Akeroyd -C ISIS Facility, Rutherford Appleton Laboratory -C -C See NAPI.C for details -C -C 97/7/30 - Initial Release -C 97/7/31 - Correct NXPUTATTR/NXGETATTR and make 'implicit none' clean -C 97/8/7 - Update interface -C---------------------------------------------------------------------------- - -C *** NXaccess enum - access modes for NXopen - INTEGER NXACC_READ,NXACC_RDWR,NXACC_CREATE - PARAMETER(NXACC_READ=1,NXACC_RDWR=3,NXACC_CREATE=7) -C *** NXHANDLESIZE should be the size of an INTEGER*4 array that is (at least) -C *** large enough to hold an NXhandle structure - INTEGER NXHANDLESIZE - PARAMETER(NXHANDLESIZE=600) -C *** NXLINKSIZE is (at least) the size of an INTEGER*4 array that can hold -C *** an NXlink structure: we'll assume 64bit alignment of structure members for safety - INTEGER NXLINKSIZE - PARAMETER(NXLINKSIZE=4) -C *** Possible NXstatus values - these are returned by all NX routines - INTEGER NX_OK,NX_ERROR,NX_EOD - PARAMETER(NX_OK=1,NX_ERROR=0,NX_EOD=-1) -C *** HDF datatypes used by Nexus - see hntdefs.h in HDF distribution - INTEGER DFNT_FLOAT32,DFNT_FLOAT64,DFNT_INT8,DFNT_UINT8,DFNT_INT16, - + DFNT_UINT16,DFNT_INT32,DFNT_UINT32 - PARAMETER(DFNT_FLOAT32=5,DFNT_FLOAT64=6,DFNT_INT8=20, - + DFNT_UINT8=21,DFNT_INT16=22,DFNT_UINT16=23, - + DFNT_INT32=24,DFNT_UINT32=25) - INTEGER NXOPEN, NXCLOSE, NXMAKEGROUP, NXOPENGROUP, NXCLOSEGROUP, - + NXMAKEDATA, NXOPENDATA, NXCLOSEDATA, NXGETDATA, NXGETSLAB, - + NXGETATTR, NXGETDIM, NXPUTDATA, NXPUTSLAB, NXPUTATTR, - + NXPUTDIM, NXGETINFO, NXGETNEXTENTRY, NXGETNEXTATTR, - + NXGETGROUPID, NXMAKELINK - EXTERNAL NXOPEN, NXCLOSE, NXMAKEGROUP, NXOPENGROUP, NXCLOSEGROUP, - + NXMAKEDATA, NXOPENDATA, NXCLOSEDATA, NXGETDATA, NXGETSLAB, - + NXGETATTR, NXGETDIM, NXPUTDATA, NXPUTSLAB, NXPUTATTR, - + NXPUTDIM, NXGETINFO, NXGETNEXTENTRY, NXGETNEXTATTR, - + NXGETGROUPID, NXMAKELINK diff --git a/nxdataset.c b/nxdataset.c new file mode 100644 index 00000000..c64c1321 --- /dev/null +++ b/nxdataset.c @@ -0,0 +1,299 @@ +/* + This is a module which implements the notion of a dataset. Its is + designed for the use with scripting languages. + + copyright: GPL + + Mark Koennecke, October 2002 +*/ +#include +#include +#include "nxdataset.h" + +/*-----------------------------------------------------------------------*/ +static int getTypeSize(int typecode){ + switch(typecode){ + case NX_FLOAT32: + case NX_INT32: + case NX_UINT32: + return 4; + break; + case NX_FLOAT64: + return 8; + break; + case NX_INT16: + case NX_UINT16: + return 2; + break; + default: + return 1; + break; + } +} +/*-----------------------------------------------------------------------*/ +pNXDS createNXDataset(int rank, int typecode, int dim[]){ + pNXDS pNew = NULL; + int i, length; + + 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++){ + length *= dim[i]; + } + pNew->u.ptr = malloc(length*getTypeSize(typecode)); + + 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++){ + pNew->dim[i] = dim[i]; + } + pNew->magic = MAGIC; + memset(pNew->u.ptr,0,length*getTypeSize(typecode)); + return pNew; +} +/*---------------------------------------------------------------------*/ +pNXDS createTextNXDataset(char *name){ + pNXDS pNew = NULL; + + pNew = (pNXDS)malloc(sizeof(NXDS)); + if(pNew == NULL){ + return NULL; + } + pNew->dim = (int *)malloc(sizeof(int)); + pNew->u.cPtr = strdup(name); + if(pNew->dim == NULL || pNew->u.ptr == NULL){ + free(pNew); + return NULL; + } + pNew->rank = 1; + pNew->type = NX_CHAR; + pNew->magic = MAGIC; + pNew->dim[0] = strlen(name); + return pNew; +} +/*-----------------------------------------------------------------------*/ +void dropNXDataset(pNXDS dataset){ + if(dataset == NULL){ + return; + } + if(dataset->magic != MAGIC){ + return; + } + if(dataset->dim != NULL){ + free(dataset->dim); + } + if(dataset->u.ptr != NULL){ + free(dataset->u.ptr); + } + if(dataset->format != NULL){ + free(dataset->format); + } + free(dataset); +} +/*-----------------------------------------------------------------------*/ +int getNXDatasetRank(pNXDS dataset){ + if(dataset == NULL){ + return 0; + } + if(dataset->magic != MAGIC){ + return 0; + } + return dataset->rank; +} +/*-----------------------------------------------------------------------*/ +int getNXDatasetDim(pNXDS dataset, int which){ + if(dataset == NULL){ + return 0; + } + if(dataset->magic != MAGIC){ + return 0; + } + if(which < 0 || which >= dataset->rank){ + return 0; + } + return dataset->dim[which]; +} +/*------------------------------------------------------------------------*/ +int getNXDatasetType(pNXDS dataset){ + if(dataset == NULL){ + return 0; + } + if(dataset->magic != MAGIC){ + return 0; + } + return dataset->type; +} +/*--------------------------------------------------------------------*/ +int getNXDatasetLength(pNXDS dataset){ + int length, i; + + if(dataset == NULL){ + return 0; + } + if(dataset->magic != MAGIC){ + return 0; + } + length = dataset->dim[0]; + for(i = 1; i < dataset->rank; i++){ + length *= dataset->dim[i]; + } + return length; +} +/*---------------------------------------------------------------------*/ +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; + int i, j; + + result = pos[dataset->rank - 1]; + for(i = 0; i < dataset->rank -1; i++){ + mult = 1; + 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]; + } + } + return result; +} +/*-----------------------------------------------------------------------*/ +double getNXDatasetValue(pNXDS dataset, int pos[]){ + int address; + double value; + + if(dataset == NULL){ + return 0; + } + if(dataset->magic != MAGIC){ + return 0; + } + + address = calculateAddress(dataset,pos); + return getNXDatasetValueAt(dataset, address); +} +/*----------------------------------------------------------------------*/ +double getNXDatasetValueAt(pNXDS dataset, int address){ + double value; + + if(dataset == NULL){ + return 0; + } + if(dataset->magic != MAGIC){ + return 0; + } + + switch(dataset->type){ + case NX_FLOAT64: + value = dataset->u.dPtr[address]; + break; + case NX_FLOAT32: + value = (double)dataset->u.fPtr[address]; + break; + case NX_INT32: + case NX_UINT32: + value = (double)dataset->u.iPtr[address]; + break; + case NX_INT16: + case NX_UINT16: + value = (double)dataset->u.sPtr[address]; + break; + default: + value = (double)dataset->u.cPtr[address]; + break; + } + return value; +} +/*-----------------------------------------------------------------------*/ +char *getNXDatasetText(pNXDS dataset){ + char *resultBuffer = NULL; + int length, status = 1; + + if(dataset == NULL){ + status = 0; + } + if(dataset->magic != MAGIC){ + status = 0; + } + 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_INT16 || + dataset->type == NX_UINT16 ) { + status = 0; + } + + if(status == 0){ + return strdup("NO type problem"); + }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]); + } + return resultBuffer; +} +/*----------------------------------------------------------------------*/ +int putNXDatasetValue(pNXDS dataset, int pos[], double value){ + int address; + + if(dataset == NULL){ + return 0; + } + if(dataset->magic != MAGIC){ + return 0; + } + + address = calculateAddress(dataset,pos); + return putNXDatasetValueAt(dataset,address,value); +} + /*---------------------------------------------------------------------*/ +int putNXDatasetValueAt(pNXDS dataset, int address, double value){ + /* + 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; + break; + case NX_INT32: + case NX_UINT32: + dataset->u.iPtr[address] = (int)value; + break; + case NX_INT16: + case NX_UINT16: + dataset->u.sPtr[address] = (short int)value; + break; + default: + dataset->u.cPtr[address] = (char)value; + break; + } + return 1; +} + + + diff --git a/nxdataset.h b/nxdataset.h new file mode 100644 index 00000000..c8613aa1 --- /dev/null +++ b/nxdataset.h @@ -0,0 +1,69 @@ +/* + This is a module which implements the notion of a dataset. Its is + designed for the use with scripting languages. + + copyright: GPL + + Mark Koennecke, October 2002 +*/ +#ifndef NXDATASET +#define NXDATASET + + +#define MAGIC 7776622 + +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; + } u; +}*pNXDS, NXDS; + +/* + include NeXus type codes if not already defined +*/ +#ifndef NX_FLOAT32 + +#define NX_FLOAT32 5 +#define NX_FLOAT64 6 +#define NX_INT8 20 +#define NX_UINT8 21 +#define NX_INT16 22 +#define NX_UINT16 23 +#define NX_INT32 24 +#define NX_UINT32 25 +#define NX_CHAR 4 + +#define NX_MAXRANK 32 + +#endif + + +pNXDS createNXDataset(int rank, int typecode, int dim[]); +pNXDS createTextNXDataset(char *name); + +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); + +double getNXDatasetValue(pNXDS dataset, int pos[]); +double getNXDatasetValueAt(pNXDS dataset, int address); +char *getNXDatasetText(pNXDS dataset); + +int putNXDatasetValue(pNXDS dataset, int pos[], double value); +int putNXDatasetValueAt(pNXDS dataset, int address, double value); + +#endif diff --git a/nxdict.c b/nxdict.c index b053cc2e..7453988d 100644 --- a/nxdict.c +++ b/nxdict.c @@ -733,6 +733,67 @@ /* not reached */ return; } +/*-----------------------------------------------------------------------*/ + static void NXDIAttValue(ParDat *sStat) + { + int i; + + + sStat->pToken[0] = '\0'; + + /* skip whitespace */ + while( (*(sStat->pPtr) == ' ') || (*(sStat->pPtr) == '\t') ) + { + sStat->pPtr++; + } + + if(*(sStat->pPtr) == ',') + { + sStat->iToken = DKOMMA; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } + else if(*(sStat->pPtr) == '\0') + { + sStat->iToken = DEND; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } + else if(*(sStat->pPtr) == '{') + { + sStat->iToken = DOPEN; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } + else if(*(sStat->pPtr) == '}') + { + sStat->iToken = DCLOSE; + sStat->pToken[0] = *(sStat->pPtr); + sStat->pPtr++; + return; + } + else + { + sStat->iToken = DWORD; + /* copy word to pToken */ + i = 0; + while( (*(sStat->pPtr) != ' ') && (*(sStat->pPtr) != '\t') && + (*(sStat->pPtr) != '\0') && + (*(sStat->pPtr) != ',') && (*(sStat->pPtr) != '}') ) + { + sStat->pToken[i] = *(sStat->pPtr); + sStat->pPtr++; + i++; + } + sStat->pToken[i] = '\0'; + return; + } + /* not reached */ + return; + } /*------------------------------------------------------------------------*/ @@ -864,7 +925,7 @@ } /* a word is expected */ - NXDIDefToken(pParse); + NXDIAttValue(pParse); if(pParse->iToken != DWORD) { sprintf(pError,"ERROR: expected attribute value, got %s",pParse->pToken); diff --git a/nxio.c b/nxio.c new file mode 100644 index 00000000..4f156422 --- /dev/null +++ b/nxio.c @@ -0,0 +1,550 @@ +/** + * This file contains functions necessary to perform XML-I/O for + * NeXus with the mxml-library. + * + * Most notably it contains the callback function for reading and + * writing data + * + * Copyright (C) 2004 Mark Koennecke + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * 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 + */ +#include +#include +#include "nxio.h" +#include "nxdataset.h" + +/* #define TESTMAIN 1 */ +/*=================== type code handling ================================= */ +typedef struct { + char name[30]; + char format[30]; + int nx_type; +}type_code; + +static type_code typecode[9]; +/*-----------------------------------------------------------------------*/ +void initializeNumberFormats(){ + type_code myCode; + + 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"); + myCode.nx_type = NX_FLOAT64; + typecode[1] = myCode; + + 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"); + myCode.nx_type = NX_UINT8; + typecode[3] = myCode; + + 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"); + myCode.nx_type = NX_UINT16; + typecode[5] = myCode; + + strcpy(myCode.name,"NX_INT32"); + strcpy(myCode.format,"%12d"); + myCode.nx_type = NX_INT32; + typecode[6] = myCode; + + strcpy(myCode.name,"NX_UNIT32"); + strcpy(myCode.format,"%12d"); + myCode.nx_type = NX_UINT32; + typecode[7] = myCode; + + strcpy(myCode.name,"NX_CHAR"); + strcpy(myCode.format,"%c"); + myCode.nx_type = NX_CHAR; + typecode[8] = myCode; +} +/*----------------------------------------------------------------------*/ +void setNumberFormat(int nx_type, char *format){ + int i; + + for(i = 0; i < 9; i++){ + if(typecode[i].nx_type == nx_type){ + strncpy(typecode[i].format,format,29); + } + } +} +/*------------------------------------------------------------------*/ +static void getNumberFormat(int nx_type, char format[30]){ + int i; + + for(i = 0; i < 9; i++){ + if(typecode[i].nx_type == nx_type){ + strncpy(format,typecode[i].format,29); + } + } +} +/*----------------------------------------------------------------*/ +void getNumberText(int nx_type, char *typestring, int typeLen){ + int i; + + for(i = 0; i < 9; 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 */ + + + if (*bufptr >= (*buffer + *bufsize - 4)) + { + /* + * Increase the size of the buffer... + */ + + if (*bufsize < 1024) + (*bufsize) *= 2; + else + (*bufsize) += 1024; + + 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); + free(*buffer); + + *bufptr = newbuffer + (*bufptr - *buffer); + *buffer = newbuffer; + } + + if (ch < 128) + { + /* + * Single byte ASCII... + */ + + *(*bufptr)++ = ch; + } + else if (ch < 2048) + { + /* + * Two-byte UTF-8... + */ + + *(*bufptr)++ = 0xc0 | (ch >> 6); + *(*bufptr)++ = 0x80 | (ch & 0x3f); + } + 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... + */ + + *(*bufptr)++ = 0xf0 | (ch >> 18); + *(*bufptr)++ = 0x80 | ((ch >> 12) & 0x3f); + *(*bufptr)++ = 0x80 | ((ch >> 6) & 0x3f); + *(*bufptr)++ = 0x80 | (ch & 0x3f); + } + + return (0); +} +/*------------------------------------------------------------------*/ +extern char *stptok(char *s, char *tok, size_t toklen, char *brk); +/*===================================================================== + actual stuff for implementing the callback functions + =====================================================================*/ +static void analyzeDim(const char *typeString, int *rank, + int *iDim, int *type){ + char dimString[132]; + char dim[20]; + char *dimStart, *dimEnd; + int myRank; + + if(strchr(typeString,(int)'[') == NULL){ + switch(*type){ + case NX_INT8: + case NX_UINT8: + case NX_INT16: + case NX_UINT16: + case NX_INT32: + case NX_UINT32: + case NX_FLOAT32: + case NX_FLOAT64: + iDim[0] = 1; + break; + case NX_CHAR: + iDim[0] = -1; + 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); + return; + } + 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,","); + myRank = 0; + while(dimStart != NULL){ + iDim[myRank] = atoi(dim); + dimStart = stptok(dimStart,dim,19,","); + myRank++; + } + *rank = myRank; + } +} +/*--------------------------------------------------------------------*/ +int translateTypeCode(char *code){ + int i, result = -1; + + for(i = 0; i < 9; i++){ + if(strstr(code,typecode[i].name) != NULL){ + result = typecode[i].nx_type; + break; + } + } + return result; +} +/*---------------------------------------------------------------------*/ +static void analyzeDataType(mxml_node_t *parent, int *rank, int *type, + int *iDim){ + const char *typeString; + mxml_type_t myType; + int i, nx_type = -1; + + *rank = 1; + *type = NX_CHAR; + iDim[0] = -1; + + /* + get the type attribute. No attribute means: plain text + */ + typeString = mxmlElementGetAttr(parent,TYPENAME); + if(typeString == NULL){ + return; + } + + 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; + return; + } + + *type = nx_type; + + analyzeDim(typeString, rank, iDim, type); +} +/*-------------------------------------------------------------------*/ +void destroyDataset(void *data){ + if(data != NULL){ + dropNXDataset((pNXDS)data); + } +} +/*-------------------------------------------------------------------*/ +static char *getNextNumber(char *pStart, char pNumber[80]){ + int charCount = 0; + pNumber[0] = '\0'; + + /* advance to first digit */ + while(isspace(*pStart) && *pStart != '\0'){ + pStart++; + } + if(*pStart == '\0'){ + return NULL; + } + + /* copy */ + while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){ + pNumber[charCount] = *pStart; + pStart++; + charCount++; + } + pNumber[charCount] = '\0'; + return pStart; +} +/*--------------------------------------------------------------------*/ +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){ + return MXML_ELEMENT; + } else { + 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 want. + */ + return MXML_OPAQUE; + } else{ + return MXML_CUSTOM; + } + } +} +/*----------------------------------------------------------------------*/ +int nexusLoadCallback(mxml_node_t *node, const char *buffer){ + mxml_node_t *parent = NULL; + int rank, type, 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){ + 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){ + mxml_error("Failed to allocate custom dataset"); + return 1; + } + node->value.custom.destroy = destroyDataset; + } + + /* + load data + */ + pStart = (char *)buffer; + maxAddress = getNXDatasetLength(dataset); + address = 0; + 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; + + 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){ + case NX_INT8: + case NX_UINT8: + case NX_INT16: + case NX_UINT16: + case NX_INT32: + case NX_UINT32: + snprintf(txt,txtLen,format,(int)value); + break; + case NX_FLOAT32: + case NX_FLOAT64: + snprintf(txt,txtLen,format,value); + break; + default: + assert(0); /* something is very wrong here */ + break; + } +} +/*--------------------------------------------------------------------*/ +static int countDepth(mxml_node_t *node){ + int count = 0; + mxml_node_t *cur; + + cur = node; + while(cur != NULL){ + count++; + cur = cur->parent; + } + count--; + return count; +} +/*---------------------------------------------------------------------*/ +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; + + /* + allocate output buffer + */ + buffer = (char *)malloc(1024*sizeof(char)); + if(buffer == NULL){ + mxml_error("Unable to allocate buffer"); + return NULL; + } + memset(buffer,0,1024); + bufPtr = buffer; + bufsize = 1024; + + dataset = (pNXDS)node->value.custom.data; + + /* + prepare indentation level + */ + col = countDepth(node)*2; + memset(indent,0,80); + for(i = 0; i < col; i++){ + indent[i] = ' '; + } + + /* + get dataset info + */ + type = getNXDatasetType(dataset); + 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); + 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; +} +/*---------------------------------------------------------------------*/ +const char *NXwhitespaceCallback(mxml_node_t *node, int where){ + char *indent; + int len; + + if(strstr(node->value.element.name,"?xml") != NULL){ + return NULL; + } + + if(where == MXML_WS_BEFORE_OPEN || where == MXML_WS_BEFORE_CLOSE){ + len = countDepth(node)*2 + 2; + 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; + + mxmlSetCustomHandlers(nexusLoadCallback, nexusWriteCallback); + initializeNumberFormats(); + + /* + read test + */ + 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); + +} +#endif diff --git a/nxio.h b/nxio.h new file mode 100644 index 00000000..f0f5bc64 --- /dev/null +++ b/nxio.h @@ -0,0 +1,45 @@ +/** + * This file contains functions necessary to perform XML-I/O for + * NeXus with the mxml-library. + * + * Most notably it contains the callback function for reading data + * + * Copyright (C) 2004 Mark Koennecke + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * 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 + */ + +#ifndef __NXIO +#define __NXIO +#include + +#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); + +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); + + + +#endif diff --git a/nxscript.c b/nxscript.c index d555d90a..04d9c0e0 100644 --- a/nxscript.c +++ b/nxscript.c @@ -159,6 +159,8 @@ static int handleFileOperations(SConnection *pCon, pNXScript self, } else if(strcmp(argv[1],"create5") == 0){ access = NXACC_CREATE5; unlink(argv[2]); /* kill file for overwrite */ + } else if(strcmp(argv[1],"createxml") == 0){ + access = NXACC_CREATEXML; } else { return 0; } @@ -727,6 +729,91 @@ static void putArray(SConnection *pCon, SicsInterp *pSics, SCSendOK(pCon); } /*----------------------------------------------------------------------*/ +static void putIntArray(SConnection *pCon, SicsInterp *pSics, + pNXScript self, + int argc, char *argv[]){ + int *data = NULL; + int length, i, status; + char num[20]; + char buffer[256], defString[512], *varData; + Tcl_Interp *tcl = NULL; + int iVal; + + if(argc < 5){ + SCWrite(pCon,"ERROR: insufficient number of arguments to array", + eError); + return; + } + tcl = InterpGetTcl(pSics); + assert(tcl != NULL); + + /* + get array length + */ + status = Tcl_GetInt(tcl,argv[4],&length); + if(status != TCL_OK){ + sprintf(buffer,"ERROR: failed to convert %s to integer",argv[4]); + SCWrite(pCon,buffer,eError); + return; + } + + /* + allocate + */ + if(length > 0){ + data = (int *)malloc(length*sizeof(int)); + } + if(data == NULL){ + SCWrite(pCon,"ERROR: out of memory or invalid length",eError); + return; + } + memset(data,0,length*sizeof(int)); + + /* + try getting data + */ + for(i = 0; i < length; i++){ + sprintf(num,"%d",i); + varData = (char *)Tcl_GetVar2(tcl,argv[3],num,0); + if(varData != NULL){ + status = Tcl_GetInt(tcl,varData,&iVal); + if(status != TCL_OK){ + sprintf(buffer,"ERROR: failed to convert %s to int", + varData); + SCWrite(pCon,buffer,eError); + } + data[i] = iVal; + } else { + snprintf(buffer,254,"WARNING: failed to find array element %d", i); + SCWrite(pCon,buffer,eError); + } + } + + /* + build definition string + */ + status = NXDdefget(self->dictHandle,argv[2],buffer,254); + if(!status){ + sprintf(buffer,"ERROR: alias %s for array not found", + argv[2]); + SCWrite(pCon,buffer,eError); + free(data); + return; + } + snprintf(defString,511,"%s -dim {%d} ",buffer,length); + + /* + write it! + */ + status = NXDputdef(self->fileHandle,self->dictHandle,defString,data); + if(status != NX_OK){ + sprintf(buffer,"ERROR: failed to write array"); + SCWrite(pCon,buffer,eError); + } + free(data); + SCSendOK(pCon); +} +/*----------------------------------------------------------------------*/ static void putGlobal(SConnection *pCon, SicsInterp *pSics, pNXScript self, int argc, char *argv[]){ @@ -851,6 +938,9 @@ static int handlePut(SConnection *pCon, SicsInterp *pSics, pNXScript self, }else if(strcmp(argv[1],"putarray") == 0){ /*================*/ putArray(pCon,pSics,self,argc,argv); + }else if(strcmp(argv[1],"putintarray") == 0){ + /*================*/ + putIntArray(pCon,pSics,self,argc,argv); }else if(strcmp(argv[1],"putglobal") == 0){ /*===============*/ putGlobal(pCon,pSics,self,argc,argv); diff --git a/scan.c b/scan.c index be6c1561..4dec8030 100644 --- a/scan.c +++ b/scan.c @@ -94,6 +94,7 @@ static void ConfigureScanDict(pStringDict dict) StringDictAddPair(dict,"collect","stdscan collect"); StringDictAddPair(dict,"writepoint","stdscan writepoint"); StringDictAddPair(dict,"userdata","unknown"); + StringDictAddPair(dict,"finish","stdscan finish"); } /*--------------------------------------------------------------------------*/ pScanData CreateScanObject(char *pRecover, char *pHeader,pCounter pCount, @@ -670,6 +671,7 @@ CountEntry CollectCounterData(pScanData self) self->iActive = 1; iRet = ScanLoop(self); + ScriptScanFinish(self); InvokeCallBack(self->pCall,SCANEND,self); SendQuieck(QUIECK,self->pFile); self->iActive = 0; @@ -834,6 +836,7 @@ CountEntry CollectCounterData(pScanData self) self->iActive = 1; iRet = ScanLoop(self); + ScriptScanFinish(self); InvokeCallBack(self->pCall,SCANEND,self); SendQuieck(QUIECK,self->pFile); self->iActive = 0; diff --git a/scan.tex b/scan.tex index 20677a38..1d99cb0e 100644 --- a/scan.tex +++ b/scan.tex @@ -516,6 +516,10 @@ $\langle$stdscan {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@ */@\\ \mbox{}\verb@ int ScriptScanCollect(pScanData self, int iPoint); @\\ \mbox{}\verb@ /**@\\ +\mbox{}\verb@ * ScriptScanFinish invokes a script after the scan has finished@\\ +\mbox{}\verb@ */@\\ +\mbox{}\verb@ int ScriptScanFinish(pScanData self); @\\ +\mbox{}\verb@ /**@\\ \mbox{}\verb@ * ConfigureScript assigns the script invocation functions for@\\ \mbox{}\verb@ * scan@\\ \mbox{}\verb@ */@\\ diff --git a/scan.w b/scan.w index 083c22e7..53135d5f 100644 --- a/scan.w +++ b/scan.w @@ -461,6 +461,10 @@ documentation. * Script collecting scan data for each scan point */ int ScriptScanCollect(pScanData self, int iPoint); + /** + * ScriptScanFinish invokes a script after the scan has finished + */ + int ScriptScanFinish(pScanData self); /** * ConfigureScript assigns the script invocation functions for * scan diff --git a/stdscan.c b/stdscan.c index ed0824ce..71601976 100644 --- a/stdscan.c +++ b/stdscan.c @@ -860,6 +860,10 @@ int ScriptScanCollect(pScanData self, int iPoint){ int ScriptWriteScanPoints(pScanData self, int iPoint){ return StandardScriptInvokeWithPoint(self,"writepoint",iPoint); } +/*--------------------------------------------------------------------*/ +int ScriptScanFinish(pScanData self){ + return StandardScriptInvoke(self,"finish"); +} /*---------------------------------------------------------------------*/ void ConfigureScript(pScanData self){ assert(self); @@ -890,7 +894,9 @@ int StandardScanWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, return WriteHeader(self); } else if(strcmp(argv[1],"prepare") == 0){ return PrepareScan(self); - } + } else if(strcmp(argv[1],"finish") == 0) { + return 1; + } /* from here on we need a scan point diff --git a/stdscan.h b/stdscan.h index 2a95fa6d..bb7404da 100644 --- a/stdscan.h +++ b/stdscan.h @@ -11,10 +11,6 @@ #ifndef SICSSTDSCAN #define SICSSTDSCAN - /** - * make a scan file name - */ - char *ScanMakeFileName(SicsInterp *pSics, SConnection *pCon); /** * write the header of the scan file */ @@ -33,10 +29,6 @@ /** * second version of PrepareScan which does not check scan limits */ - int SilentPrepare(pScanData self); - /** - * third version of PrepareScan which does not create data files but checks - */ int NonCheckPrepare(pScanData self); /** * ScanDrive handles driving to the scan point iPoint. @@ -84,6 +76,10 @@ * Script collecting scan data for each scan point */ int ScriptScanCollect(pScanData self, int iPoint); + /** + * ScriptScanFinish invokes a script after the scan has finished + */ + int ScriptScanFinish(pScanData self); /** * ConfigureScript assigns the script invocation functions for * scan diff --git a/tasdrive.c b/tasdrive.c index fc702a44..b0b1e7a9 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -633,7 +633,8 @@ int TasMot(SConnection *pCon,SicsInterp *pSics, void *pData, SCWrite(pCon,pBueffel,eValue); return 1; } else { - SCWrite(pCon,"ERROR: tasmot does not understand this subcommand",eError); + snprintf(pBueffel,131,"ERROR: tasmot does not understand %s", argv[1]); + SCWrite(pCon,pBueffel,eError); return 0; } } diff --git a/tasscanub.c b/tasscanub.c index d704f23e..73263930 100644 --- a/tasscanub.c +++ b/tasscanub.c @@ -23,6 +23,7 @@ #include #include #include "tasscanub.h" +#include "nxscript.h" /*------------------------------------------------------------------------ a little local utility for making a line of characters -------------------------------------------------------------------------*/ @@ -968,6 +969,100 @@ int TASUBPrepare(pScanData self) return status; } +/*---------------------------------------------------------------------*/ +static void TASUBDump(pTASdata self, SicsInterp *pSics, SConnection *pCon, + int argc, char *argv[]){ + float v[3], ub[3][3], cell[6]; + int status, i, j; + pNXScript nxscript = NULL; + char pBueffel[256]; + tasReflection r; + + if(argc < 4){ + SCWrite(pCon,"ERROR: not enough argument to dump tasub",eError); + return; + } + + nxscript = (pNXScript)FindCommandData(pSics,argv[2],"NXScript"); + if(nxscript == NULL){ + snprintf(pBueffel,255,"ERROR: %s is no NXScript object", + argv[2]); + SCWrite(pCon,pBueffel,eError); + return; + } + if(nxscript->fileHandle == NULL){ + SCWrite(pCon,"ERROR: files is closed, cannot write",eError); + return; + } + + /* + write cell + */ + snprintf(pBueffel,255,"%s_cell",argv[3]); + cell[0] = self->ub->cell.a; + cell[1] = self->ub->cell.b; + cell[2] = self->ub->cell.c; + cell[3] = self->ub->cell.alpha; + cell[4] = self->ub->cell.beta; + cell[5] = self->ub->cell.gamma; + status = NXDputalias(nxscript->fileHandle,nxscript->dictHandle,pBueffel,cell); + if(status != NX_OK){ + snprintf(pBueffel,255,"ERROR: failed to write cell to %s_cell",argv[3]); + SCWrite(pCon,pBueffel,eWarning); + } + + /* + write planenormal + */ + for(i = 0; i < 3; i++){ + v[i] = self->ub->machine.planeNormal[i][0]; + } + snprintf(pBueffel,255,"%s_norm",argv[3]); + status = NXDputalias(nxscript->fileHandle,nxscript->dictHandle,pBueffel,v); + if(status != NX_OK){ + snprintf(pBueffel,255,"ERROR: failed to write plane_normal to %s_norm",argv[3]); + SCWrite(pCon,pBueffel,eWarning); + } + + /* + write orienting reflections + */ + snprintf(pBueffel,255,"%s_vec1",argv[3]); + findReflection(self->ub->reflectionList, self->ub->r1,&r); + v[0] = r.qe.qh; + v[1] = r.qe.qk; + v[2] = r.qe.ql; + status = NXDputalias(nxscript->fileHandle,nxscript->dictHandle,pBueffel,v); + if(status != NX_OK){ + snprintf(pBueffel,255,"ERROR: failed to write plane vector 1 to %s_vec1",argv[3]); + SCWrite(pCon,pBueffel,eWarning); + } + snprintf(pBueffel,255,"%s_vec2",argv[3]); + findReflection(self->ub->reflectionList, self->ub->r2,&r); + v[0] = r.qe.qh; + v[1] = r.qe.qk; + v[2] = r.qe.ql; + status = NXDputalias(nxscript->fileHandle,nxscript->dictHandle,pBueffel,v); + if(status != NX_OK){ + snprintf(pBueffel,255,"ERROR: failed to write plane vector 2 to %s_vec2",argv[3]); + SCWrite(pCon,pBueffel,eWarning); + } + + /* + write UB + */ + for(i = 0; i < 3; i++){ + for(j = 0; j < 3; j++){ + ub[i][j] = self->ub->machine.UB[i][j]; + } + } + snprintf(pBueffel,255,"%s_ub",argv[3]); + status = NXDputalias(nxscript->fileHandle,nxscript->dictHandle,pBueffel,ub); + if(status != NX_OK){ + snprintf(pBueffel,255,"ERROR: failed to write UB to %s_ub",argv[3]); + SCWrite(pCon,pBueffel,eWarning); + } +} /*----------------------------------------------------------------------*/ int TASUBScan(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ @@ -1014,6 +1109,9 @@ int TASUBScan(SConnection *pCon, SicsInterp *pSics, void *pData, } } else if(strcmp(argv[1],"prepare") == 0){ return TASUBPrepare(self->pScan); + } else if(strcmp(argv[1],"nxdump") == 0){ + TASUBDump(self,pSics,pCon,argc,argv); + return 1; } else if(strcmp(argv[1],"drive") == 0){ if(argc < 5) { SCWrite(pCon,"ERROR: insufficient number of arguments to tasscan drive",