AMROC Main     Blockstructured Adaptive Mesh Refinement in object-oriented C++


Main Page   Class Hierarchy   Compound List   File List  

sds.c

Go to the documentation of this file.
00001 
00006 #include <stdio.h>
00007 #include <stdlib.h>
00008 /*#include <bstring.h>*/
00009 #include <strings.h>
00010 #include <time.h>
00011 
00012 #include "sds.h"
00013 
00014  /*@@
00015    @file      sds.c
00016    @date      Wed Feb 26 20:05:00 1996
00017    @author   John Shalf 
00018    @desc 
00019    The SDS routines are a wrapper for the HDF SD interface
00020    that allows you to refer to files by name instead of
00021    explicitly opening them and refering to them by fileID.
00022    This file contain all of the source code that implements
00023    these wrappers.
00024    @enddesc 
00025    @includes sds.h
00026    @seeheader sds.h
00027    @version 0.9a
00028  @@*/
00029 
00030 static int32 DefaultNumberType=DFNT_FLOAT32;
00031 static int32 nfiles=0,maxfiles=54;
00032 
00033 /* Need to set the default NumberType!!!! */
00034 
00035 typedef struct fileID {
00036   char componentname[128];
00037   char filename[256];
00038   char sds_name[MAX_NC_NAME];  /* to keep track of SDS name internally */
00039   int32 id,sds_id,sdsnumber,nsds,nattrib,numbertype;
00040   int32 accessflags;
00041   clock_t lastaccess; /* in clock ticks.  Uses clock().  CLOCKS_PER_SEC */
00042   struct fileID *next;
00043 }fileID;  
00044 
00045 static fileID *files=NULL;
00046 
00047  /*@@
00048    @routine    deactivateOldFiles
00049    @date       Wed Feb 28 15:37:43 1996
00050    @desc 
00051         Finds the filesID's with longest time since last reference
00052         and deactivates the worst 1/8 of them to free up some
00053         file descriptors.
00054    @enddesc 
00055    @seeroutine SDSdeactivate SDSreactivate getFileID
00056    @calledby   NewFileID
00057 
00058    @history 
00059    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf 
00060    @hdesc Initial Version   
00061    @endhistory 
00062  @@*/
00063 static
00064 void deactivateOldFiles() 
00065 {
00066   fileID *tmpid;
00067   int i,ntimes;
00068   clock_t *worst_times;
00069   ntimes=maxfiles>>3; /* Ok, divide by 8 */
00070   ntimes=ntimes?ntimes:1; /* make sure its >0 */
00071   /* It was the best of times... it was the worst of times... */
00072   worst_times=(clock_t *)calloc(ntimes,sizeof(clock_t));
00073   /* first search for the top-1/8 longest times since last access */
00074   for(tmpid=files;tmpid;tmpid=tmpid->next){
00075     clock_t t=tmpid->lastaccess;
00076     if(tmpid->id<0) continue;
00077     for(i=0;i<ntimes;i++){      
00078       if(t<=worst_times[i]){ /* swap */
00079         clock_t tmp=worst_times[i];
00080         worst_times[i]=t;
00081         t=tmp; /* now looking for second-worst time */
00082       }
00083     }
00084   }
00085   /* next deactivate those top-10% */
00086   for(tmpid=files;tmpid;tmpid=tmpid->next)
00087     if(tmpid->id && tmpid->lastaccess<=worst_times[ntimes-1]) 
00088       SDSdeactivate(tmpid->filename); /* deactivate it */
00089   free(worst_times);
00090 }
00091 
00092  /*@@
00093    @routine    NewFileID
00094    @date       Wed Feb 28 15:37:43 1996
00095    @desc 
00096         Creates a new fileID structure, opens the file and
00097         initializes all of the structure elements. 
00098    @enddesc 
00099    @calledby   SDSopen getFileID
00100    @calls deactivateOldFiles
00101 
00102    @par     name
00103    @pdesc   Name of the HDF file to open or create
00104    @ptype   char*
00105    @endpar 
00106 
00107    @par     access
00108    @pdesc   Access mode for the file (uses ANSI C access modes)
00109    @ptype   char*
00110    @pvalues "r","w","rw","w+","ra"
00111    @endpar 
00112 
00113    @history 
00114    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf 
00115    @hdesc Initial Version   
00116    @endhistory 
00117  @@*/
00118 fileID *NewFileID(char *name,char *access) {
00119   fileID *id=(fileID *)calloc(sizeof(fileID),1);
00120   strcpy(id->componentname,name);
00121   strcpy(id->filename,name);
00122   /* make certain that there are enough file descriptors around */
00123   if(nfiles==maxfiles) /* gotta deactivate a few */
00124     deactivateOldFiles();
00125   
00126   /* open SDS */
00127   if(*access=='r'){
00128     if(access[1]=='w'){ 
00129       id->id=SDstart(id->filename,id->accessflags=DFACC_RDWR);
00130       if(id->id<0){
00131         /* kludge around HDF bug */
00132         id->id=SDstart(id->filename,id->accessflags=DFACC_CREATE);
00133       }
00134       SDfileinfo(id->id,&(id->nsds),&(id->nattrib));
00135       id->sdsnumber=0; /* end of file */
00136       if(id->accessflags!=DFACC_CREATE)
00137         id->sds_id=SDselect(id->id,0); /* goto first */
00138       else
00139         id->sds_id=-1;
00140     }
00141     else if (access[1]=='a' || access[1]=='+') {
00142       id->id=SDstart(id->filename,id->accessflags=DFACC_RDWR);
00143       nfiles++; 
00144       if(id->id<0){
00145         /* kludge around HDF bug */
00146         id->id=SDstart(id->filename,id->accessflags=DFACC_CREATE);
00147       }
00148       SDfileinfo(id->id,&(id->nsds),&(id->nattrib));
00149       id->sdsnumber=id->nsds; /* end of file */
00150       if(id->accessflags!=DFACC_CREATE)
00151         id->sds_id=SDselect(id->id,id->sdsnumber); /* goto last */
00152       else
00153         id->sds_id=-1;
00154     }
00155     else {
00156       id->id=SDstart(id->filename,id->accessflags=DFACC_RDONLY);
00157       SDfileinfo(id->id,&(id->nsds),&(id->nattrib));
00158       id->sdsnumber=0; /* end of file */
00159       id->sds_id=SDselect(id->id,id->sdsnumber); /* means, need to create */
00160     }
00161   }
00162   else if(*access=='w'){
00163     if(access[1]=='\0'){
00164       id->id=SDstart(id->filename,id->accessflags=DFACC_CREATE);
00165       id->sdsnumber=id->nsds=0; /* end of file */
00166       id->sds_id=-1; /* means, need to create */
00167     }
00168     else{
00169       id->id=SDstart(id->filename,id->accessflags=DFACC_ALL);
00170       SDfileinfo(id->id,&(id->nsds),&(id->nattrib));
00171       id->sdsnumber=id->nsds;
00172       id->sds_id=SDselect(id->id,id->sdsnumber); /* goto last */
00173     }
00174   }
00175   if(id->id >= 0)
00176     nfiles++; /* it has been opened successfully */
00177   id->lastaccess=clock();
00178   id->numbertype=DefaultNumberType;
00179   id->next=files;
00180   files=id;
00181   return id;
00182 }
00183 
00184  /*@@
00185    @routine    findIDbyComponent
00186    @date       Wed Feb 28 20:37:43 1996
00187    @desc
00188         Finds a File ID given the name of the component
00189         that the file contains.  This is to support a
00190         user interface style in which the componentnames
00191         can be used as alias for the actual filename.
00192    @enddesc
00193 
00194    @par     name
00195    @pdesc   Name of the component.
00196    @ptype   char*
00197    @endpar
00198 
00199    @history
00200    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00201    @hdesc Initial Version
00202    @endhistory
00203  @@*/
00204 
00205 fileID *findIDbyComponent(char *name) 
00206 {
00207   fileID *id;
00208   for(id=files;id!=NULL;id=id->next)
00209     if(!strcmp(name,id->componentname))
00210       break;
00211   return id;
00212 }
00213 
00214  /*@@
00215    @routine    findIDbyFilename
00216    @date       Wed Feb 28 20:37:43 1996
00217    @desc
00218         Finds a File ID given the name of the component
00219         that the file contains.  This is to support a
00220         user interface style in which the componentnames
00221         can be used as alias for the actual filename.
00222    @enddesc
00223    @calledby   SDSopen SDSclose SDSdeactivate SDSreactivate getFileID
00224 
00225    @par     name
00226    @pdesc   Name of the HDF file.
00227    @ptype   char*
00228    @endpar
00229 
00230    @history
00231    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00232    @hdesc Initial Version
00233    @endhistory
00234  @@*/
00235 fileID *findIDbyFilename(char *name) 
00236 {
00237   fileID *id;
00238   for(id=files;id!=NULL;id=id->next)
00239     if(!strcmp(name,id->filename))
00240       break;
00241   return id;
00242 }
00243 
00244  /*@@
00245    @routine    removeFileID
00246    @date       Wed Feb 28 20:37:43 1996
00247    @desc
00248         Remove a file ID reference and free associated memory.
00249         It does not close the HDF file if is left open though.
00250    @enddesc
00251    @calledby   SDSclose getFileID
00252 
00253    @par     name
00254    @pdesc   Name of the file.
00255    @ptype   char*
00256    @endpar
00257 
00258    @history
00259    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00260    @hdesc Initial Version
00261    @endhistory
00262  @@*/
00263 void removeFileID(char *filename)
00264 {
00265   fileID *id,*lastid,*nextid=0;
00266 
00267   for(lastid=0,id=files;id;lastid=id,id=nextid) {
00268     if(!strcmp(id->filename,filename)){
00269       nextid=id->next;
00270       if(!lastid){
00271         files=id->next;
00272       }
00273       else {
00274         lastid->next=id->next;
00275       }
00276       free(id);
00277     }
00278   }
00279 }
00280 
00281 /*@@
00282  @routine    SDScomputeSize
00283    @date       Wed Feb 28 15:37:43 1996
00284    @desc
00285         Computes the Size in bytes required to store a dataset
00286         based on its dimensions and datatype.
00287    @enddesc
00288    @seeroutine SDSgetDims SDSreadData
00289 
00290    @par rank
00291    @pdesc Number of dimensions in the dataset
00292    @ptype int32
00293    @endpar
00294 
00295    @par dims
00296    @pdesc The size of each dimension in the dataset (in elements).
00297    @ptype int32*
00298    @endpar
00299 
00300    @par datatype
00301    @pdesc The HDF datatype for each element in the dataset.
00302    @ptype int32*
00303    @endpar
00304 
00305    @history
00306    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00307    @hdesc Initial Version
00308    @endhistory
00309 @@*/
00310 long SDScomputeSize(int32 rank,int32 *dims,int32 datatype)
00311 {
00312   register int i,n;
00313   register long nbytes;
00314   for(nbytes=1,n=rank,i=0;i<n;i++){
00315     nbytes*=dims[i];
00316   }
00317   nbytes*=DFKNTsize(datatype);
00318   return nbytes;
00319 }
00320 
00321  /*@@
00322    @routine    SDScloseAll
00323    @date       Wed Feb 28 15:37:43 1996
00324    @desc
00325         Closes and all SDS files and deallocates all
00326         in-memory datastructures used by the SDS routines.
00327    @enddesc
00328    @seeroutine SDSclose
00329 
00330    @history
00331    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00332    @hdesc Initial Version
00333    @endhistory
00334  @@*/
00335 void SDScloseAll()
00336 {
00337   fileID *id,*nextid;
00338   for(id=files;id;id=nextid) {
00339     nextid=id->next;
00340     if(id->sds_id>=0)
00341       SDendaccess(id->sds_id); 
00342     id->sds_id=-1;
00343     if(id->id>=0){
00344       nfiles--;
00345       SDend(id->id);
00346     }
00347     id->id=-1;
00348     free(id); 
00349   }
00350   files=NULL;
00351 }
00352 
00353  /*@@
00354    @routine    SDSdeactivate
00355    @date       Wed Feb 28 15:37:43 1996
00356    @desc
00357         Closes and HDF file but preserves its access state so
00358         that it can be reactivated later.  Used to free up 
00359         file descriptors temporarily when more files are 
00360         active than there are file descriptors availible.
00361         Used for "file descriptor juggling".
00362    @enddesc
00363    @seeroutine SDSreactivate
00364    @calledby   getFileID
00365    @calls      findIDbyFilename
00366 
00367    @par     name
00368    @pdesc   Name of the HDF file
00369    @ptype   char*
00370    @endpar
00371 
00372    @history
00373    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00374    @hdesc Initial Version
00375    @endhistory
00376  @@*/
00377 
00378 /* make file handle inactive (use if shortage of descriptors) */
00379 void SDSdeactivate(char *filename) 
00380 {
00381   fileID *id=findIDbyFilename(filename);
00382   if(id){
00383     if(id->sds_id)
00384       SDendaccess(id->sds_id);
00385     SDend(id->id);
00386     id->id=-1;
00387     nfiles--;
00388     if(id->accessflags==DFACC_CREATE) 
00389       id->accessflags=DFACC_RDWR; /* make sure it doesn't purge the file
00390                                      on reactivation */
00391   }
00392 }
00393 
00394 
00395 /*@@
00396    @routine    SDSreactivate
00397    @date       Wed Feb 28 15:37:43 1996
00398    @desc
00399         Reopens an HDF file closed by SDSdeactivate and
00400         returns it to its original state.
00401    @enddesc 
00402    @seeroutine SDSdeactivate
00403    @calledby   getFileID
00404    @calls      findIDbyFilename
00405 
00406    @par     name
00407    @pdesc   Name of the HDF file
00408    @ptype   char*
00409    @endpar
00410 
00411    @history
00412    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00413    @hdesc Initial Version
00414    @endhistory
00415  @@*/
00416 void SDSreactivate(char *filename)
00417 {
00418   fileID *id=findIDbyFilename(filename);
00419   if(id && id->id < 0){
00420     id->id=SDstart(filename,id->accessflags);
00421     if(id->id)
00422       nfiles++;
00423     if(id->sds_id>=0)
00424       id->sds_id=SDselect(id->id,id->sdsnumber);
00425   }
00426 }
00427 
00428 /*@@
00429    @routine    SDSclose
00430    @date       Wed Feb 28 15:37:43 1996
00431    @desc
00432         Closes an HDF file and removes its state description
00433         from memory.
00434    @enddesc 
00435    @seeroutine SDSopen SDSdeactivate SDSreactivate
00436    @calls      findIDbyFilename
00437 
00438    @par     name
00439    @pdesc   Name of the HDF file
00440    @ptype   char*
00441    @endpar
00442 
00443    @history
00444    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00445    @hdesc Initial Version
00446    @endhistory
00447  @@*/
00448 void SDSclose(char *filename)
00449 {
00450   fileID *id=findIDbyFilename(filename);
00451   if(id) {    
00452     SDend(id->id);
00453     nfiles--;
00454     removeFileID(filename);
00455   }
00456 }
00457 
00458  /*@@
00459    @routine    getFileID
00460    @date       Wed Feb 28 20:37:43 1996
00461    @desc
00462         Checks to see if the specified file is open.
00463         If it isn't already availbile, it opens it
00464         in read-write mode.  Otherwise return the existing
00465         fileID structure.
00466    @enddesc
00467    @calls findIDbyFilename
00468    @calledby   SDSopen SDSflush SDSpurge SDSseek SDSseekName SDSgetIndex
00469                SDSisCoord SDSgetFileInfo SDSgetDataName SDSgetNumDatasets
00470                SDSgetDims SDSgetNT SDSsetNT SDSreadData SDSreadChunk
00471                SDSallocateDataset SDSwriteData SDSwriteChunk
00472                SDSaddAnnotation SDSgetAnnotationSize SDSgetAnnotation
00473                SDSgetNumAttribs SDSwriteAttrib SDSreadAttrib 
00474                SDSfindAttribInfo SDSgetAttribInfo SDSgetDataStrs
00475                
00476 
00477    @par     name
00478    @pdesc   Name of the HDF file.
00479    @ptype   char*
00480    @endpar
00481 
00482    @history
00483    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00484    @hdesc Initial Version
00485    @endhistory
00486  @@*/
00487 fileID *getFileID(char *filename)
00488 {
00489   fileID *id=findIDbyFilename(filename);
00490   if(!id)
00491     id=NewFileID(filename,"rw");
00492   else
00493     id->lastaccess=clock();
00494   if(id->id<0)
00495     SDSreactivate(filename); /* could be more efficient */
00496   return id;
00497 }
00498 
00499 /*@@
00500    @routine    SDSopen
00501    @date       Wed Feb 28 15:37:43 1996
00502    @desc
00503          Opens an HDF file in specified access mode.
00504    @enddesc 
00505    @seeroutine SDSclose SDSdeactivate SDSreactivate
00506    @calls      findIDbyFilename NewFileID
00507 
00508    @par     name
00509    @pdesc   Name of the HDF file
00510    @ptype   char*
00511    @endpar
00512 
00513    @par     access
00514    @pdesc   Access mode for the file (uses ANSI C access modes)
00515    @ptype   char*
00516    @pvalues "r","w","rw","w+","ra"
00517    @endpar 
00518 
00519    @history
00520    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00521    @hdesc Initial Version
00522    @endhistory
00523  @@*/
00524 void SDSopen(char *filename,char *access)
00525 {
00526   fileID *id=findIDbyFilename(filename);
00527   if(!id)
00528     id=NewFileID(filename,access);
00529 }
00530 
00531 /*@@
00532    @routine    SDSflush
00533    @date       Wed Feb 28 15:37:43 1996
00534    @desc
00535          Flushes the HDF file so that if a crash occurs, 
00536          the contents of the file will be preserved. (currently disabled)
00537    @enddesc 
00538    @seeroutine SDSclose SDSdeactivate SDSreactivate
00539    @calls      findIDbyFilename SDSdeactivate SDSreactivate
00540 
00541    @par     name
00542    @pdesc   Name of the HDF file
00543    @ptype   char*
00544    @endpar 
00545 
00546    @history
00547    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00548    @hdesc Initial Version
00549    @hdate Tues March 8 
00550    @hdesc Commented out deactivate/reactivate due to file access mode problems (must fix later)
00551    @endhistory
00552  @@*/
00553 void SDSflush(char *filename)
00554 {
00555   fileID *id=findIDbyFilename(filename);
00556   if(id && id->sds_id>=0)
00557     SDendaccess(id->sds_id);
00558   /*
00559   SDSdeactivate(filename);
00560   SDSreactivate(filename);
00561   */
00562 }
00563 
00564 /*@@
00565    @routine    SDSpurge
00566    @date       Wed Feb 28 15:37:43 1996
00567    @desc
00568          Purges an HDF file, removing all of its contents.
00569          Can Use to garauntee that you are writing into a
00570          fresh HDF file since the default way SDS opens 
00571          a file is Read/Write/Append mode.
00572          Potentially dangerous routine...
00573    @enddesc 
00574    @calls      SDSclose SDSopen
00575 
00576    @par     name
00577    @pdesc   Name of the HDF file
00578    @ptype   char*
00579    @endpar 
00580 
00581    @history
00582    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00583    @hdesc Initial Version
00584    @endhistory
00585  @@*/
00586 void SDSpurge(char *filename)
00587 {
00588   SDSclose(filename);
00589   SDSopen(filename,"w");
00590 }
00591 
00592 /*@@
00593    @routine    SDSseek
00594    @date       Wed Feb 28 15:37:43 1996
00595    @desc
00596          Allows random acces in HDF files.
00597          Moves to the sds in the file specified by setnum.
00598    @enddesc 
00599    @calls      getFileID
00600 
00601    @par     name
00602    @pdesc   Name of the HDF file
00603    @ptype   char*
00604    @endpar 
00605 
00606    @par     setnum
00607    @pdesc   Index of the dataset in the HDf file
00608    @ptype   int
00609    @endpar 
00610 
00611    @history
00612    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00613    @hdesc Initial Version
00614    @endhistory
00615  @@*/
00616 void SDSseek(char *filename,int setnum) 
00617 {
00618   fileID *id=getFileID(filename);
00619   id->sdsnumber=setnum;
00620   id->sds_id=SDselect(id->id,id->sdsnumber);
00621 }
00622 
00623 /*@@
00624    @routine    SDSseekName
00625    @date       Wed Feb 28 15:37:43 1996
00626    @desc
00627          Allows random acces in HDF files.
00628          Moves to the sds in the file with the name specified by "dataname".
00629    @enddesc 
00630    @calls      getFileID
00631 
00632    @par     name
00633    @pdesc   Name of the HDF file
00634    @ptype   char*
00635    @endpar 
00636 
00637    @par     dataname
00638    @pdesc   Name of the dataset in the HDf file
00639    @ptype   char*
00640    @endpar 
00641 
00642    @history
00643    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00644    @hdesc Initial Version
00645    @endhistory
00646  @@*/
00647 int32 SDSseekName(char *filename,char *dataname)
00648 {
00649   fileID *id=getFileID(filename);
00650   id->sdsnumber=SDnametoindex(id->id,dataname);
00651   id->sds_id=SDselect(id->id,id->sdsnumber);
00652   return id->sdsnumber;
00653 }
00654 
00655 /*@@
00656    @routine    SDSgetNT
00657    @date       Wed Feb 28 15:37:43 1996
00658    @desc
00659            Gets the numbertype of the current SDS.
00660    @enddesc 
00661    @calls      getFileID
00662 
00663    @par     name
00664    @pdesc   Name of the HDF file
00665    @ptype   char*
00666    @endpar 
00667 
00668    @history
00669    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00670    @hdesc Initial Version
00671    @endhistory
00672  @@*/
00673 /* analogue to DFSDgetDims()
00674    it gets the AMR attributes of the next SDS */
00675 int32 SDSgetNT(char *filename)
00676 {
00677   int32 numbertype,attribs,rank,dims[MAX_VAR_DIMS];
00678   fileID *id=getFileID(filename);
00679   if(id->sds_id<0)
00680     id->sds_id=SDselect(id->id,id->sdsnumber);
00681   if(id->sds_id<0)
00682     return -1;  
00683   SDgetinfo(id->sds_id,NULL,&rank,dims,&numbertype,&attribs);
00684   id->numbertype=numbertype;
00685   return numbertype;
00686 }
00687 
00688 /*@@
00689    @routine    SDSisCoord
00690    @date       Wed Feb 28 15:37:43 1996
00691    @desc
00692            Returns 1 if the current dataset is a coordinate array
00693            and false if it is not.  This is a direct passthru of
00694            the function SDisCoordVar().  This function has become
00695            necessary because in order to make HDF compatible with
00696            NetCDF, the files the designers had to disable its ability
00697            to tell the difference between datasets and stored coordinates
00698            for the datasets.
00699    @enddesc 
00700    @calls      getFileID
00701 
00702    @par     name
00703    @pdesc   Name of the HDF file
00704    @ptype   char*
00705    @endpar 
00706 
00707    @history
00708    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00709    @hdesc Initial Version
00710    @endhistory
00711  @@*/
00712 int32 SDSisCoord(char *filename)
00713 {
00714   fileID *id=getFileID(filename);
00715   if(id->sds_id<0)
00716     id->sds_id=SDselect(id->id,id->sdsnumber);
00717   if(id->sds_id<0)
00718     return -1;  
00719   return SDiscoordvar(id->sds_id);
00720 }
00721 
00722 /*@@
00723    @routine    SDSsetNT
00724    @date       Wed Feb 28 15:37:43 1996
00725    @desc
00726           Sets the default numbertype for a particular
00727           HDF file.  All further write operations will assume
00728           this numbertype until SDSsetNT is used again to
00729           select a new numbertype.<p>
00730 
00731           The default numbertype is DFNT_FLOAT32 (32 bit float)   
00732    @enddesc 
00733    @calls      getFileID
00734 
00735    @par     name
00736    @pdesc   Name of the HDF file
00737    @ptype   char*
00738    @endpar 
00739 
00740    @par     numbertype
00741    @pdesc   Numbertype for subsequent data writes
00742    @ptype   char*
00743    @pvalues DFNT_FLOAT32 (32-bit float), DFNT_FLOAT64 (64-bit float/double), 
00744             DFNT_INT8 (char), DFNT_INT16 (short int), DFNT_INT32,(int),
00745             DFNT_UINT8 (unsigned char), DFNT_UNINT16 (unsigned short), 
00746             DFNT_UINT32 (unsigned int),
00747             DFNT_NATIVE (if bit-OR'ed with the above, uses machine native format)
00748             
00749    @endpar 
00750 
00751    @history
00752    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00753    @hdesc Initial Version
00754    @endhistory
00755  @@*/
00756 void SDSsetNT(char *filename,int32 numbertype)
00757 {
00758    fileID *id=getFileID(filename);
00759    id->numbertype=numbertype;
00760 }
00761 
00762 
00763 /*@@
00764    @routine    SDSgetDims
00765    @date       Wed Feb 28 15:37:43 1996
00766    @desc
00767           Reads data from an HDF file.
00768           This must be preceded by an SDSgetDims() which
00769           returns the dimensions of the data so that the user
00770           can allocate the space to read in the data.
00771    @enddesc
00772    @seeroutine SDSreadData
00773    @calls      getFileID
00774 
00775    @par     filename
00776    @pdesc   Name of the HDF file
00777    @ptype   char*
00778    @endpar 
00779 
00780    @par     name
00781    @pdesc   Name of the dataset (read from the file)
00782    @ptype   char*
00783    @endpar 
00784 
00785    @par     rank
00786    @pdesc   Number of dimension in the dataset
00787    @ptype   int32
00788    @endpar 
00789 
00790    @par     dims
00791    @pdesc   Dimensions of the dataset
00792    @ptype   int32*
00793    @endpar 
00794 
00795    @par     data
00796    @pdesc   Pointer to the actual dataset (preallocated by the user)
00797    @ptype   VOIDP
00798    @endpar 
00799 
00800    @history
00801    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00802    @hdesc Initial Version
00803    @endhistory
00804  @@*/
00805 long SDSgetDims (char *filename,char *dataname,int32 *rank,int32 *dims)
00806 {
00807   int32 numbertype,attribs;
00808   long status;
00809   fileID *id=getFileID(filename);
00810   if(id->sds_id>=0)
00811     SDendaccess(id->sds_id);
00812   id->sds_id=SDselect(id->id,(id->sdsnumber)++);
00813   if(id->sds_id<0)
00814     return -1;  
00815   status=SDgetinfo(id->sds_id,dataname,rank,dims,&numbertype,&attribs);
00816   if(status>=0){
00817     id->numbertype=numbertype;
00818     id->nattrib = attribs;
00819     SDScomputeSize(*rank,dims,numbertype);
00820                 return 0;
00821   }
00822   else
00823     return -1;
00824 }
00825 /*@@
00826    @routine    SDSreadData
00827    @date       Wed Feb 28 15:37:43 1996
00828    @desc
00829           Reads data from an HDF file.
00830           This must be preceded by an SDSgetDims() which
00831           returns the dimensions of the data so that the user
00832           can allocate the space to read in the data.
00833    @enddesc
00834    @seeroutine SDSgetDims
00835    @calls      getFileID
00836 
00837    @par     filename
00838    @pdesc   Name of the HDF file
00839    @ptype   char*
00840    @endpar 
00841 
00842    @par     dataname
00843    @pdesc   Name of the dataset (read from the file)
00844    @ptype   char*
00845    @endpar 
00846 
00847    @par     rank
00848    @pdesc   Number of dimension in the dataset
00849    @ptype   int32
00850    @endpar 
00851 
00852    @par     dims
00853    @pdesc   Dimensions of the dataset
00854    @ptype   int32*
00855    @endpar 
00856 
00857    @par     data
00858    @pdesc   Pointer to the actual dataset (preallocated by the user)
00859    @ptype   VOIDP
00860    @endpar 
00861 
00862    @history
00863    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00864    @hdesc Initial Version
00865    @endhistory
00866  @@*/
00867 int SDSreadData(char *filename,int32 rank,int32 *dims,VOIDP data)
00868 {
00869   static int32 originS[5]={0,0,0,0,0},*origin;
00870   int status;
00871   fileID *id=getFileID(filename);
00872   if(id->sds_id<0)
00873     id->sds_id=SDselect(id->id,id->sdsnumber);
00874 
00875   if(rank > 5) {
00876     origin=(int32 *)calloc(sizeof(int),rank); /* origin is zeroed */
00877   }
00878   else 
00879     origin=originS;
00880   if(id->sds_id<0)
00881     id->sds_id=SDselect(id->id,id->sdsnumber);
00882   if(id->sds_id<0)
00883     return -1;
00884   /*SDgetinfo(id->sds_id,NULL,&rank,dims,&(id->numbertype),&(id->nattrib));*/
00885   status = SDreaddata(id->sds_id,origin,NULL,dims,data);
00886   if(origin!=originS) 
00887     free(origin);
00888   if(status>=0)
00889     return SDScomputeSize(rank,dims,id->numbertype);
00890   else
00891     return -1;
00892 }
00893 
00894 
00895 
00896 /*@@
00897    @routine    SDSreadChunk
00898    @date       Wed Feb 28 15:37:43 1996
00899    @desc
00900           Reads a subsection (chunk) of data from a selected dataset.
00901           You can specify any origin, stride, and region-
00902           of-interest within the total size of the dataset.
00903 
00904           A dataset must have been selected by an SDSgetDims() which
00905           returns the total dimensions of the data.  Once selected
00906           though, it can be followed by any number of reads.
00907    @enddesc
00908    @seeroutine SDSgetDims
00909    @calls      getFileID
00910 
00911    @par     filename
00912    @pdesc   Name of the HDF file
00913    @ptype   char*
00914    @endpar 
00915 
00916    @par     rank
00917    @pdesc   Number of dimension in the dataset
00918    @ptype   int32
00919    @endpar 
00920 
00921    @par     dims
00922    @pdesc   Dimensions of the dataset to read
00923    @ptype   int32*
00924    @endpar 
00925 
00926    @par     origin
00927    @pdesc   Origin of the read within the dataset
00928    @ptype   int32*
00929    @endpar 
00930 
00931    @par     stride
00932    @pdesc   Stride of the read in each dimension
00933    @ptype   int32*
00934    @endpar 
00935 
00936    @par     data
00937    @pdesc   Pointer to the actual dataset (preallocated by the user)
00938    @ptype   VOIDP
00939    @endpar 
00940 
00941    @history
00942    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
00943    @hdesc Initial Version
00944    need to eliminate chunk reading inefficiency.
00945    Basically, it needs to re-read the chunkname on every cycle
00946    which results in a lot of unneccessary seeking.  To
00947    optimize, will need to store the sds name internally and
00948    only get it again if its a different sds.  Either that
00949    or just separate readNamedChunk from this one.
00950    @hdate Tues Mar 8 @hauthor
00951    @hdesc Eliminated "name" from parameter list.
00952    Depends on SDSgetDims to read the name now.
00953    @endhistory
00954  @@*/
00955 int SDSreadChunk(char *filename,int32 rank,int32 *dims,
00956                       int32 *origin,int32 *stride,VOIDP data)
00957 {
00958   static int32 originS[5]={0,0,0,0,0};
00959   int status;
00960   char name[MAX_NC_NAME];
00961   fileID *id=getFileID(filename);
00962   if(!origin){
00963     if(rank > 5) {
00964       origin=(int32 *)calloc(sizeof(int),rank); /* origin is zeroed */
00965     }
00966     else 
00967       origin=originS;
00968   }
00969   if(id->sds_id<0){
00970     id->sds_id=SDselect(id->id,id->sdsnumber);
00971     if(id->sds_id<0)
00972       return -1;
00973     SDgetinfo(id->sds_id,name,&rank,dims,&(id->numbertype),&(id->nattrib));
00974   }
00975   status = SDreaddata(id->sds_id,origin,stride,dims,data);
00976   if(origin!=originS) 
00977     free(origin);
00978   return status;
00979 }
00980 
00981 
00982 /*@@
00983    @routine    SDSgetFileInfo
00984    @date       Wed Feb 28 15:37:43 1996
00985    @desc
00986           Gets information relevant to the entire file.
00987           Namely the number datasets contained in the file as
00988           well as the number of attributes associated with the file.
00989    @enddesc
00990    @calls      getFileID
00991 
00992    @par     filename
00993    @pdesc   Name of the HDF file
00994    @ptype   char*
00995    @endpar 
00996 
00997    @par     nsds
00998    @pdesc   Number of datasets (sds's) in the hdf file
00999    @ptype   int32*
01000    @endpar 
01001 
01002    @par     nattrib
01003    @pdesc   Number of netcdf attributes for the file
01004    @ptype   int32*
01005    @endpar 
01006 
01007    @history
01008    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01009    @hdesc Initial Version
01010    @endhistory
01011  @@*/
01012 void SDSgetFileInfo (char *filename,int32 *nsds,int32 *nattrib)
01013 {
01014   fileID *id=getFileID(filename);
01015   if(nsds)
01016     *nsds=id->nsds;
01017   if(nattrib)
01018     *nattrib=id->nattrib;
01019 }
01020 
01021 /*@@
01022    @routine    SDSgetDataName
01023    @date       Wed Feb 28 15:37:43 1996
01024    @desc
01025           Gets the name of the current dataset
01026    @enddesc
01027    @calls      getFileID
01028 
01029    @par     filename
01030    @pdesc   Name of the HDF file
01031    @ptype   char*
01032    @endpar 
01033 
01034    @par     dataname
01035    @pdesc   Name of the current dataset
01036    @ptype   char*
01037    @endpar 
01038 
01039    @history
01040    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01041    @hdesc Initial Version
01042    @endhistory
01043  @@*/
01044 int32 SDSgetDataName (char *filename,char *name)
01045 {
01046   int32 status;
01047   int32 rank,dims[MAX_NC_DIMS];
01048   fileID *id=getFileID(filename);
01049   if(id->sds_id<0)
01050     id->sds_id=SDselect(id->id,id->sdsnumber);
01051   if(id->sds_id<0)
01052     return -1;
01053   status=SDgetinfo(id->sds_id,name,&rank,dims,
01054                    &(id->numbertype),
01055                    &(id->nattrib));
01056   return status;
01057 }
01058 
01059 /*@@
01060    @routine    SDSgetIndex
01061    @date       Wed Feb 28 15:37:43 1996
01062    @desc
01063           Returns the index of the current dataset
01064    @enddesc
01065    @calls      getFileID
01066 
01067    @par     filename
01068    @pdesc   Name of the HDF file
01069    @ptype   char*
01070    @endpar 
01071 
01072    @history
01073    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01074    @hdesc Initial Version
01075    @endhistory
01076  @@*/
01077 int32  SDSgetIndex (char *filename)
01078 {
01079   fileID *id=getFileID(filename);
01080   return id->sdsnumber;
01081 }
01082 
01083 /*@@
01084    @routine    SDSgetDataStrs
01085    @date       Wed Feb 28 15:37:43 1996
01086    @desc
01087           Retrieves the data strings associated with the current dataset.
01088    @enddesc
01089    @calls      getFileID
01090 
01091    @par     filename
01092    @pdesc   Name of the HDF file
01093    @ptype   char*
01094    @endpar 
01095 
01096    @par     label
01097    @pdesc   Label of the current dataset
01098    @ptype   char*
01099    @endpar 
01100 
01101    @par     units
01102    @pdesc   Units of the current dataset (ie. meters, millibars, foot-pounds)
01103    @ptype   char*
01104    @endpar   
01105 
01106    @par     format
01107    @pdesc   Format of the current dataset
01108    @ptype   char*
01109    @endpar 
01110 
01111    @par     coordsys
01112    @pdesc   Coordinate system for the current dataset.
01113    @ptype   char*
01114    @endpar 
01115 
01116    @par     maxlen
01117    @pdesc   Maximum length of a string the variables can receive.
01118    @ptype   int32
01119    @endpar
01120 
01121    @history
01122    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01123    @hdesc Initial Version
01124    @endhistory
01125  @@*/
01126 
01127 int32  SDSgetDataStrs (char *filename,char *label,char *units,
01128                        char *format,char *coordsys,int maxlen)
01129 {
01130   fileID *id=getFileID(filename);
01131   if(id->sds_id<0)
01132     id->sds_id=SDselect(id->id,id->sdsnumber);
01133   if(id->sds_id<0)
01134     return -1;
01135   return SDgetdatastrs(id->sds_id,label,units,format,coordsys,maxlen);
01136 }
01137 
01138 /*@@
01139    @routine    SDSgetNumDatasets
01140    @date       Wed Feb 28 15:37:43 1996
01141    @desc
01142           Returns the number of SDS's in the current dataset
01143    @enddesc
01144    @calls      getFileID
01145 
01146    @par     filename
01147    @pdesc   Name of the HDF file
01148    @ptype   char*
01149    @endpar 
01150 
01151    @history
01152    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01153    @hdesc Initial Version
01154    @endhistory
01155  @@*/
01156 int32  SDSgetNumDatasets (char *filename)
01157 {
01158   fileID *id=getFileID(filename);
01159   return id->nsds;
01160 }
01161 
01162 /*@@
01163    @routine    SDSallocateDataset
01164    @date       Wed Feb 28 15:37:43 1996
01165    @desc
01166             Creates and reserves a dataset to receive data in chunks.
01167             Use in conjunction with SDSwriteChunk.
01168    @enddesc
01169    @seeroutine SDSwriteChunk
01170    @calls      getFileID
01171 
01172    @par     filename
01173    @pdesc   Name of the HDF file
01174    @ptype   char*
01175    @endpar 
01176 
01177    @par     dataname
01178    @pdesc   Name of the SDS
01179    @ptype   char*
01180    @endpar 
01181 
01182    @par     rank
01183    @pdesc   Number of dimensions for the dataset
01184    @ptype   char*
01185    @endpar 
01186 
01187    @par     dims
01188    @pdesc   The maximum dimension sizes for the dataset 
01189             (can be SD_UNLIMITED in any dimension to allow the
01190              space availible to automatically grow as you write chunks)
01191    @ptype   char*
01192    @endpar 
01193 
01194    @history
01195    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01196    @hdesc Initial Version
01197    @endhistory
01198  @@*/
01199 int32 SDSallocateDataset(char *filename,char *dataname,int32 rank,int32 *dims)
01200 {
01201   fileID *id=getFileID(filename);
01202   if(id->accessflags==DFACC_RDONLY)
01203     return -1; /* cant write to this file */
01204   if(id->sds_id>=0)
01205    SDendaccess(id->sds_id); /* may no longer be a valid operation */
01206 
01207   id->sds_id=SDcreate(id->id,dataname,id->numbertype,rank,dims);
01208   if(id->sds_id>=0)
01209     (id->nsds)++;
01210 
01211   return id->sdsnumber=SDreftoindex(id->id,SDidtoref(id->sds_id));
01212 }
01213 
01214 /*@@
01215    @routine    SDSwriteChunk
01216    @date       Wed Feb 28 15:37:43 1996
01217    @desc
01218             Writes a chunk of data to an sds with any
01219             stride, origin, and dimension so long as the
01220             chunk falls within the bounds of the dataset
01221             reserved with SDSallocateDataset().  If any
01222             of the dimensions were declared SD_UNLIMITED
01223             for size, then the size of the chunk is only
01224             constrained by system and file size limits.
01225    @enddesc
01226    @seeroutine SDSallocateDataset
01227    @calls      getFileID
01228 
01229    @par     filename
01230    @pdesc   Name of the HDF file
01231    @ptype   char*
01232    @endpar 
01233 
01234    @par     rank
01235    @pdesc   Number of dimensions for the dataset
01236    @ptype   char*
01237    @endpar 
01238 
01239    @par     dims
01240    @pdesc   The maximum dimension sizes for the dataset 
01241             (can be SD_UNLIMITED in any dimension to allow the
01242              space availible to automatically grow as you write chunks)
01243    @ptype   char*
01244    @endpar 
01245 
01246    @history
01247    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01248    @hdesc Initial Version
01249    @endhistory
01250  @@*/
01251 int SDSwriteChunk (char *filename,int32 rank,int32 *dims,
01252                         int32 *origin,int32 *stride,VOIDP data)
01253 {
01254   static int32 originS[5]={0,0,0,0,0};
01255   int status;
01256   fileID *id=getFileID(filename);
01257   if(id->accessflags==DFACC_RDONLY)
01258     return -1; /* cant write to this file */
01259   
01260   if(!origin){
01261     if(rank > 5) {
01262       origin=(int32 *)calloc(sizeof(int32),rank); /* origin is zeroed */
01263     }
01264     else 
01265       origin=originS;
01266   }
01267   if(id->sds_id<0)
01268         return -1; /* have to reserve the chunk first!! */
01269 /*
01270   if(id->sds_id<0)  only create if it doesn't already exist 
01271     id->sds_id=SDcreate(id->id,id->dataname,id->numbertype,rank,dims);
01272 */
01273   if(id->sds_id>=0)
01274     (id->nsds)++;
01275   id->sdsnumber=SDreftoindex(id->id,SDidtoref(id->sds_id));
01276   status=SDwritedata(id->sds_id,origin,stride,dims,data);
01277   /* SDendaccess(id->sds_id); (might append annotation) */
01278   if(origin!=originS) 
01279     free(origin);
01280   return status;
01281 }
01282 
01283 /*@@
01284    @routine    SDSwriteData
01285    @date       Wed Feb 28 15:37:43 1996
01286    @desc
01287             Writes a chunk of data to an sds with any
01288             stride, origin, and dimension so long as the
01289             chunk falls within the bounds of the dataset
01290             reserved with SDSallocateDataset().  If any
01291             of the dimensions were declared SD_UNLIMITED
01292             for size, then the size of the chunk is only
01293             constrained by system and file size limits.
01294    @enddesc
01295    @seeroutine SDSreadData SDSsetNT()
01296    @calls      getFileID
01297 
01298    @par     filename
01299    @pdesc   Name of the HDF file
01300    @ptype   char*
01301    @endpar 
01302 
01303    @par     dataname
01304    @pdesc   Name for the dataset
01305    @ptype   char*
01306    @endpar 
01307 
01308    @par     rank
01309    @pdesc   Number of dimensions for the dataset
01310    @ptype   char*
01311    @endpar 
01312 
01313    @par     dims
01314    @pdesc   The maximum dimension sizes for the dataset 
01315    @ptype   char*
01316    @endpar 
01317 
01318    @par     data
01319    @pdesc   Pointer to the dataset to write.  
01320              Default type is DFNT_FLOAT32 (32-bit float).
01321              This default can be changed using SDSsetNT().
01322    @ptype   VOIDP
01323    @endpar 
01324 
01325    @history
01326    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01327    @hdesc Initial Version
01328    @endhistory
01329  @@*/
01330 int SDSwriteData (char *filename,char *dataname,int32 rank,
01331                   int32 *dims,VOIDP data)
01332 {
01333   static int32 originS[5]={0,0,0,0,0},*origin;
01334   int status;
01335   fileID *id=getFileID(filename);
01336   if(id->accessflags==DFACC_RDONLY)
01337     return -1; /* cant write to this file */
01338   if(id->sds_id>=0)
01339    SDendaccess(id->sds_id);
01340     
01341   if(rank > 5) {
01342     origin=(int32 *)calloc(sizeof(int32),rank); /* origin is zeroed */
01343   }
01344   else 
01345     origin=originS;
01346 
01347   id->sds_id=SDcreate(id->id,dataname,id->numbertype,rank,dims);
01348   if(id->sds_id>=0)
01349     (id->nsds)++;
01350   id->sdsnumber=SDreftoindex(id->id,SDidtoref(id->sds_id));
01351   status=SDwritedata(id->sds_id,origin,NULL,dims,data);
01352   /* SDendaccess(id->sds_id); (might append annotation) */
01353   if(origin!=originS) 
01354     free(origin);
01355   return status;
01356 }
01357 
01358 /*@@
01359    @routine    SDSgetAnnotationSize
01360    @date       Wed Feb 28 15:37:43 1996
01361    @desc
01362           Returns the size of the current annotation attached to
01363           the current dataset
01364    @enddesc
01365    @seeroutine SDSgetAnnotation
01366    @calls      getFileID
01367 
01368    @par     filename
01369    @pdesc   Name of the HDF file
01370    @ptype   char*
01371    @endpar 
01372 
01373    @history
01374    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01375    @hdesc Initial Version
01376    @endhistory
01377  @@*/
01378 int32 SDSgetAnnotationSize(char *filename)
01379 {
01380   int32 ref;
01381   fileID *id=getFileID(filename);
01382   if(id->accessflags==DFACC_RDONLY)
01383     return -1; /* cant write to this file */
01384   if(id->sds_id<0)
01385    id->sds_id=SDselect(id->id,id->sdsnumber);
01386   ref=SDidtoref(id->sds_id);
01387   return DFANgetlablen(id->filename,DFTAG_NDG,ref);
01388 }
01389 
01390 /*@@
01391    @routine    SDSgetAnnotation
01392    @date       Wed Feb 28 15:37:43 1996
01393    @desc
01394           Returns the size of the current annotation attached to
01395           the current dataset.
01396    @enddesc
01397    @seeroutine SDSgetAnnotationSize SDSaddAnnotation
01398    @calls      getFileID
01399 
01400    @par     filename
01401    @pdesc   Name of the HDF file
01402    @ptype   char*
01403    @endpar 
01404 
01405    @par     annotation
01406    @pdesc   buffer to store the annotation in
01407    @ptype   char*
01408    @endpar 
01409 
01410    @par     maxlen
01411    @pdesc   Maximum length of the annotation (ie. the buffer size)
01412    @ptype   char*
01413    @endpar 
01414 
01415    @history
01416    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01417    @hdesc Initial Version
01418    @endhistory
01419  @@*/
01420 int32 SDSgetAnnotation(char *filename,char *annotation,int32 maxlen)
01421 {
01422   int32 ref;
01423   fileID *id=getFileID(filename);
01424   if(id->accessflags==DFACC_RDONLY)
01425     return -1; /* cant write to this file */
01426   if(id->sds_id<0)
01427    id->sds_id=SDselect(id->id,id->sdsnumber);
01428   ref=SDidtoref(id->sds_id);
01429   return DFANgetlabel(id->filename,DFTAG_NDG,ref,annotation,maxlen);
01430 }
01431 
01432 /*@@
01433    @routine    SDSaddAnnotation
01434    @date       Wed Feb 28 15:37:43 1996
01435    @desc
01436          Adds a text string annotation to the currently selected SDS
01437    @enddesc
01438    @seeroutine SDSgetAnnotation SDSgetAnnotationSize
01439    @calls      getFileID
01440 
01441    @par     filename
01442    @pdesc   Name of the HDF file
01443    @ptype   char*
01444    @endpar 
01445 
01446    @par     annotation
01447    @pdesc   buffer to store the annotation in
01448    @ptype   char*
01449    @endpar 
01450 
01451    @history
01452    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01453    @hdesc Initial Version
01454    @endhistory
01455  @@*/
01456 int32 SDSaddAnnotation(char *filename,char *annotation)
01457 {
01458   int32 ref;
01459   fileID *id=getFileID(filename);
01460   if(id->accessflags==DFACC_RDONLY)
01461     return -1; /* cant write to this file */
01462   if(id->sds_id<0)
01463    id->sds_id=SDselect(id->id,id->sdsnumber);
01464   ref=SDidtoref(id->sds_id);
01465   return DFANputlabel(id->filename,DFTAG_NDG,ref,annotation);
01466 }
01467 
01468 /*@@
01469    @routine    SDSgetNumAttribs
01470    @date       Wed Feb 28 15:37:43 1996
01471    @desc
01472           Returns the number of attributes associated with the
01473           current dataset.  The attributes can be retreived by
01474           name (if you already know which attributes you are
01475           looking for) or by index (if you want to step through them
01476           in order).  Returns an error if no SDS is currently selected.
01477    @enddesc
01478    @seeroutine SDSreadAttrib SDSfindAttribInfo SDSgetAttribInfo
01479    @calls      getFileID
01480 
01481    @par     filename
01482    @pdesc   Name of the HDF file
01483    @ptype   char*
01484    @endpar 
01485 
01486    @history
01487    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01488    @hdesc Initial Version
01489    @endhistory
01490  @@*/
01491 int32 SDSgetNumAttribs(char *filename)
01492 {
01493   fileID *id=getFileID(filename);
01494   if(id->sds_id>=0)
01495     return id->nattrib;
01496   else
01497     return -1; /* or should it return 0???? */
01498 }
01499 
01500 /*@@
01501    @routine    SDSwriteAttrib
01502    @date       Wed Feb 28 15:37:43 1996
01503    @desc
01504           Writes an attribute associated with the current SDS
01505           to the HDF file.  The attribute can be referred to
01506           by its name or by its index when read back in.
01507    @enddesc
01508    @seeroutine SDSreadAttrib SDSfindAttribInfo SDSgetAttribInfo SDSgetNumAttribs
01509    @calls      getFileID
01510 
01511    @par     filename
01512    @pdesc   Name of the HDF file
01513    @ptype   char*
01514    @endpar 
01515 
01516    @par     attribname
01517    @pdesc   Name of the attribute.
01518    @ptype   char*
01519    @endpar 
01520 
01521    @par     numbertype
01522    @pdesc   Numbertype of the attribute
01523    @pvalues DFNT_FLOAT32 (32-bit float), DFNT_FLOAT64 (64-bit float/double), 
01524             DFNT_INT8 (char), DFNT_INT16 (short int), DFNT_INT32,(int),
01525             DFNT_UINT8 (unsigned char), DFNT_UNINT16 (unsigned short), 
01526             DFNT_UINT32 (unsigned int),
01527             DFNT_NATIVE (if bit-OR'ed with the above, uses machine native format)
01528    @ptype   int32
01529    @endpar 
01530 
01531    @par     nelements
01532    @pdesc   Number of elements (of the type specified by the numbertype param)
01533             to store in the attribute.
01534    @ptype   int32
01535    @endpar 
01536 
01537    @par     buffer
01538    @pdesc   Pointer to the attribute data.
01539    @ptype   VOIDP
01540    @endpar 
01541 
01542    @history
01543    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01544    @hdesc Initial Version
01545    @endhistory
01546  @@*/
01547 int32 SDSwriteAttrib(char *filename,char *attribname,
01548                      int32 numbertype,int32 nelements,VOIDP buffer)
01549 {
01550   fileID *id=getFileID(filename);
01551   if(id->accessflags==DFACC_RDONLY)
01552     return -1; /* cant write to this file */
01553   if(id->sds_id<0)
01554     return -1; /* needs to be existing writeable SDS ? */
01555   /*
01556    id->sds_id=SDselect(id->id,id->sdsnumber);
01557   if(id->sds_id<0)
01558     return -1;
01559   */
01560   return SDsetattr(id->sds_id,attribname,numbertype,nelements,buffer);
01561 }
01562 /*@@
01563    @routine    SDSreadAttrib
01564    @date       Wed Feb 28 15:37:43 1996
01565    @desc
01566           Reads the attribute with the specified "attribname" associated 
01567           with the current SDS to the HDF file.  If there is no attribute
01568           by that name, it returns 0.  If an attribute is found by that
01569           name, it returns the number of elements read.
01570           The attribute can be referred to by its name or by its 
01571           index when read back in.<p>
01572 
01573           If you want to pre-allocate the buffer to match the size of
01574           the attribute being read in, then you should use 
01575           SDSfindAttribInfo() or SDSgetAttribInfo() to get the 
01576           exact size of the data contained in the attribute before
01577           reading.  If the size of the buffer is smaller than the
01578           amount of data that needs to be read, the read will be
01579           truncated to fit into the buffer.<p>
01580           
01581           If the stored data is a character string and the returned
01582           size==the size of your buffer, you will need to null
01583           terminate the buffer yourself after it is returned.
01584    @enddesc
01585    @seeroutine SDSwriteAttrib SDSfindAttribInfo SDSgetAttribInfo SDSgetNumAttribs
01586    @calls      getFileID
01587 
01588    @par     filename
01589    @pdesc   Name of the HDF file
01590    @ptype   char*
01591    @endpar 
01592 
01593    @par     attribname
01594    @pdesc   Name of the attribute.
01595    @ptype   char*
01596    @endpar 
01597 
01598    @par     nelements
01599    @pdesc   The maximimum number of elements that can be read by the
01600             from the attribute (ie. the size of the buffer).
01601    @ptype   int32
01602    @endpar 
01603 
01604    @par     buffer
01605    @pdesc   Pointer to the attribute data.
01606    @ptype   VOIDP
01607    @endpar 
01608 
01609    @history
01610    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01611    @hdesc Initial Version
01612    @endhistory
01613  @@*/
01614 int32 SDSreadAttrib(char *filename,char *attribname2,int32 nelements,VOIDP buffer)
01615 {
01616   int status;
01617   int index;
01618   int32 nt,count,rtval;
01619   fileID *id=getFileID(filename);
01620   char *attribname;
01621   if(id->sds_id<0)
01622    id->sds_id=SDselect(id->id,id->sdsnumber);
01623   if(id->sds_id<0)
01624     return -1;
01625   /* Copied to temporary string, SDattrinfo changes data! --- RD */
01626   attribname=(char *)malloc(HDstrlen(attribname2));
01627   HDmemcpy(attribname, attribname2, HDstrlen(attribname2));
01628   attribname[HDstrlen(attribname2)] = '\0';  
01629   index=SDfindattr(id->sds_id,attribname);
01630   /* Check to make sure the number of elements in the attribute
01631      is less than the number of elements in the buffer */     
01632   status=SDattrinfo(id->sds_id,index,attribname,&nt,&count);
01633   free(attribname);
01634   if(status<0)
01635     return status;
01636   if(count>nelements){
01637     char *tmpdata=(char *)malloc(count*DFKNTsize(nt));
01638     rtval=SDreadattr(id->sds_id,index,tmpdata);
01639     bcopy(tmpdata,buffer,DFKNTsize(nt)*nelements);
01640     free(tmpdata);
01641     /* if(nt==DFNT_INT8){
01642        might be a string, so null terminate 
01643        buffer[nelements-1]='\0';
01644        }*/
01645   }  
01646   else
01647     rtval=SDreadattr(id->sds_id,index,buffer);
01648   return (rtval>=0)?count:rtval;
01649 }
01650 
01651 /*@@
01652    @routine    SDSfindAttribInfo
01653    @date       Wed Feb 28 15:37:43 1996
01654    @desc
01655           Finds the named attribute associated with the current dataset
01656           by name and retrieves information about it.  It will return
01657           -1 if no attribute with that name is found.
01658    @enddesc
01659    @seeroutine SDSreadAttrib SDSgetAttribInfo SDSgetAttribInfo SDSgetNumAttribs
01660    @calls      getFileID
01661 
01662    @par     filename
01663    @pdesc   Name of the HDF file
01664    @ptype   char*
01665    @endpar 
01666 
01667    @par     attribname
01668    @pdesc   Name of the attribute.
01669    @ptype   char*
01670    @endpar 
01671 
01672    @par     numbertype
01673    @pdesc   Storage in which to return the numbertype of the attribute
01674    @pvalues DFNT_FLOAT32 (32-bit float), DFNT_FLOAT64 (64-bit float/double), 
01675             DFNT_INT8 (char), DFNT_INT16 (short int), DFNT_INT32,(int),
01676             DFNT_UINT8 (unsigned char), DFNT_UNINT16 (unsigned short), 
01677             DFNT_UINT32 (unsigned int),
01678             DFNT_NATIVE (if bit-OR'ed with the above, uses machine native format)
01679    @ptype   int32*
01680    @endpar 
01681 
01682    @par     nelements
01683    @pdesc   Storage in which to return the number of elements in the attribute
01684    of the type defined by the numbertype param.
01685             
01686    @ptype   int32*
01687    @endpar 
01688 
01689    @history
01690    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01691    @hdesc Initial Version
01692    @endhistory
01693  @@*/
01694 int32 SDSfindAttribInfo(char *filename,char *attribname,
01695                         int32 *numbertype,int32 *nelements)
01696 {
01697   int index;
01698   fileID *id=getFileID(filename);
01699   if(id->sds_id<0)
01700    id->sds_id=SDselect(id->id,id->sdsnumber);
01701   if(id->sds_id<0)
01702     return -1;
01703   index=SDfindattr(id->sds_id,attribname);
01704   return SDattrinfo(id->sds_id,index,attribname,numbertype,nelements);
01705 }
01706 /*@@
01707    @routine    SDSgetAttribInfo
01708    @date       Wed Feb 28 15:37:43 1996
01709    @desc
01710            Allows you to get the attribute information by index
01711            instead of by name.
01712    @enddesc
01713    @seeroutine SDSreadAttrib SDSwriteAttrib SDSfindAttribInfo SDSgetNumAttribs
01714    @calls      getFileID
01715 
01716    @par     filename
01717    @pdesc   Name of the HDF file
01718    @ptype   char*
01719    @endpar 
01720 
01721    @par     index
01722    @pdesc   Index of the attribute attached to the SDS
01723    @ptype   int32
01724    @endpar
01725 
01726    @par     attribname
01727    @pdesc   Storage area for name of the attribute (so that it can be
01728    returned to the user)
01729    @ptype   char*
01730    @endpar 
01731 
01732    @par     numbertype
01733    @pdesc   Storage in which to return the numbertype of the attribute
01734    @pvalues DFNT_FLOAT32 (32-bit float), DFNT_FLOAT64 (64-bit float/double), 
01735             DFNT_INT8 (char), DFNT_INT16 (short int), DFNT_INT32,(int),
01736             DFNT_UINT8 (unsigned char), DFNT_UNINT16 (unsigned short), 
01737             DFNT_UINT32 (unsigned int),
01738             DFNT_NATIVE (if bit-OR'ed with the above, uses machine native format)
01739    @ptype   int32*
01740    @endpar 
01741 
01742    @par     nelements
01743    @pdesc   Storage in which to return the number of elements in the attribute
01744    of the type defined by the numbertype param.
01745             
01746    @ptype   int32*
01747    @endpar 
01748 
01749    @history
01750    @hdate Wed Feb 28 20:38:57 1996 @hauthor John Shalf
01751    @hdesc Initial Version
01752    @endhistory
01753  @@*/
01754 int32 SDSgetAttribInfo(char *filename,int32 index,char *attribname,
01755                        int32 *numbertype,int32 *nelements)
01756 {
01757   fileID *id=getFileID(filename);
01758   if(id->sds_id<0)
01759    id->sds_id=SDselect(id->id,id->sdsnumber);
01760   if(id->sds_id<0)
01761     return -1;
01762   return SDattrinfo(id->sds_id,index,attribname,numbertype,nelements);
01763 }


Quickstart     Users Guide     Programmers Reference     Installation      Examples     Download



AMROC Main      Home      Contact
last update: 06/01/04