1851 lines
72 KiB
TeX
1851 lines
72 KiB
TeX
% 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 <stdlib.h>@\\
|
|
\mbox{}\verb@#include <assert.h>@\\
|
|
\mbox{}\verb@#include <string.h>@\\
|
|
\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 <mfhdf.h>@\\
|
|
\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}
|