#include #include #include //#include #include "H5IO.hh" #include 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; default: 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); //fprintf(stderr,"class=%d size=%d\n",typeclass,typesize); 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: return Char8; //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==(hsize_t) rank){ // lets compare dims int val=1; for(int i=0;i=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%09u",index); // was a KLUDGE! getdatasetname(index,dataname); //fprintf(stderr,"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; /* typedef struct H5G_stat_t { unsigned long fileno[2]; unsigned long objno[2]; unsigned nlink; int type; time_t mtime; size_t linklen; } H5G_stat_t */ H5G_stat_t objinfo; // request info about the type of objects in root group if(H5Gget_objinfo(group_id, member_name, 1 /* follow links */, &objinfo)<0) { //fprintf(stderr,"\tcounter: Bad Info [%s] count=%u\n",member_name,*count); return 0; // error (probably bad symlink) } // only count objects that are datasets (not subgroups) if(objinfo.type==H5G_DATASET){ // fprintf(stderr,"\tcounter: This is a dataset [%s] count=%u\n",member_name,*count); (*count)++; } //else // fprintf(stderr,"\tcounter: **reject dataset [%s] count=%u\n",member_name,*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; // check type first (only respond if it is a dataset) H5G_stat_t objinfo; // request info about the type of objects in root group if(H5Gget_objinfo(group_id, member_name, 1 /* follow links */, &objinfo)<0) return 0; // error (probably bad symlink) // only count objects that are datasets (not subgroups) if(objinfo.type!=H5G_DATASET) return 0; // do not increment count if it isn't a dataset. 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); //} //fprintf(stderr,"getndatasets:=%u\n",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;(hsize_t) i= 0) nitems = getndatasets(); break; case Write: file=H5Fcreate(fname, H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT); break; case Append: file=H5Fopen(fname, H5F_ACC_RDWR, H5P_DEFAULT); if (file >= 0) nitems = getndatasets(); break; default: file = -1; puts("H5IO: constructor... invalid accessmode"); break; } filevalid = file >= 0; } 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(file>=0) H5Fclose(file); filevalid=0; } int H5IO::isValid() { return filevalid; } int H5IO::write(IObase::DataType typeID,int rank,CONST int *dims,const 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%09u",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 return 1; } 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 // sprintf(annotation,"not-implemented"); length=0; return 0; } 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 if(maxlen>30) sprintf(annotation,"not-implemented"); else if(annotation) *annotation=0; 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 0; } int H5IO::writeAttribute(CONST char *name,IObase::DataType typeID,Long length,const void *data){ //printf("writeAttrib index=%u\n",index); selectdataset(index); // make sure it is selected //printf("\tindex=%u\n",index); // create a datashape hid_t datatype = DataType2H5(typeID); int is_string = datatype == H5T_NATIVE_CHAR; if (is_string) { datatype = H5Tcopy (H5T_C_S1); // we want the string length (without the trailing '\0') H5Tset_size (datatype, length - 1); length = 1; } hsize_t dimsa = length; hid_t shape = dimsa > 1 ? H5Screate_simple (1, &dimsa, NULL) : H5Screate (H5S_SCALAR); hid_t attrib = H5Acreate(dataset,name,datatype,shape,H5P_DEFAULT); H5Awrite(attrib, datatype, data); H5Aclose(attrib); H5Sclose(shape); if (is_string) { H5Tclose (datatype); } 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); // rank should always be 0 for scalars and 1 for arrays; hsize_t arank = H5Sget_simple_extent_ndims(ashape); hsize_t adims; if ((arank != 0 && arank != 1) || H5Sget_simple_extent_dims (ashape, &adims, NULL) < 0) { return (0); } typeID = H5DataType2DataType(atype); nelem = arank ? adims : 1; // single-dimensional array for attributes if (H5Tget_class (atype) == H5T_STRING) { nelem = H5Tget_size(atype); } 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); // rank should always be 0 for scalars and 1 for arrays; hsize_t arank = H5Sget_simple_extent_ndims(ashape); hsize_t adims; if ((arank != 0 && arank != 1) || H5Sget_simple_extent_dims (ashape, &adims, NULL) < 0) { return (0); } typeID = H5DataType2DataType(atype); nelem = arank ? adims : 1; // single-dimensional array for attributes if (H5Tget_class (atype) == H5T_STRING) { nelem = H5Tget_size(atype); } 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,atype /*DataType2H5(H5DataType2DataType(atype))*/ ,data); // need to explicitely set the terminating NUL character in string attributes if (H5Tget_class (atype) == H5T_STRING) { size_t len = H5Tget_size (atype); ((char *) data)[len] = 0; } H5Tclose(atype); H5Aclose(attrib); return 1; } int H5IO::nAttributes(){ selectdataset(index); unsigned idx=0; int count=0; 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;iisValid()) 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)); }