/* Hdf_file.cpp */ #undef DEBUG_HDF_FILE_CPP #ifdef DEBUG_HDF_FILE_CPP #define PDEBUG { std::fprintf(stderr, "call to %s (%s)\n", __PRETTY_FUNCTION__, __FILE__); } #else #define PDEBUG #endif #include #include #include #include #include // new(nothrow) #include "Hdf_common.hpp" #include "Hdf_file.hpp" void Hdf_file::Hdf_file_init(const char *filename, int32 access) { intn status; using namespace std; status = Hishdf(filename); if (status == FALSE) { bad_hdf_file e(filename); throw e; } // ***** init SD interface ***** // sd_id = SDstart(filename, access); if (sd_id == FAIL) { bad_hdf_file_opening_mode e(filename,Hdf_common::hdf_access_mode(access)); throw e; } status = SDfileinfo(sd_id, &n_sds, &n_file_attrs); if (status == FAIL) { bad_sd_file_info e(filename); throw e; } try { file_attrs = new Hdf_attr[n_file_attrs]; } catch (bad_alloc &e) { delete[] file_attrs; cout<<"Sorry, can't allocate the memory in "<<__FILE__<<" at "<<__LINE__< sds_infos, int32 fill_mode, int32 compression_type, int32 compression_level) : filename(filename) { intn status; using namespace std; PDEBUG; if (access == DFACC_CREATE) { sd_id = SDstart(filename, access); if (sd_id == FAIL) { bad_hdf_file_opening_mode e(filename,Hdf_common::hdf_access_mode(access)); throw e; } for (unsigned int isds = 0 ; isds < sds_infos.size() ; isds++) { char *sds_name = sds_infos[isds].sds_name; int32 sds_type = sds_infos[isds].sds_type; int32 sds_rank = sds_infos[isds].sds_rank; int32 *sds_dimensions = sds_infos[isds].sds_dimensions; float64 cal = sds_infos[isds].sds_cal; float64 cal_err = sds_infos[isds].sds_cal_err; float64 offset = sds_infos[isds].sds_offset; float64 offset_err = sds_infos[isds].sds_offset_err; HDF_CHUNK_DEF chunk_def; int32 sds_id = SDcreate(sd_id, sds_name, sds_type, sds_rank, sds_dimensions); if (sds_id == FAIL) { bad_sd_create e(filename); throw e; } if (compression_type == COMP_CODE_DEFLATE) { for (int32 idim = 0 ; idim < sds_rank ; idim++) { chunk_def.chunk_lengths[idim] = chunk_def.comp.chunk_lengths[idim] = sds_dimensions[idim]; } chunk_def.comp.comp_type = COMP_CODE_DEFLATE; chunk_def.comp.cinfo.deflate.level = compression_level; if (SDsetchunk(sds_id, chunk_def, HDF_CHUNK | HDF_COMP) == FAIL) { bad_chunk_creation e(filename,sds_name); throw e; } } else if (compression_type == COMP_CODE_SKPHUFF) { for (int32 idim = 0 ; idim < sds_rank ; idim++) { chunk_def.chunk_lengths[idim] = chunk_def.comp.chunk_lengths[idim] = sds_dimensions[idim]; } chunk_def.comp.comp_type = COMP_CODE_SKPHUFF; chunk_def.comp.cinfo.skphuff.skp_size = Hdf_common::hdf_sizeof(sds_type); if (SDsetchunk(sds_id, chunk_def, HDF_CHUNK | HDF_COMP) == FAIL) { bad_chunk_creation e(filename,sds_name); throw e;; } } else { if (compression_type != COMP_CODE_NONE) { fprintf(stderr, "%s: invalid or unknown compression type, compression ignored (only Adaptive Huffman and Lempel/Ziv-77 GZIP deflation are supported today)\n", filename); compression_type = COMP_CODE_NONE; } } /* if/else (compression_type) */ SDsetcal(sds_id, cal, cal_err, offset, offset_err, sds_type); SDsetfillmode(sds_id,fill_mode); status = SDendaccess(sds_id); if (status == FAIL) { bad_sd_end_access e; throw e; } } // for (isds) status = SDend(sd_id); if ( status == FAIL ) { bad_sd_end e; throw e; } access = DFACC_WRITE; } Hdf_file_init(filename, access); } Hdf_file::Hdf_file(const char *filename, int32 access, int32 n_sds_array, Hdf_sds *sds_array, int32 fill_mode, int32 compression_type, int32 compression_level) : filename(filename) { intn status; using namespace std; PDEBUG; if (access == DFACC_CREATE) { sd_id = SDstart(filename, access); if (sd_id == FAIL) { bad_hdf_file_opening_mode e(filename,Hdf_common::hdf_access_mode(access)); throw e; } for (int32 isds = 0 ; isds < n_sds_array ; isds++) { const char *sds_name = sds_array[isds].get_name().c_str(); int32 sds_type = sds_array[isds].get_data_type(); int32 sds_rank = sds_array[isds].get_rank(); int32 *sds_dimensions = new int32[sds_rank]; sds_array[isds].get_dimensions(sds_dimensions); int32 sds_id = SDcreate(sd_id, sds_name, sds_type, sds_rank, sds_dimensions); HDF_CHUNK_DEF chunk_def; delete[] sds_dimensions; if (sds_id == FAIL) { bad_sd_create e(filename); throw e; } if (compression_type == COMP_CODE_DEFLATE) { for (int32 idim = 0 ; idim < sds_rank ; idim++) { chunk_def.chunk_lengths[idim] = chunk_def.comp.chunk_lengths[idim] = sds_dimensions[idim]; } chunk_def.comp.comp_type = COMP_CODE_DEFLATE; chunk_def.comp.cinfo.deflate.level = compression_level; if (SDsetchunk(sds_id, chunk_def, HDF_CHUNK | HDF_COMP) == FAIL) { bad_chunk_creation e(filename,sds_name); throw e; } } else if (compression_type == COMP_CODE_SKPHUFF) { for (int32 idim = 0 ; idim < sds_rank ; idim++) { chunk_def.chunk_lengths[idim] = chunk_def.comp.chunk_lengths[idim] = sds_dimensions[idim]; } chunk_def.comp.comp_type = COMP_CODE_SKPHUFF; chunk_def.comp.cinfo.skphuff.skp_size = Hdf_common::hdf_sizeof(sds_type); if (SDsetchunk(sds_id, chunk_def, HDF_CHUNK | HDF_COMP) == FAIL) { bad_chunk_creation e(filename,sds_name); throw e;; } } else { if (compression_type != COMP_CODE_NONE) { fprintf(stderr, "%s: invalid or unknown compression type, compression ignored (only Adaptive Huffman and Lempel/Ziv-77 GZIP deflation are supported today)\n", filename); compression_type = COMP_CODE_NONE; } } /* if/else (compression_type) */ SDsetfillmode(sds_id,fill_mode); status = SDendaccess(sds_id); if (status == FAIL) { bad_sd_end_access e; throw e; } } // for (isds) status = SDend(sd_id); if ( status == FAIL ) { bad_sd_end e; throw e; } access = DFACC_WRITE; } Hdf_file_init(filename, access); } Hdf_file::Hdf_file(const Hdf_file &hdf_file) : filename(hdf_file.filename), n_sds(hdf_file.n_sds), n_file_attrs(hdf_file.n_file_attrs) { try { file_attrs = new Hdf_attr[n_file_attrs]; sds = new Hdf_sds[n_sds]; for (int32 iattr = 0 ; iattr < n_file_attrs ; iattr++) { file_attrs[iattr] = hdf_file.file_attrs[iattr]; } for (int32 isds = 0 ; isds < n_sds ; isds++) { sds[isds] = hdf_file.sds[isds]; } } catch (bad_alloc &e) { cout<<"Sorry, can't allocate the memory in "<<__FILE__<<" at "<<__LINE__<(HEvalue(0)); read_sds_error e(filename,sds_index,HEstring(errcode)); throw e; } status = SDendaccess(sds_id); if ( status == FAIL ) { bad_sd_end_access e; throw e; } } return sds[sds_index]; } /* stores 'sds_data' in the sds whose name is 'sds_name' * start, stride and edges must be given */ void Hdf_file::write_sds(const char *sds_name, const void *sds_data, int32 *start, int32 *stride, int32 *edges, float64 cal, float64 offset, float64 cal_err, float64 off_err) { int32 sds_index; assert(sds_name != NULL); sds_index = SDnametoindex(sd_id, sds_name); if (sds_index == FAIL) { bad_sds_name e(filename.c_str(),sds_name); throw e; } write_sds(sds_index, sds_data, start, stride, edges, cal, offset, cal_err, off_err); } // same as above, where sds_name is replaced by sds_index void Hdf_file::write_sds(const int32 sds_index, const void *sds_data, int32 *start, int32 *stride, int32 *edges, float64 cal, float64 offset, float64 cal_err, float64 off_err) { int32 sds_id; intn status; if (sds_data != NULL) { sds_id = SDselect(sd_id, sds_index); assert(sds_id != FAIL); status = SDwritedata(sds_id, start, stride, edges, (VOIDP) sds_data); if (status == FAIL) { hdf_err_code_t errcode = static_cast(HEvalue(status)); sd_write_data_error e(filename,get_sds_name(sds_index),HEstring(errcode)); throw e; } if (cal != 0) { int32 data_type; status = SDgetinfo(sds_id, NULL, NULL, NULL, &data_type, NULL); assert(status != FAIL); status = SDsetcal(sds_id, cal, cal_err, offset, off_err, data_type); assert(status != FAIL); } status = SDendaccess(sds_id); if ( status == FAIL ) { bad_sd_end_access e; throw e; } } } Hdf_sds Hdf_file::get_sds(const int32 &sds_index) const { assert(sds_index < n_sds); return sds[sds_index]; } Hdf_sds Hdf_file::get_sds(const char *sds_name) const { int32 sds_index; assert(sds_name != NULL); sds_index = ((Hdf_file*)this)->get_sds_index(sds_name); if (sds_index == FAIL) { bad_sds_name e(filename.c_str(),sds_name); throw e; } return get_sds(sds_index); } Hdf_attr Hdf_file::get_attr(const char *file_attr) const { int32 attr_index; assert(file_attr != NULL); attr_index = SDfindattr(sd_id, file_attr); if (attr_index == FAIL) { bad_attribute_name e(filename,file_attr,HDF_FILE); throw e; } assert(attr_index < n_file_attrs); return file_attrs[attr_index]; } bool Hdf_file::has_attr( const char * file_attr ) const { int32 attr_index; assert(file_attr != NULL); attr_index = SDfindattr(sd_id, file_attr); return (attr_index != FAIL); } void Hdf_file::get_sds_array(Hdf_sds *sds_array) { assert(sds_array); for (int32 isds = 0 ; isds < n_sds ; isds++) { sds_array[isds] = sds[isds]; } } void Hdf_file::set_sds(int32 sds_index, Hdf_sds sds) { assert(sds_index > 0); assert(sds_index < n_sds); this->sds[sds_index] = sds; } /* returns a string representation of the file attributes list */ std::string Hdf_file::list_of_attributes(const int32 chars_to_display, const int32 numbers_to_display) const { std::string s; Hdf_attr::chars_to_display = chars_to_display; Hdf_attr::numbers_to_display = numbers_to_display; s = ""; for (int32 iattr = 0 ; iattr < n_file_attrs ; iattr++) { s += file_attrs[iattr].to_string(); s += '\n'; } return s; } /* returns a string representation of the list of sds in the file */ std::string Hdf_file::list_of_sds() const { std::string s; s = ""; for (int32 isds = 0 ; isds < n_sds ; isds++) { s += sds[isds].to_string(); s += '\n'; } return s; } /* returns a string representation of the list of vdata in the file */ std::string Hdf_file::list_of_vdata() const { std::string s; s = ""; int32 n_vdata = vd.size(); for (int32 ivdata = 0 ; ivdata < n_vdata ; ivdata++) { s += vd[ivdata].to_string(); s += '\n'; } return s; } Hdf_file & Hdf_file::operator= (const Hdf_file &hdf_file) { if (&hdf_file == this) return *this; // protect against self assignation this->filename = hdf_file.filename; this->n_sds = hdf_file.n_sds; this->n_file_attrs = hdf_file.n_file_attrs; if (n_file_attrs) delete[] file_attrs; if (n_sds) delete[] sds; file_attrs = new(std::nothrow) Hdf_attr[n_file_attrs]; assert(file_attrs != NULL); /* FIXME: nothrow to be replaced by try ... catch */ sds = new(std::nothrow) Hdf_sds[n_sds]; assert(sds != NULL); /* FIXME: nothrow to be replaced by try ... catch */ for (int32 iattr = 0 ; iattr < n_file_attrs ; iattr++) { file_attrs[iattr] = hdf_file.file_attrs[iattr]; } for (int32 isds = 0 ; isds < n_sds ; isds++) { sds[isds] = hdf_file.sds[isds]; } return *this; } void Hdf_file::set_file_attr( const char * attr_name, const int val_type, const int32 val_length, VOIDP attr_val ) { intn status; //Hdf_attr attr = Hdf_attr(sd_id, get_n_file_attrs(), attr_name, val_type, val_length); // FIXME adding manually an attribute using this method doesn't update the list of Hdf_attr. So, after that, get_n_file_attrs and all this kind of methods have wrong values. status= SDsetattr (sd_id, attr_name, val_type, val_length, attr_val); if (status == FAIL) { bad_set_file_attribute e(filename.c_str(),attr_name); throw e; } } void Hdf_file::set_sds_attr( const int32 sds_index, const char * attr_name, const int val_type, const int32 val_length, VOIDP attr_val ) { intn status; int32 sds_id = SDselect(sd_id, sds_index); if (sds_id == FAIL){ bad_sd_select e(sds_index); throw e; } status=SDsetattr(sds_id, attr_name, val_type, val_length, attr_val); if (status == FAIL) { std::string s=get_sds_name(sds_index); bad_set_sds_attribute e(filename.c_str(),s.c_str(),attr_name); throw e; } status = SDendaccess(sds_id); if ( status == FAIL ) { bad_sd_end_access e; throw e; } } void Hdf_file::set_sds_attr( const char * sds_name, const char * attr_name, const int val_type, const int32 val_length, VOIDP attr_val ) { int32 sds_index = get_sds_index(sds_name); set_sds_attr(sds_index,attr_name,val_type,val_length,attr_val); } const int32 Hdf_file::get_sds_index( const char * sds_name ) { assert(sds_name != NULL); int32 sds_index = SDnametoindex(sd_id, sds_name); if (sds_index == FAIL) { bad_sds_name e(filename.c_str(),sds_name); throw e; } return sds_index; } const int32 Hdf_file::get_sds_id( const char * sds_name ) { int32 sds_index = get_sds_index(sds_name); return sds[sds_index].get_id(); } std::string Hdf_file::get_sds_name( const int32 & sds_index ) { Hdf_sds sds = get_sds(sds_index); return sds.get_name(); } void Hdf_file::get_fill_value( const char * sds_name, void* fill_value ) { Hdf_sds sds = get_sds(sds_name); sds.get_fill_value(fill_value); } void Hdf_file::set_fill_value( const char * sds_name, void * fill_value ) { Hdf_sds sds = get_sds(sds_name); sds.set_fill_value(fill_value); } void Hdf_file::get_calibration( const char * sds_name, float64 & cal, float64 & cal_error, float64 & offset, float64 & offset_err, int32 & data_type ) { Hdf_sds sds = get_sds(sds_name); sds.get_calibration(cal, cal_error, offset, offset_err, data_type); } void Hdf_file::get_sds_attr( const char * sds_name, const char * attr_name, void * value, const int32 ival ) const { try { Hdf_sds sds = get_sds(sds_name); sds.get_attr_value(attr_name,value,ival); } catch (bad_sds_attribute &e) { bad_get_sds_attribute super_e(filename.c_str(),sds_name,attr_name); throw super_e; } } const int32 Hdf_file::get_sds_data_type( const char * sds_name ) { Hdf_sds sds = get_sds(sds_name); return sds.get_data_type(); } const size_t Hdf_file::get_sds_sizeof( const char * sds_name ) { Hdf_sds sds = get_sds(sds_name); return Hdf_common::hdf_sizeof(sds.get_data_type()); } int32 Hdf_file::get_vd_idx( const char * vd_name ) const { int32 i=0; int32 end=vd.size(); while (i=static_cast(vd.size())) { bad_vd_index e(filename,vd_idx); throw e; } return vd[vd_idx]; } const bool Hdf_file::has_vd( const char * vd_name ) const { return ( get_vd_idx(vd_name)!=-1 ); } void Hdf_file::get_vd_attr(const char * vd_name, const char * attr_name, void * value, const int32 ival) const { Hdf_vd vd = get_vd(vd_name); vd.get_attr_value(attr_name,value,ival); } Hdf_vd_field Hdf_file::read_vdata_field( const char * vd_name, const char* vd_field_name, void* data, int32 start, int32 edges ) { assert(data!=NULL); assert(start>=0); bool already_opened_vs_interface = is_vs_interface_opened(); if (!already_opened_vs_interface) open_vs_interface(); // VData and VData field name to index conversion int32 vd_idx=get_vd_idx(vd_name); if (vd_idx==-1){ bad_vd_name e(filename,vd_name); throw e; } // read the datas Hdf_vd_field vd_field=read_vdata_field( vd_idx, vd_field_name, data, start, edges); close_vs_interface(); return vd_field; } const int32 Hdf_file::get_vd_field_data_type(const char * vd_name, const char * vd_field_name) { Hdf_vd_field vd_field = get_vd(vd_name).get_field(vd_field_name); return vd_field.get_type(); } Hdf_vd_field Hdf_file::read_vdata_field( const int32 & vd_idx, const char* vd_field_name, void* data, int32 start, int32 edges ) { // test the parameters validity if (vd_idx==-1 || vd_idx>=(int32)vd.size()) { bad_vd_index e(filename,vd_idx); throw e; } return get_vd(vd_idx).read_field_data( file_id, filename, vd_field_name, data, start, edges ); } std::string Hdf_file::to_string() const { std::string s="File "+get_filename()+"\n"+ "-> Attributes "+list_of_attributes()+"\n"+ "-> Sds "+list_of_sds()+"\n"+ "-> VData "+list_of_vdata()+"\n"; return s; }; std::ostream & operator <<( std::ostream & stream, const Hdf_file & hdf_file ) { stream << hdf_file.to_string(); return stream; } const intn Hdf_file::append_sds(const sds_infos_type & sds_infos, const void * sds_data) { intn status = FAIL; if ( sds_data == NULL ) { string msg ( "Can't write a NULL data buffer" ) ; hdfcpp_exception e( __FILE__ , __LINE__ , msg ); throw e; } int32 sds_id = SDcreate( sd_id, sds_infos.sds_name, sds_infos.sds_type, sds_infos.sds_rank, sds_infos.sds_dimensions); if (sds_id == FAIL) { hdf_err_code_t errcode = static_cast(HEvalue(status)); sd_create_error e(filename, sds_infos.sds_name, HEstring(errcode)); throw e; } // set start parametre to origin int32 * start = new int32 [ sds_infos.sds_rank ]; memset ( start, 0, sizeof (int32) * sds_infos.sds_rank ); status = SDwritedata(sds_id, start, NULL, sds_infos.sds_dimensions, (VOIDP) sds_data); if (status == FAIL) { hdf_err_code_t errcode = static_cast(HEvalue(status)); sd_write_data_error e(filename,sds_infos.sds_name,HEstring(errcode)); throw e; } if ( sds_infos.sds_cal != 0. ) { status = SDsetcal(sds_id, sds_infos.sds_cal, sds_infos.sds_cal_err, sds_infos.sds_offset, sds_infos.sds_offset_err, sds_infos.sds_type); assert(status != FAIL); } status = SDendaccess(sds_id); if ( status == FAIL ) { bad_sd_end_access e; throw e; } delete[] start; return status; }