aboutsummaryrefslogtreecommitdiff
path: root/src/H5IO.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5IO.cc')
-rw-r--r--src/H5IO.cc689
1 files changed, 689 insertions, 0 deletions
diff --git a/src/H5IO.cc b/src/H5IO.cc
new file mode 100644
index 0000000..f41471b
--- /dev/null
+++ b/src/H5IO.cc
@@ -0,0 +1,689 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+//#include <hdf.h>
+#include "H5IO.hh"
+#include <hdf5.h>
+
+hid_t H5IO::DataType2H5(IObase::DataType nt){
+ switch(nt){
+ case Int8:
+ return H5T_NATIVE_CHAR; // means data
+ case Char8: // distinct from INT8..
+ return H5T_NATIVE_CHAR; // means string
+ case Float32:
+ return H5T_NATIVE_FLOAT;
+ case Float64:
+ return H5T_NATIVE_DOUBLE;
+ case Int32:
+ return H5T_NATIVE_INT;
+ case Int64:
+ return H5T_NATIVE_LLONG;
+ case Int16:
+ return H5T_NATIVE_SHORT;
+ case uInt8:
+ return H5T_NATIVE_UCHAR;
+ case uInt16:
+ return H5T_NATIVE_USHORT;
+ case uInt32:
+ return H5T_NATIVE_UINT;
+ case uInt64:
+ return H5T_NATIVE_ULLONG;
+ case Char16: // unicode character type
+ return H5T_NATIVE_USHORT;
+ }
+ printf("H5IO::H52DataType(): Don't recognize type %d\n",(int)nt);
+ return -1;
+}
+
+IObase::DataType H5IO::H5DataType2DataType(hid_t nt){
+ H5T_class_t typeclass;
+ size_t typesize;
+
+ typeclass = H5Tget_class(nt);
+ typesize = H5Tget_size(nt);
+
+ switch(typeclass){
+ case H5T_INTEGER:
+ printf("Int %d bytes\n",typesize);
+ switch(typesize){
+ case 1:
+ return Int8;
+ case 2:
+ return Int16;
+ case 4:
+ return Int32;
+ case 8:
+ return Int64;
+ default:
+ printf("Cannot convert type for integer with %d bytes\n",
+ typesize);
+ break;
+ }
+ break;
+ case H5T_FLOAT:
+ // printf("Float %d bytes\n",typesize);
+ switch(typesize){
+ case 4:
+ return Float32;
+ case 8:
+ return Float64;
+ default:
+ printf("Cannot convert type for floating point with %d bytes\n",
+ typesize);
+ }
+ break;
+ case H5T_TIME:
+ puts("Cannot convert type Time");
+ break;
+ case H5T_STRING:
+ //puts("String");
+ switch(typesize){
+ case 1:
+ return Char8;
+ case 2:
+ return Char16;
+ default:
+ printf("Cannot convert type for string element with %d bytes\n",
+ typesize);
+ break;
+ }
+ break;
+ case H5T_BITFIELD:
+ puts("Cannot convert type Bitfield");
+ break;
+ case H5T_OPAQUE:
+ puts("Cannot convert type Opaque");
+ break;
+ case H5T_COMPOUND:
+ default:
+ puts("Cannot convert type Unknown");
+ break;
+ }
+ puts("Type conversion failed");
+ return Error;
+}
+#if 0
+IObase::DataType H5IO::H52DataType(hid_t &nt){
+ switch(nt){
+ case H5T_NATIVE_CHAR:
+ return Int8;
+ case H5T_NATIVE_CHAR:
+ return Char8;
+ case H5T_NATIVE_FLOAT:
+ return Float32;
+ case H5T_NATIVE_DOUBLE:
+ return Float64;
+ case H5T_NATIVE_INT:
+ return Int32;
+ case H5T_NATIVE_LONGLONG:
+ return Int64;
+ case H5T_NATIVE_SHORT:
+ return Int16;
+ case H5T_NATIVE_UCHAR:
+ return uInt8;
+ case H5T_NATIVE_USHORT:
+ return uInt16;
+ case H5T_NATIVE_UINT:
+ return uInt32;
+ case H5T_NATIVE_ULONGLONG:
+ return uInt64;
+ // no translation to Char16 from HDF5 right now (unclear what to do)
+ }
+ fprintf(stderr,"H5IO::H52DataType(): Don't recognize type %d\n",(int)nt);
+ return Error;
+}
+#endif
+int H5IO::createdataspace(int rank,CONST int *dims){
+ if(dataspacevalid && rankf==rank){
+ // lets compare dims
+ int val=1;
+ for(int i=0;i<rank;i++) if(dims[i]!=dimsf[i]) val=0;
+ if(val){ // current dataspace is sufficient
+ nitems++;
+ index=nitems-1; // error in returnval here!
+ return 1; // success
+ }
+ // otherwise, must nuke current dataspace
+ enddataspace();
+ }
+ for(int i=0;i<rank;i++) dimsf[i]=dims[i];
+ rankf=rank;
+ dataspace = H5Screate_simple(rankf, dimsf, NULL);
+ dataspacevalid=1;
+ nitems++;
+ index=nitems-1;
+ return 1; // created new datapace
+}
+
+int H5IO::createdatatype(IObase::DataType dt){
+ if(currentdatatype==dt) return 0;
+ enddatatype();
+ datatype = H5Tcopy(DataType2H5(dt));
+ currentdatatype = dt;
+ datatypevalid = 1;
+ return 1;
+}
+
+int H5IO::selectdataset(int i){
+ // printf("datasetvalid=%u i=%d index=%d nitems=%d\n",datasetvalid,i,index,nitems);
+
+ if(index==i && datasetvalid)
+ return index;
+ index=i;
+ if(index>=nitems) index=nitems-1;
+ if(index<0) index=0;
+ // must iterate to select or for now just
+ char dataname[128];
+ //char dataname2[128];
+ sprintf(dataname,"H5IO-Dataset%u",index); // was a KLUDGE!
+ //getdatasetname(index,dataname2);
+ //printf("Datasetname for dataset[%u]=[%s] [%s]\n",index,dataname,dataname2);
+ enddataset(); // close current dataset
+ dataset = H5Dopen(file,dataname); // open a dataset
+ if(!dataset) puts("error no dataset");
+ datasetvalid=1; // we have a new dataset
+ // if(!datasetvalid) return -1;
+ enddataspace();
+ dataspace = H5Dget_space(dataset);
+ if(!dataspace) puts("error no dataspace");
+ enddatatype();
+ datatype = H5Dget_type(dataset);
+ enddataspace();
+ rankf = H5Sget_simple_extent_ndims(dataspace);
+ H5Sget_simple_extent_dims(dataspace,dimsf,NULL);
+ //printf("\tdimsf is now %lu:%lu:%lu\n",dimsf[0],dimsf[1],dimsf[2]);
+ datasetvalid=dataspacevalid=datatypevalid=1; // all valid now
+ return index;
+}
+
+herr_t H5IOcounter(hid_t group_id,
+ const char *member_name,
+ void *operator_data){
+ int *count = (int*)operator_data;
+ (*count)++;
+ return 0;
+}
+
+struct H5IO_getname_t {
+ int index,count;
+ char *name;
+};
+herr_t H5IOgetname(hid_t group_id,
+ const char *member_name,
+ void *operator_data){
+ H5IO_getname_t *getn = (H5IO_getname_t*)operator_data;
+ if(getn->index==getn->count){
+ strcpy(getn->name,member_name);
+ return 1; // success
+ }
+ getn->count++;
+ return 0;
+}
+
+int H5IO::getndatasets(){
+ int count=0;
+ int idx=0;
+ while(H5Giterate(file, /* hid_t loc_id, */
+ "/", /*const char *name, */
+ &idx, /* int *idx, */
+ H5IOcounter,
+ &count)<0){}
+ //if(nitems!=count){
+ //printf("getndatasets: nitems{%d}!=count{%d}\n",
+ // nitems,count);
+ //}
+ nitems = count; // just for internal bookkeeping
+ return count;
+}
+
+void H5IO::getdatasetname(int _index, // in
+ char *name){ // out
+ H5IO_getname_t getn;
+ int idx=_index;
+ getn.index=_index; getn.name=name; getn.count=_index;
+ while(H5Giterate(file, /* hid_t loc_id, */
+ "/", /*const char *name, */
+ &idx, /* int *idx, */
+ H5IOgetname,
+ &getn)<0){}
+}
+
+void H5IO::enddataspace(){
+ if(!dataspacevalid) return;
+ dataspacevalid=0;
+ for(int i=0;i<rankf;i++) dimsf[i]=0;
+ rankf=0;
+ H5Sclose(dataspace);
+}
+void H5IO::enddatatype(){
+ if(!datatypevalid) return;
+ datatypevalid=0;
+ currentdatatype = IObase::Error;
+ H5Tclose(datatype);
+}
+
+// This is broken: It must create a different name for each dataset
+// for the purpose of indexing. So the "name" as it is passed here
+// should actually be an attribute of the dataset which is tacked on
+// right here.
+int H5IO::createdataset(char *name,IObase::DataType nt,int rank,CONST int *dims){
+ //printf("++createdataset index=%u\n",index);
+ createdataspace(rank,dims);
+ createdatatype(nt);
+ //printf("+++createdataset index=%u\n",index);
+ // dump the old one and create a new one
+ dataset = H5Dcreate(file, name, datatype, dataspace,
+ H5P_DEFAULT);
+ datasetvalid=1;
+ return 1;
+}
+
+int H5IO::createdataset(IObase::DataType nt,int rank,CONST int *dims){
+ //printf("++createdataset index=%u\n",index);
+ createdataspace(rank,dims);
+ createdatatype(nt);
+ //printf("+++createdataset index=%u\n",index);
+ // dump the old one and create a new one
+ char buffer[32];
+ sprintf(buffer,"H5IO-Dataset%u",index); // current index in file
+ //printf("Creating dataset [%s]\n",buffer);
+ dataset = H5Dcreate(file,buffer, datatype, dataspace,
+ H5P_DEFAULT);
+ datasetvalid=1;
+ return 1;
+}
+
+int H5IO::getdatasetinfo(int &rank, int *dims, IObase::DataType &nt){
+ if(!datasetvalid) return 0;
+ rank = rankf;
+ //printf("getdatasetinfo: Rankf = %u dimsf= %u %u %u\n",
+ // (int)rankf,(int)dimsf[0],(int)dimsf[1],(int)dimsf[2]);
+ for(int i=0;i<rank;i++){
+ dims[i]=dimsf[i];
+ //printf("[%u] %u:%u ",i,dims[i],dimsf[i]);
+ }
+ //puts("<---were copied dims");
+ nt = H5DataType2DataType(datatype);
+ return 1;
+}
+
+void H5IO::enddataset(){
+ if(!datasetvalid) return;
+ H5Dclose(dataset);
+ datasetvalid=0;
+}
+
+H5IO::H5IO(CONST char *fname,AccessMode access):IObase(fname,access),filevalid(0),datasetvalid(0),dataspacevalid(0),datatypevalid(0),hasread(0){
+ filevalid=1;
+ switch(accessmode){
+ case Read:
+ file=H5Fopen(fname, H5F_ACC_RDONLY, H5P_DEFAULT);
+ nitems = getndatasets();
+ break;
+ case Write:
+ file=H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+ nitems = 0;
+ break;
+ case Append:
+ file=H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT);
+ nitems = getndatasets();
+ break;
+ default:
+ filevalid=0; // set filevalid flag to failure value
+ puts("H5IO: constructor... invalid accessmode");
+ break;
+ }
+}
+
+H5IO::~H5IO(){
+ // printf("Destroying H5 file fid=%u, sid=%u\n",fid,sid);
+ enddataset(); // close all dataset and datatype IDs which are open
+ enddatatype();
+ enddataspace();
+ if(filevalid>=0) H5Fclose(file);
+ filevalid=0;
+}
+
+int H5IO::isValid() { return filevalid; }
+
+int H5IO::write(IObase::DataType typeID,int rank,CONST int *dims,void *data){
+ hasread=0;
+ //printf("++Write index=%u\n",index);
+ createdataset(typeID,rank,dims);
+ status = H5Dwrite(dataset, DataType2H5(typeID), H5S_ALL, H5S_ALL,
+ H5P_DEFAULT, data);
+ enddataset(); // commit it now
+ return status;
+}
+
+//int H5IO::write(char *name, IObase::DataType typeID,int rank,CONST int *dims,void *data){
+// hasread=0;
+// createdataset(name,typeID,rank,dims);
+// return status = H5Dwrite(dataset, DataType2H5(typeID), H5S_ALL, H5S_ALL,
+// H5P_DEFAULT, data);
+//}
+
+int H5IO::readInfo(char *name,IObase::DataType &typeID,int &rank,int *dims,int maxdims){
+
+ // name shouls be attribute "long_name");
+ if(hasread){
+ //printf("hasread=1, so get next dataset index %u\n",index+1);
+ hasread=0;
+ selectdataset(index+1);
+ }
+ else {
+ //printf("hasread=0, so select current index for dataset %u\n",index);
+ selectdataset((int)index);
+ }
+ getdatasetinfo(rank,dims,typeID);
+ //sprintf(name,"H5IO-Dataset%u",index);
+ getdatasetname(index,name);
+ hasread=1;
+ return 1;
+}
+
+int H5IO::readInfo(IObase::DataType &typeID,int &rank,int *dims,int maxdims){
+ // name is an attribute "long_name");
+ if(hasread){
+ hasread=0;
+ selectdataset(index+1);
+ }
+ else {
+ selectdataset((int)index);
+ }
+ getdatasetinfo(rank,dims,typeID);
+ hasread=1;
+ return 1;
+}
+
+int H5IO::read(void *data){
+ selectdataset(index); // make certain its selected
+ // we will be getting all of the dataset
+ //SDgetinfo(sid,name,&rank,dims,&nt,&natt);
+ // set up memspace
+ hid_t memspace = H5Screate_simple(rankf,dimsf,NULL);
+ //printf("rankf=%u dimsf=%u:%u:%u\n",(int)rankf,
+ // (int)dimsf[0],(int)dimsf[1],(int)dimsf[2]);
+ // printf("Data = %u\n",data);
+ // if(!memspace) puts("no memspace");
+ //if(!dataset) puts("no dataset");
+ status = H5Dread(dataset,DataType2H5(H5DataType2DataType(datatype)),
+ memspace,dataspace,H5P_DEFAULT,data);
+ // printf("H5Dread status = %d\n",status);
+ hasread=1;
+ return status;
+}
+
+int H5IO::seek(int i) { selectdataset((int)i); hasread=0; return index; }
+
+int H5IO::nDatasets(){ // not completely correct due to coordvar's
+ // must scan for coordvar's and eliminate them from the count.
+ // int32 ndatasets,nattribs;
+ //SDfileinfo(fid,&ndatasets,&nattribs);
+ // return (int)ndatasets; //?
+ return getndatasets();
+}
+
+int H5IO::writeAnnotation(CONST char *annotation){
+#if 0
+ select((int)index); // select if not already selected
+ int32 ref=SDidtoref(sid);
+ return (int)DFANputlabel(filename,DFTAG_NDG,ref,(char*)annotation);
+#endif
+}
+
+int H5IO::readAnnotationInfo(int number,int &length){
+#if 0
+ select(index);
+ int32 ref=SDidtoref(sid);
+ length=(int)DFANgetlablen(filename,DFTAG_NDG,ref);
+ return length;
+#endif
+ return 1;
+}
+
+int H5IO::readAnnotation(int number,char *annotation,int maxlen){
+#if 0
+ // number=0; // How do I get the number of annotations availible?
+ // use get lablist to get list of tags
+ number=0; // number is ALWAYS 0 for hdf files
+ select(index);
+ int32 ref=SDidtoref(sid);
+ return (int)DFANgetlabel(filename,DFTAG_NDG,ref,annotation,maxlen);
+#endif
+ return 1;
+}
+
+
+int H5IO::nAnnotations(){
+#if 0
+ select(index);
+ int32 ref=SDidtoref(sid);
+ if(DFANgetlablen(filename,DFTAG_NDG,ref)<=0) return 0; // no labels found
+ return 1; // always 1 annotation per object limit for H5 is appears
+#endif
+ return 1;
+}
+
+int H5IO::writeAttribute(CONST char *name,IObase::DataType typeID,Long length,void *data){
+ //printf("writeAttrib index=%u\n",index);
+ selectdataset(index); // make sure it is selected
+ //printf("\tindex=%u\n",index);
+ // create a datashape
+ hsize_t dimsa[2]={0,0};
+ dimsa[0]=length;
+ hid_t shape = H5Screate_simple(1, dimsa, NULL);
+ hid_t attrib = H5Acreate(dataset,name,DataType2H5(typeID),shape,H5P_DEFAULT);
+ H5Awrite(attrib, DataType2H5(typeID), data);
+ H5Aclose(attrib);
+ H5Sclose(shape);
+ return 1;
+}
+
+int H5IO::readAttributeInfo(int number,char *name,IObase::DataType &typeID,Long &nelem,int maxnamelen){
+ selectdataset(index); // make sure current dataset is selected
+ hid_t attrib = H5Aopen_idx(dataset,number);
+ hid_t atype = H5Aget_type(attrib);
+ hid_t ashape = H5Aget_space(attrib);
+ H5Aget_name(attrib,maxnamelen,name);
+ hsize_t ranka = H5Sget_simple_extent_ndims(ashape);
+ // rank should always be 1;
+ hsize_t dimsa[5];
+ H5Sget_simple_extent_dims(ashape,dimsa,NULL);
+ typeID = H5DataType2DataType(atype);
+ nelem = dimsa[0]; // single-dimensional array for attributes
+
+ H5Tclose(atype);
+ H5Sclose(ashape);
+ H5Aclose(attrib);
+ return 1;
+}
+
+struct H5IOatt_name2index_t {
+ char *name;
+ int count;
+};
+herr_t H5IOattr_name2index(hid_t group_id,
+ const char *member_name,
+ void *operator_data){
+ H5IOatt_name2index_t *s=(H5IOatt_name2index_t*)operator_data;
+ s->count++;
+ if(!strcmp(member_name,s->name))
+ return s->count;
+ else{
+ return 0;
+ }
+}
+
+herr_t H5IOattr_count(hid_t group_id,
+ const char *member_name,
+ void *operator_data){
+ // cycle through all attribs as a dummy counter
+ int *count = (int *)operator_data;
+ (*count)++;
+ return 0;
+}
+
+int H5IO::readAttributeInfo(CONST char *name,IObase::DataType &typeID,Long &nelem){
+ selectdataset(index); // make sure current dataset is selected
+ H5IOatt_name2index_t stype;
+ stype.name=(char*)name;
+ stype.count=0;
+ unsigned idx=0;
+ int aindex = H5Aiterate(dataset,&idx,H5IOattr_name2index,&stype);
+ if(aindex<=0) return -1;
+ aindex--; // index is one more than the actual index of the item
+ hid_t attrib = H5Aopen_name(dataset,name);
+ hid_t atype = H5Aget_type(attrib);
+ hid_t ashape = H5Aget_space(attrib);
+ hsize_t ranka = H5Sget_simple_extent_ndims(ashape);
+ // rank should always be 1;
+ hsize_t dimsa[5];
+ H5Sget_simple_extent_dims(ashape,dimsa,NULL);
+ typeID = H5DataType2DataType(atype);
+ nelem = dimsa[0]; // single-dimensional array for attributes
+
+ H5Tclose(atype);
+ H5Sclose(ashape);
+ H5Aclose(attrib);
+ return aindex;
+}
+
+int H5IO::readAttribute(int number,void *data){
+ // now must openIDX again
+ selectdataset(index); // just to be sure we've got data
+ hid_t attrib = H5Aopen_idx(dataset,number);
+ hid_t atype = H5Aget_type(attrib);
+ H5Aread(attrib,DataType2H5(H5DataType2DataType(atype)),data);
+ H5Tclose(atype);
+ H5Aclose(attrib);
+ return 1;
+}
+
+int H5IO::nAttributes(){
+ selectdataset(index);
+ unsigned idx=0;
+ int count=0;
+ int aindex = H5Aiterate(dataset,&idx,H5IOattr_count,&count);
+ return count;
+}
+//================Chunking Interface-----------------------
+int H5IO::reserveChunk(IObase::DataType typeID,int rank,CONST int *dims){
+#if 0
+ hasread=0;
+ for(int i=0;i<rank;i++) chunkdims[i]=dims[i];
+ create(rank,dims,typeID);
+ current_rank=rank;
+ return 1;
+#endif
+ return 1;
+}
+
+int H5IO::writeChunk(CONST int *dims,CONST int *origin,void *data){
+#if 0
+ int32 horigin[5]={0,0,0,0,0};
+ int32 stride[5]={1,1,1,1,1}; // kludge... we'll fix later
+ int32 hdims[5]={0,0,0,0,0};
+ int32 rank = current_rank;
+ for(int i=0;i<rank;i++) { hdims[i]=dims[i]; horigin[i]=origin[i]; }
+ return (int)SDwritedata(sid,horigin,stride,hdims,data);
+#endif
+ return 1;
+}
+
+
+int H5IO::readChunk(CONST int *dims,CONST int *origin,void *data){
+#if 0
+ int32 horigin[5]={0,0,0,0,0};
+ int32 stride[5]={1,1,1,1,1}; // kludge... we'll fix later
+ int32 rank,nt,natt,hdims[5]={0,0,0,0,0};
+ char name[128];
+ select(index);
+ SDgetinfo(sid,name,&rank,hdims,&nt,&natt);
+ for(int i=0;i<rank;i++) {hdims[i]=dims[i]; horigin[i]=origin[i];}
+ return (int)SDreaddata(sid,horigin,stride,hdims,data);
+#endif
+return 1;
+}
+
+//===============F77 Interface
+Long8 f_h5_open (char *file,char *accessname,int flen,int alen){
+ // would have used tolower(), but it doesn't exist everywhere.... :(
+ IObase::AccessMode mode;
+ if(*accessname=='R' || *accessname=='r')
+ mode=IObase::Read;
+ else if(*accessname=='W' || *accessname=='w' ||
+ *accessname=='C' || *accessname=='c')
+ mode=IObase::Write;
+ else if(*accessname=='A' || *accessname=='a')
+ mode=IObase::Append;
+ else {
+ fprintf(stderr,"IEEEopen(): Error unknown option [%s] to open file %s\n",
+ accessname,file);
+ return 0;
+ }
+ IObase *fid=new H5IO(file,mode);
+ if(fid->isValid())
+ return (Long8)fid;
+ else
+ delete fid; // file open failed
+ return 0;
+}
+
+Long8 f_h5_openr (char *file,int flen){
+ file[flen]='\0'; // null terminate
+ return (Long8)(new H5IO(file,IObase::Read));
+}
+
+Long8 f_h5_openw (char *file,int flen){
+ file[flen]='\0'; // null terminate
+ return (Long8)(new H5IO(file,IObase::Create));
+}
+
+Long8 f_h5_opena (char *file,int flen){
+ file[flen]='\0'; // null terminate
+ return (Long8)(new H5IO(file,IObase::Append));
+}
+
+IOFile H5IOopen (char *file,char *accessname){
+ // Parse all of the ansi stdio access option strings
+ IObase::AccessMode mode;
+ if(!strcmp(accessname,"read") ||
+ !strcmp(accessname,"r") ||
+ !strcmp(accessname,"rb"))
+ mode=IObase::Read;
+ else if(*accessname=='a')
+ mode=IObase::Append;
+ else if(!strcmp(accessname,"write") ||
+ !strcmp(accessname,"create") ||
+ !strcmp(accessname,"wb"))
+ mode = IObase::Write;
+ else if(!strcmp(accessname,"w+") ||
+ !strcmp(accessname,"w+b") ||
+ !strcmp(accessname,"wb+"))
+ mode=IObase::Append;
+ else{
+ fprintf(stderr,"IEEEopen(): Error unknown option [%s] to open file %s\n",
+ accessname,file);
+ return 0;
+ }
+ IObase *fid=new H5IO(file,mode);
+ if(fid->isValid())
+ return (IOFile)fid;
+ else
+ delete fid; // file open failed
+ return 0; // unknown option
+}
+
+IOFile H5IOopenRead (char *file){
+ return (IOFile)(new H5IO(file,IObase::Read));
+}
+
+IOFile H5IOopenWrite (char *file){
+ return (IOFile)(new H5IO(file,IObase::Write));
+}
+
+IOFile H5IOopenAppend (char *file){
+ return (IOFile)(new H5IO(file,IObase::Append));
+}