diff options
Diffstat (limited to 'src/H5IO.cc')
-rw-r--r-- | src/H5IO.cc | 689 |
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)); +} |