From f323a72861467a6f503b06946194b3576aa0fc7b Mon Sep 17 00:00:00 2001 From: Binh-Minh Ribler Date: Thu, 18 May 2017 13:40:20 -0500 Subject: Purpose: Add new C++ wrappers (HDFFV-10156) Description: Added wrappers for H5Iis_valid, H5Ps/get_nlinks, H5Tget_create_plist, H5Oopen, and H5Oclose // Checks if the given ID is valid. static bool isValid(hid_t an_id); // Sets the number of soft or user-defined links that can be // traversed before a failure occurs. void setNumLinks(size_t nlinks) const; // Gets the number of soft or user-defined link traversals allowed size_t getNumLinks() const; // Returns a copy of the creation property list of a datatype. PropList getCreatePlist() const; // Opens an object within a group or a file, i.e., root group. hid_t openObjId(const char* name,...); hid_t openObjId(const H5std_string& name,...); // Closes an object opened by getObjId(). void closeObjId(hid_t obj_id) const; // Gets general information about this file. void getFileInfo(H5F_info2_t& file_info) const; Platforms tested: Linux/32 2.6 (jam) Linux/64 (platypus) Darwin (osx1010test) --- c++/src/H5DataType.cpp | 25 ++++++ c++/src/H5DataType.h | 3 + c++/src/H5Exception.cpp | 23 +++++ c++/src/H5Exception.h | 7 ++ c++/src/H5File.cpp | 19 +++++ c++/src/H5File.h | 3 + c++/src/H5Group.cpp | 7 +- c++/src/H5Group.h | 3 +- c++/src/H5IdComponent.cpp | 21 +++++ c++/src/H5IdComponent.h | 3 + c++/src/H5Library.cpp | 1 - c++/src/H5Location.cpp | 135 +++++++++++++++++++++++------ c++/src/H5Location.h | 10 +++ c++/test/tfile.cpp | 213 ++++++++++++++++++++++++++++++++++++++++------ c++/test/tlinks.cpp | 49 +++++++++++ c++/test/tobject.cpp | 185 +++++++++++++++++++++++++++++++++++++++- c++/test/ttypes.cpp | 20 ++++- 17 files changed, 668 insertions(+), 59 deletions(-) diff --git a/c++/src/H5DataType.cpp b/c++/src/H5DataType.cpp index 84e59e8..679f42f 100644 --- a/c++/src/H5DataType.cpp +++ b/c++/src/H5DataType.cpp @@ -681,6 +681,31 @@ bool DataType::isVariableStr() const } //-------------------------------------------------------------------------- +// Function: DataType::getCreatePlist +///\brief Returns a copy of the property list, which is for datatype +/// creation. +///\return A property list object +///\exception H5::DataTypeIException +// Programmer Binh-Minh Ribler - May, 2017 +// Description +// Currently, there is no datatype creation property list class +// in the C++ API because there is no associated functionality. +//-------------------------------------------------------------------------- +PropList DataType::getCreatePlist() const +{ + hid_t create_plist_id = H5Tget_create_plist(id); + if (create_plist_id < 0) + { + throw DataTypeIException(inMemFunc("getCreatePlist"), + "H5Tget_create_plist returns negative value"); + } + // create and return the DSetCreatPropList object + PropList create_plist; + f_PropList_setId(&create_plist, create_plist_id); + return(create_plist); +} + +//-------------------------------------------------------------------------- // Function: DataType::getId ///\brief Get the id of this datatype ///\return Datatype identifier diff --git a/c++/src/H5DataType.h b/c++/src/H5DataType.h index 1118dcf..ac998ef 100644 --- a/c++/src/H5DataType.h +++ b/c++/src/H5DataType.h @@ -111,6 +111,9 @@ class H5_DLLCPP DataType : public H5Object { // Checks whether this datatype is a variable-length string. bool isVariableStr() const; + // Returns a copy of the creation property list of a datatype. + PropList getCreatePlist() const; + ///\brief Returns this class name. virtual H5std_string fromClass () const { return("DataType"); } diff --git a/c++/src/H5Exception.cpp b/c++/src/H5Exception.cpp index ebb7d62..ed10044 100644 --- a/c++/src/H5Exception.cpp +++ b/c++/src/H5Exception.cpp @@ -425,6 +425,29 @@ DataTypeIException::DataTypeIException(const H5std_string& func, const H5std_str DataTypeIException::~DataTypeIException() throw() {} //-------------------------------------------------------------------------- +// Subclass: ObjHeaderIException +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// Function: ObjHeaderIException default constructor +///\brief Default constructor. +//-------------------------------------------------------------------------- +ObjHeaderIException::ObjHeaderIException():Exception(){} +//-------------------------------------------------------------------------- +// Function: ObjHeaderIException overloaded constructor +///\brief Creates an ObjHeaderIException with the name of the function, +/// in which the failure occurs, and an optional detailed message. +///\param func - IN: Name of the function where failure occurs +///\param message - IN: Message on the failure +//-------------------------------------------------------------------------- +ObjHeaderIException::ObjHeaderIException(const H5std_string& func, const H5std_string& message) : Exception(func, message) {} +//-------------------------------------------------------------------------- +// Function: ObjHeaderIException destructor +///\brief Noop destructor. +//-------------------------------------------------------------------------- +ObjHeaderIException::~ObjHeaderIException() throw() {} + +//-------------------------------------------------------------------------- // Subclass: PropListIException // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- diff --git a/c++/src/H5Exception.h b/c++/src/H5Exception.h index b57ca64..b8f29a4 100644 --- a/c++/src/H5Exception.h +++ b/c++/src/H5Exception.h @@ -121,6 +121,13 @@ class H5_DLLCPP DataTypeIException : public Exception { virtual ~DataTypeIException() throw(); }; +class H5_DLLCPP ObjHeaderIException : public Exception { + public: + ObjHeaderIException(const H5std_string& func_name, const H5std_string& message = DEFAULT_MSG); + ObjHeaderIException(); + virtual ~ObjHeaderIException() throw(); +}; + class H5_DLLCPP PropListIException : public Exception { public: PropListIException(const H5std_string& func_name, const H5std_string& message = DEFAULT_MSG); diff --git a/c++/src/H5File.cpp b/c++/src/H5File.cpp index 4d7177a..e84717c 100644 --- a/c++/src/H5File.cpp +++ b/c++/src/H5File.cpp @@ -349,6 +349,25 @@ FileAccPropList H5File::getAccessPlist() const } //-------------------------------------------------------------------------- +// Function: H5File::getFileInfo +///\brief Retrieves the general information of this file. +/// +///\exception H5::FileIException +///\par Description +/// The retrieved information may include information about +/// superblock extension, free space management, and shared object +// Programmer Binh-Minh Ribler - May 2017 +//-------------------------------------------------------------------------- +void H5File::getFileInfo(H5F_info_t& file_info) const +{ + herr_t ret_value = H5Fget_info(id, &file_info); + if (ret_value < 0) + { + throw FileIException("H5File::getFileInfo", "H5Fget_info failed"); + } +} + +//-------------------------------------------------------------------------- // Function: H5File::getFreeSpace ///\brief Returns the amount of free space in the file. ///\return Amount of free space diff --git a/c++/src/H5File.h b/c++/src/H5File.h index e06a942..06c4edc 100644 --- a/c++/src/H5File.h +++ b/c++/src/H5File.h @@ -54,6 +54,9 @@ class H5_DLLCPP H5File : public Group { // Gets the creation property list of this file. FileCreatPropList getCreatePlist() const; + // Gets general information about this file. + void getFileInfo(H5F_info_t& file_info) const; + // Retrieves the file size of an opened file. hsize_t getFileSize() const; diff --git a/c++/src/H5Group.cpp b/c++/src/H5Group.cpp index a5d052c..07e76a2 100644 --- a/c++/src/H5Group.cpp +++ b/c++/src/H5Group.cpp @@ -105,11 +105,16 @@ Group::Group(const H5Location& loc, const void* ref, H5R_type_t ref_type) : H5Ob ///\param ref_type - IN: Reference type - default to H5R_OBJECT ///\exception H5::ReferenceException // Programmer Binh-Minh Ribler - Oct, 2006 +// Modification +// May, 2017 +// Removed in 1.8.19 because H5Location is Attribute's baseclass +// now. -BMR //-------------------------------------------------------------------------- -Group::Group(const Attribute& attr, const void* ref, H5R_type_t ref_type) : H5Object(), id(H5I_INVALID_HID) +/*Group::Group(const Attribute& attr, const void* ref, H5R_type_t ref_type) : H5Object(), id(H5I_INVALID_HID) { id = H5Location::p_dereference(attr.getId(), ref, ref_type, "constructor - by dereference"); } +*/ //-------------------------------------------------------------------------- // Function: Group::getId diff --git a/c++/src/H5Group.h b/c++/src/H5Group.h index 0d26b27..ab5b186 100644 --- a/c++/src/H5Group.h +++ b/c++/src/H5Group.h @@ -39,7 +39,8 @@ class H5_DLLCPP Group : public H5Object, public CommonFG { // Creates a group by way of dereference. Group(const H5Location& loc, const void* ref, H5R_type_t ref_type = H5R_OBJECT); - Group(const Attribute& attr, const void* ref, H5R_type_t ref_type = H5R_OBJECT); + // Removed in 1.10.1, because H5Location is baseclass + //Group(const Attribute& attr, const void* ref, H5R_type_t ref_type = H5R_OBJECT); // default constructor Group(); diff --git a/c++/src/H5IdComponent.cpp b/c++/src/H5IdComponent.cpp index 7054369..a8e8ba4 100644 --- a/c++/src/H5IdComponent.cpp +++ b/c++/src/H5IdComponent.cpp @@ -163,6 +163,27 @@ H5I_type_t IdComponent::getHDFObjType() const } //-------------------------------------------------------------------------- +// Function: isValid (static) +///\brief Checks if the given ID is valid. +///\return true if the given identifier is valid, and false, otherwise. +///\par Description +/// A valid ID is one that is in use and has an application +/// reference count of at least 1. +// Programmer Binh-Minh Ribler - Mar 1, 2017 +//-------------------------------------------------------------------------- +bool IdComponent::isValid(hid_t an_id) +{ + // Call C function + htri_t ret_value = H5Iis_valid(an_id); + if (ret_value > 0) + return true; + else if (ret_value == 0) + return false; + else // Raise exception when H5Iis_valid returns a negative value + throw IdComponentException("isValid", "H5Iis_valid failed"); +} + +//-------------------------------------------------------------------------- // Function: IdComponent::operator= ///\brief Assignment operator. ///\param rhs - IN: Reference to the existing object diff --git a/c++/src/H5IdComponent.h b/c++/src/H5IdComponent.h index e9d0c84..1ada605 100644 --- a/c++/src/H5IdComponent.h +++ b/c++/src/H5IdComponent.h @@ -47,6 +47,9 @@ class H5_DLLCPP IdComponent { // Returns an HDF5 object type of this object. H5I_type_t getHDFObjType() const; + // Checks if the given ID is valid. + static bool isValid(hid_t an_id); + // Assignment operator. IdComponent& operator=(const IdComponent& rhs); diff --git a/c++/src/H5Library.cpp b/c++/src/H5Library.cpp index 7adc508..3e656e5 100644 --- a/c++/src/H5Library.cpp +++ b/c++/src/H5Library.cpp @@ -27,7 +27,6 @@ #include "H5DcreatProp.h" #include "H5DxferProp.h" #include "H5LaccProp.h" -#include "H5LaccProp.h" #include "H5Location.h" #include "H5Object.h" #include "H5DataType.h" diff --git a/c++/src/H5Location.cpp b/c++/src/H5Location.cpp index f10ad0d..33d0832 100644 --- a/c++/src/H5Location.cpp +++ b/c++/src/H5Location.cpp @@ -251,23 +251,6 @@ int H5Location::iterateAttrs(attr_operator_t user_op, unsigned *_idx, void *op_d } //-------------------------------------------------------------------------- -// Function: H5Location::getNumAttrs -///\brief Deprecated - Returns the number of attributes attached to this HDF5 object. -///\return Number of attributes -///\exception H5::AttributeIException -// Programmer Binh-Minh Ribler - 2000 -//-------------------------------------------------------------------------- -int H5Location::getNumAttrs() const -{ - H5O_info_t oinfo; /* Object info */ - - if(H5Oget_info(getId(), &oinfo) < 0) - throw AttributeIException(inMemFunc("getNumAttrs"), "H5Oget_info failed"); - else - return(static_cast(oinfo.num_attrs)); -} - -//-------------------------------------------------------------------------- // Function: H5Location::attrExists ///\brief Deprecated - Checks whether the named attribute exists at this location. ///\param name - IN: Name of the attribute to be queried @@ -354,6 +337,23 @@ void H5Location::renameAttr(const H5std_string& oldname, const H5std_string& new } //-------------------------------------------------------------------------- +// Function: H5Location::getNumAttrs +///\brief Returns the number of attributes attached to this HDF5 object. +///\return Number of attributes +///\exception H5::AttributeIException +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +int H5Location::getNumAttrs() const +{ + H5O_info_t oinfo; /* Object info */ + + if(H5Oget_info(getId(), &oinfo) < 0) + throw AttributeIException(inMemFunc("getNumAttrs"), "H5Oget_info failed"); + else + return(static_cast(oinfo.num_attrs)); +} + +//-------------------------------------------------------------------------- // Function: H5Location::nameExists ///\brief Checks if a link of a given name exists in a location ///\param name - IN: Searched name @@ -431,6 +431,39 @@ H5std_string H5Location::getFileName() const } //-------------------------------------------------------------------------- +// Function: H5Location::objVersion +///\brief Returns the header version of this HDF5 object. +///\return Object version, which can have the following values: +/// \li \c H5O_VERSION_1 +/// \li \c H5O_VERSION_2 +///\exception H5::ObjHeaderIException +/// Exception will be thrown when: +/// - an error returned by the C API +/// - version number is not one of the valid values above +// Programmer Binh-Minh Ribler - May, 2017 +//-------------------------------------------------------------------------- +unsigned H5Location::objVersion() const +{ + H5O_info_t objinfo; + unsigned version = 0; + + // Use C API to get information of the object + herr_t ret_value = H5Oget_info(getId(), &objinfo); + + // Throw exception if C API returns failure + if (ret_value < 0) + throw ObjHeaderIException(inMemFunc("objVersion"), "H5Oget_info failed"); + // Return a valid version or throw an exception for invalid value + else + { + version = objinfo.hdr.version; + if (version != H5O_VERSION_1 && version != H5O_VERSION_2) + throw ObjHeaderIException(inMemFunc("objVersion"), "Invalid version for object"); + } + return(version); +} + +//-------------------------------------------------------------------------- // Function: H5Location::setComment ///\brief Sets or resets the comment for an object specified by its name. ///\param name - IN: Name of the object @@ -454,7 +487,7 @@ void H5Location::setComment(const char* name, const char* comment) const { herr_t ret_value = H5Oset_comment_by_name(getId(), name, comment, H5P_DEFAULT); if(ret_value < 0) - throw LocationException(inMemFunc("setComment"), "H5Oset_comment_by_name failed"); + throw ObjHeaderIException(inMemFunc("setComment"), "H5Oset_comment_by_name failed"); } //-------------------------------------------------------------------------- @@ -481,7 +514,7 @@ void H5Location::setComment(const char* comment) const { herr_t ret_value = H5Oset_comment_by_name(getId(), ".", comment, H5P_DEFAULT); if(ret_value < 0) - throw LocationException(inMemFunc("setComment"), "H5Oset_comment_by_name failed"); + throw ObjHeaderIException(inMemFunc("setComment"), "H5Oset_comment_by_name failed"); } //-------------------------------------------------------------------------- @@ -511,7 +544,7 @@ void H5Location::removeComment(const char* name) const { herr_t ret_value = H5Oset_comment_by_name(getId(), name, NULL, H5P_DEFAULT); if(ret_value < 0) - throw LocationException(inMemFunc("removeComment"), "H5Oset_comment_by_name failed"); + throw ObjHeaderIException(inMemFunc("removeComment"), "H5Oset_comment_by_name failed"); } //-------------------------------------------------------------------------- @@ -551,7 +584,7 @@ ssize_t H5Location::getComment(const char* name, size_t buf_size, char* comment) // If H5Oget_comment_by_name returns a negative value, raise an exception if (comment_len < 0) { - throw LocationException("H5Location::getComment", "H5Oget_comment_by_name failed"); + throw ObjHeaderIException(inMemFunc("getComment"), "H5Oget_comment_by_name failed"); } // If the comment is longer than the provided buffer size, the C library // will not null terminate it @@ -584,7 +617,7 @@ H5std_string H5Location::getComment(const char* name, size_t buf_size) const // If H5Oget_comment_by_name returns a negative value, raise an exception if (comment_len < 0) { - throw LocationException("H5Location::getComment", "H5Oget_comment_by_name failed"); + throw ObjHeaderIException(inMemFunc("getComment"), "H5Oget_comment_by_name failed"); } // If comment exists, calls C routine again to get it @@ -605,7 +638,7 @@ H5std_string H5Location::getComment(const char* name, size_t buf_size) const if (temp_len < 0) { delete []comment_C; - throw LocationException("H5Location::getComment", "H5Oget_comment_by_name failed"); + throw ObjHeaderIException(inMemFunc("getComment"), "H5Oget_comment_by_name failed"); } // Convert the C comment to return @@ -630,6 +663,61 @@ H5std_string H5Location::getComment(const H5std_string& name, size_t buf_size) c { return(getComment(name.c_str(), buf_size)); } + +//-------------------------------------------------------------------------- +// Function: H5Location::openObjId +///\brief Opens an object without knowing the object type. +///\param obj_name - IN: Path to the object +///\param lapl - IN: Access property list for the link pointing +/// to the object +///\exception H5::ObjHeaderIException +///\par Description +/// This function opens an object at this location, using +/// H5Oopen. Thus, an object can be opened without knowing +/// the object's type. +// Programmer Binh-Minh Ribler - May, 2017 +//-------------------------------------------------------------------------- +hid_t H5Location::openObjId(const char* obj_name, const LinkAccPropList& lapl) const +{ + hid_t ret_value = H5Oopen(getId(), obj_name, lapl.getId()); + if (ret_value < 0) + { + throw ObjHeaderIException(inMemFunc("openObjId"), "H5Oopen failed"); + } + return(ret_value); +} + +//-------------------------------------------------------------------------- +// Function: H5Location::openObjId +///\brief This is an overloaded member function, provided for convenience. +/// It takes a reference to a \c H5std_string for the object's path. +///\param obj_name - IN: Path to the object +///\param lapl - IN: Access property list for the link pointing to +/// the object +///\exception H5::ObjHeaderIException +// Programmer Binh-Minh Ribler - May, 2017 +//-------------------------------------------------------------------------- +hid_t H5Location::openObjId(const H5std_string& obj_name, const LinkAccPropList& lapl) const +{ + return(openObjId(obj_name.c_str(), lapl)); +} + +//-------------------------------------------------------------------------- +// Function: H5Location::closeObjId +///\brief Closes an object, which was opened with H5Location::openObjId +/// +///\exception H5::ObjHeaderIException +// Programmer Binh-Minh Ribler - May, 2017 +//-------------------------------------------------------------------------- +void H5Location::closeObjId(hid_t obj_id) const +{ + herr_t ret_value = H5Oclose(obj_id); + if (ret_value < 0) + { + throw ObjHeaderIException(inMemFunc("closeObjId"), "H5Oclose failed"); + } +} + #ifndef DOXYGEN_SHOULD_SKIP_THIS //-------------------------------------------------------------------------- @@ -958,7 +1046,6 @@ DataSpace H5Location::getRegion(void *ref, H5R_type_t ref_type) const } } - //-------------------------------------------------------------------------- // Function: H5Location destructor ///\brief Noop destructor. diff --git a/c++/src/H5Location.h b/c++/src/H5Location.h index 11f8f87..d202328 100644 --- a/c++/src/H5Location.h +++ b/c++/src/H5Location.h @@ -95,6 +95,9 @@ class H5_DLLCPP H5Location : public IdComponent { virtual void removeAttr(const char* name) const; virtual void removeAttr(const H5std_string& name) const; + // Returns the object header version of an object + unsigned objVersion() const; + // Sets the comment for an HDF5 object specified by its name. void setComment(const char* name, const char* comment) const; void setComment(const H5std_string& name, const H5std_string& comment) const; @@ -129,6 +132,13 @@ class H5_DLLCPP H5Location : public IdComponent { // Retrieves a dataspace with the region pointed to selected. DataSpace getRegion(void *ref, H5R_type_t ref_type = H5R_DATASET_REGION) const; + // Opens an object at this location, without knowing the object type. + hid_t openObjId(const char* name, const LinkAccPropList& lapl = LinkAccPropList::DEFAULT) const; + hid_t openObjId(const H5std_string& name, const LinkAccPropList& lapl = LinkAccPropList::DEFAULT) const; + + // Closes an object opened by openObjId(). + void closeObjId(hid_t obj_id) const; + ///\brief Returns an identifier. (pure virtual) virtual hid_t getId() const = 0; diff --git a/c++/test/tfile.cpp b/c++/test/tfile.cpp index 6e12dfd..de62cf5 100644 --- a/c++/test/tfile.cpp +++ b/c++/test/tfile.cpp @@ -28,13 +28,10 @@ #else #include #endif -#include - -#ifndef H5_NO_STD - using std::cerr; - using std::endl; -#endif // H5_NO_STD +using std::cerr; +using std::endl; +#include #include "H5Cpp.h" // C++ API header file using namespace H5; @@ -52,6 +49,7 @@ const size_t F2_OFFSET_SIZE = 8; const size_t F2_LENGTH_SIZE = 8; const unsigned F2_SYM_LEAF_K = 8; const unsigned F2_SYM_INTERN_K = 32; +const unsigned F2_ISTORE = 64; const H5std_string FILE2("tfile2.h5"); const hsize_t F3_USERBLOCK_SIZE = (hsize_t)0; @@ -510,15 +508,13 @@ static void test_file_name() } // test_file_name() -#define NUM_OBJS 4 -#define NUM_ATTRS 3 const int RANK1 = 1; const int ATTR1_DIM1 = 3; const H5std_string FILE5("tfattrs.h5"); const H5std_string FATTR1_NAME ("file attribute 1"); const H5std_string FATTR2_NAME ("file attribute 2"); -int fattr_data[ATTR1_DIM1]={512,-234,98123}; /* Test data for file attribute */ -int dattr_data[ATTR1_DIM1]={256,-123,1000}; /* Test data for dataset attribute */ +int fattr_data[ATTR1_DIM1]={512,-234,98123}; // Test data for file attribute +int dattr_data[ATTR1_DIM1]={256,-123,1000}; // Test data for dataset attribute static void test_file_attribute() { @@ -691,8 +687,8 @@ static void test_libver_bounds_real( */ Group group = file.createGroup(GROUP1); - obj_version = file.childObjVersion(GROUP1); - verify_val(obj_version, oh_vers_mod, "H5File::childObjVersion", __LINE__, __FILE__); + obj_version = group.objVersion(); + verify_val(obj_version, oh_vers_mod, "Group::objVersion", __LINE__, __FILE__); group.close(); // close "/G1" @@ -702,8 +698,8 @@ static void test_libver_bounds_real( */ group = file.createGroup(SUBGROUP3); - obj_version = group.childObjVersion(SUBGROUP3); - verify_val(obj_version, oh_vers_mod, "H5File::childObjVersion", __LINE__, __FILE__); + obj_version = group.objVersion(); + verify_val(obj_version, oh_vers_mod, "Group::objVersion", __LINE__, __FILE__); group.close(); // close "/G1/G3" @@ -747,15 +743,175 @@ static void test_libver_bounds() test_libver_bounds_real(H5F_LIBVER_LATEST, H5O_VERSION_2, H5F_LIBVER_EARLIEST, H5O_VERSION_1); PASSED(); } /* end test_libver_bounds() */ + + +/*------------------------------------------------------------------------- + * Function: test_commonfg + * + * Purpose Verify that H5File works as a root group. + * + * Return None + * + * Programmer Binh-Minh Ribler (use C version) + * March, 2015 + * + *------------------------------------------------------------------------- + */ +static void test_commonfg() +{ + // Output message about test being performed + SUBTEST("Root group"); + + try { + // Create a file using default properties. + H5File file4(FILE4, H5F_ACC_TRUNC); + + // Try opening the root group. + Group rootgroup(file4.openGroup(ROOTGROUP)); + + // Create a group in the root group. + Group group(rootgroup.createGroup(GROUPNAME, 0)); + + // Create the data space. + hsize_t dims[RANK] = {NX, NY}; + DataSpace space(RANK, dims); + + // Create a new dataset. + DataSet dataset(group.createDataSet (DSETNAME, PredType::NATIVE_INT, space)); + + // Get and verify file name via a dataset. + H5std_string file_name = dataset.getFileName(); + verify_val(file_name, FILE4, "DataSet::getFileName", __LINE__, __FILE__); + + // Create an attribute for the dataset. + Attribute attr(dataset.createAttribute(DATTRNAME, PredType::NATIVE_INT, space)); + + // Get and verify file name via an attribute. + file_name = attr.getFileName(); + verify_val(file_name, FILE4, "Attribute::getFileName", __LINE__, __FILE__); + + // Create an attribute for the file via root group. + Attribute rootg_attr(rootgroup.createAttribute(FATTRNAME, PredType::NATIVE_INT, space)); + + // Get and verify file name via an attribute. + file_name = attr.getFileName(); + verify_val(file_name, FILE4, "Attribute::getFileName", __LINE__, __FILE__); + + PASSED(); + } // end of try block + + catch (Exception& E) + { + issue_fail_msg("test_commonfg()", __LINE__, __FILE__, E.getCDetailMsg()); + } + +} /* end test_commonfg() */ + + +const H5std_string FILE7("tfile7.h5"); + +/*------------------------------------------------------------------------- + * Function: test_file_info + * + * Purpose Verify that various properties in a file creation property + * lists are stored correctly in the file and can be retrieved + * when the file is re-opened. + * + * Return None + * + * Programmer Binh-Minh Ribler + * February, 2017 + * + *------------------------------------------------------------------------- + */ +const hsize_t FSP_SIZE_DEF = 4096; +const hsize_t FSP_SIZE512 = 512; +static void test_file_info() +{ + // Output message about test being performed + SUBTEST("File general information"); + + hsize_t out_threshold = 0; // Free space section threshold to get + hbool_t out_persist = FALSE;// Persist free-space read + + try { + // Create a file using default properties. + H5File tempfile(FILE7, H5F_ACC_TRUNC); + + // Get the file's version information. + H5F_info_t finfo; + tempfile.getFileInfo(finfo); // there's no C test for H5Fget_info + + // Close the file. + tempfile.close(); + + // Create file creation property list. + FileCreatPropList fcpl; + + // Set various file information. + fcpl.setUserblock(F2_USERBLOCK_SIZE); + fcpl.setSizes(F2_OFFSET_SIZE, F2_LENGTH_SIZE); + fcpl.setSymk(F2_SYM_INTERN_K, F2_SYM_LEAF_K); + fcpl.setIstorek(F2_ISTORE); + + // Creating a file with the non-default file creation property list + // should create a version 1 superblock + + // Create file with custom file creation property list. + H5File file7(FILE7, H5F_ACC_TRUNC, fcpl); + + // Close the file creation property list. + fcpl.close(); + + // Get the file's version information. + file7.getFileInfo(finfo); // there's no C test for H5Fget_info + + // Close the file. + file7.close(); + + // Re-open the file. + file7.openFile(FILE7, H5F_ACC_RDONLY); + + // Get the file's creation property list. + FileCreatPropList fcpl2 = file7.getCreatePlist(); + + // Get the file's version information. + file7.getFileInfo(finfo); // there's no C test for H5Fget_info + + // Retrieve the property values & check them. + hsize_t userblock = fcpl2.getUserblock(); + verify_val(userblock, F2_USERBLOCK_SIZE, "FileCreatPropList::getUserblock", __LINE__, __FILE__); + + size_t off_size = 0, len_size = 0; + fcpl2.getSizes(off_size, len_size); + verify_val(off_size, F2_OFFSET_SIZE, "FileCreatPropList::getSizes", __LINE__, __FILE__); + verify_val(len_size, F2_LENGTH_SIZE, "FileCreatPropList::getSizes", __LINE__, __FILE__); + + unsigned sym_ik = 0, sym_lk = 0; + fcpl2.getSymk(sym_ik, sym_lk); + verify_val(sym_ik, F2_SYM_INTERN_K, "FileCreatPropList::getSymk", __LINE__, __FILE__); + verify_val(sym_lk, F2_SYM_LEAF_K, "FileCreatPropList::getSymk", __LINE__, __FILE__); + + unsigned istore_ik = fcpl2.getIstorek(); + verify_val(istore_ik, F2_ISTORE, "FileCreatPropList::getIstorek", __LINE__, __FILE__); + + PASSED(); + } // end of try block + catch (Exception& E) + { + issue_fail_msg("test_filespace_info()", __LINE__, __FILE__, E.getCDetailMsg()); + } +} /* test_file_info() */ + /*------------------------------------------------------------------------- * Function: test_file * - * Purpose: Main file testing routine + * Purpose Main file testing routine * - * Return: None + * Return None * - * Programmer: Binh-Minh Ribler (use C version) + * Programmer Binh-Minh Ribler (use C version) * January 2001 * * Modifications: @@ -768,29 +924,33 @@ void test_file() // Output message about test being performed MESSAGE(5, ("Testing File I/O Operations\n")); - test_file_create(); // Test file creation (also creation templates) - test_file_open(); // Test file opening - test_file_size(); // Test file size - test_file_name(); // Test getting file's name - test_file_attribute(); // Test file attribute feature - test_libver_bounds(); // Test format version + test_file_create(); // Test file creation (also creation templates) + test_file_open(); // Test file opening + test_file_size(); // Test file size + test_file_name(); // Test getting file's name + test_file_attribute(); // Test file attribute feature + test_libver_bounds(); // Test format version + test_commonfg(); // Test H5File as a root group + test_file_info(); // Test various file info } // test_file() /*------------------------------------------------------------------------- * Function: cleanup_file * - * Purpose: Cleanup temporary test files + * Purpose Cleanup temporary test files * - * Return: none + * Return none * - * Programmer: (use C version) + * Programmer (use C version) * * Modifications: * *------------------------------------------------------------------------- */ +#ifdef __cplusplus extern "C" +#endif void cleanup_file() { HDremove(FILE1.c_str()); @@ -799,4 +959,5 @@ void cleanup_file() HDremove(FILE4.c_str()); HDremove(FILE5.c_str()); HDremove(FILE6.c_str()); + HDremove(FILE7.c_str()); } // cleanup_file diff --git a/c++/test/tlinks.cpp b/c++/test/tlinks.cpp index 0786bb5..58dd63a 100644 --- a/c++/test/tlinks.cpp +++ b/c++/test/tlinks.cpp @@ -441,7 +441,55 @@ static void test_basic_links(hid_t fapl_id, hbool_t new_format) issue_fail_msg("test_basic_links()", __LINE__, __FILE__, E.getCDetailMsg()); } } + +/*------------------------------------------------------------------------- + * Function: test_num_links + * + * Purpose Test setting and getting limit of number of links + * + * Return Success: 0 + * + * Failure: -1 + * + * Programmer Binh-Minh Ribler + * Mar, 2017 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_num_links(hid_t fapl_id, hbool_t new_format) +{ + char filename[NAME_BUF_SIZE]; + + if(new_format) + SUBTEST("Setting number of links (w/new group format)") + else + SUBTEST("Setting number of links") + try + { + // Use the file access template id to create a file access prop. list. + FileAccPropList fapl(fapl_id); + + h5_fixname(FILENAME[0], fapl_id, filename, sizeof filename); + H5File file(filename, H5F_ACC_RDWR, FileCreatPropList::DEFAULT, fapl); + + LinkAccPropList lapl; + size_t nlinks = 5; + lapl.setNumLinks(nlinks); + + // Read it back and verify + size_t read_nlinks = lapl.getNumLinks(); + verify_val(read_nlinks, nlinks, "LinkAccPropList::setNumLinks", __LINE__, __FILE__); + + PASSED(); + } // end of try block + catch (Exception& E) + { + issue_fail_msg("test_num_links()", __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_num_links /*------------------------------------------------------------------------- * Function: test_links @@ -494,6 +542,7 @@ void test_links() /* General tests... (on both old & new format groups */ // FileAccPropList may be passed in instead of fapl id test_basic_links(my_fapl_id, new_format); + test_num_links(my_fapl_id, new_format); #if 0 // these tests are from the C test links.c and left here for future // implementation of H5L API diff --git a/c++/test/tobject.cpp b/c++/test/tobject.cpp index 2639092..10012fc 100644 --- a/c++/test/tobject.cpp +++ b/c++/test/tobject.cpp @@ -37,6 +37,7 @@ using namespace H5; #include "h5cpputil.h" // C++ utilility header file const H5std_string FILE_OBJECTS("tobjects.h5"); +const H5std_string FILE_OBJHDR("tobject_header.h5"); const H5std_string GROUP1("Top Group"); const H5std_string GROUP1_PATH("/Top Group"); const H5std_string GROUP1_1("Sub-Group 1.1"); @@ -267,25 +268,25 @@ static void test_get_objtype() // Get and verify object type with // H5O_type_t childObjType(const H5std_string& objname) H5O_type_t objtype = file.childObjType(DSET_IN_FILE); - verify_val(objtype, H5O_TYPE_DATASET, "DataSet::childObjType", __LINE__, __FILE__); + verify_val(objtype, H5O_TYPE_DATASET, "H5File::childObjType", __LINE__, __FILE__); // Get and verify object type with // H5O_type_t childObjType(const char* objname) objtype = grp1.childObjType(GROUP1_1.c_str()); - verify_val(objtype, H5O_TYPE_GROUP, "DataSet::childObjType", __LINE__, __FILE__); + verify_val(objtype, H5O_TYPE_GROUP, "Group::childObjType", __LINE__, __FILE__); // Get and verify object type with // H5O_type_t childObjType(hsize_t index, H5_index_t index_type, // H5_iter_order_t order, const char* objname=".") objtype = grp1.childObjType((hsize_t)1, H5_INDEX_NAME, H5_ITER_INC); - verify_val(objtype, H5O_TYPE_NAMED_DATATYPE, "DataSet::childObjType", __LINE__, __FILE__); + verify_val(objtype, H5O_TYPE_NAMED_DATATYPE, "Group::childObjType", __LINE__, __FILE__); // Get and verify object type with // H5O_type_t childObjType(hsize_t index, // H5_index_t index_type=H5_INDEX_NAME, // H5_iter_order_t order=H5_ITER_INC, const char* objname=".") objtype = grp1.childObjType((hsize_t)2); - verify_val(objtype, H5O_TYPE_GROUP, "DataSet::childObjType", __LINE__, __FILE__); + verify_val(objtype, H5O_TYPE_GROUP, "Group::childObjType", __LINE__, __FILE__); // Everything will be closed as they go out of scope @@ -298,6 +299,180 @@ static void test_get_objtype() issue_fail_msg("test_get_objtype", __LINE__, __FILE__); } } // test_get_objtype + +/*------------------------------------------------------------------------- + * Function: test_open_object_header + * + * Purpose Test H5Location::openObjId function. + * + * Return None + * + * Programmer Binh-Minh Ribler (use C version) + * May 15, 2017 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +const H5std_string GROUPNAME("group"); +const H5std_string DTYPENAME("group/datatype"); +const H5std_string DTYPENAME_INGRP("datatype"); +const H5std_string DSETNAME("dataset"); +#define RANK 2 +#define DIM0 5 +#define DIM1 10 +static void test_open_object_header() +{ + hsize_t dims[2]; + H5G_info_t ginfo; /* Group info struct */ + + // Output message about test being performed + SUBTEST("H5Location::openObjId and H5Location::closeObjId"); + + try { + // Create file FILE1 + H5File file1(FILE_OBJHDR, H5F_ACC_TRUNC); + /* Create a group, dataset, and committed datatype within the file */ + + // Create a group in the root group + Group grp(file1.createGroup(GROUPNAME)); + grp.close(); + + // Commit the type inside the file + IntType dtype(PredType::NATIVE_INT); + dtype.commit(file1, DTYPENAME); + dtype.close(); + + // Create a new dataset + dims[0] = DIM0; + dims[1] = DIM1; + DataSpace dspace(RANK, dims); + DataSet dset(file1.createDataSet(DSETNAME, PredType::NATIVE_INT, dspace)); + + // Close dataset and dataspace + dset.close(); + dspace.close(); + + // Now make sure that openObjId can open all three types of objects + hid_t obj_grp = file1.openObjId(GROUPNAME); + hid_t obj_dtype = file1.openObjId(DTYPENAME); + hid_t obj_dset = file1.openObjId(DSETNAME); + + // Make sure that each is the right kind of ID + H5I_type_t id_type = IdComponent::getHDFObjType(obj_grp); + verify_val(id_type, H5I_GROUP, "H5Iget_type for group ID", __LINE__, __FILE__); + id_type = IdComponent::getHDFObjType(obj_dtype); + verify_val(id_type, H5I_DATATYPE, "H5Iget_type for datatype ID", __LINE__, __FILE__); + id_type = IdComponent::getHDFObjType(obj_dset); + verify_val(id_type, H5I_DATASET, "H5Iget_type for dataset ID", __LINE__, __FILE__); + + /* Do something more complex with each of the IDs to make sure */ + + Group grp2(obj_grp); + hsize_t num_objs = grp2.getNumObjs(); + verify_val(num_objs, 1, "H5Gget_info", __LINE__, __FILE__); + // There should be one object, the datatype + + // Close datatype object opened from the file + file1.closeObjId(obj_dtype); + + dset.setId(obj_dset); + dspace = dset.getSpace(); + bool is_simple = dspace.isSimple(); + dspace.close(); + + // Open datatype object from the group + obj_dtype = grp2.openObjId(DTYPENAME_INGRP); + + dtype.setId(obj_dtype); + H5T_class_t type_class = dtype.getClass(); + verify_val(type_class, H5T_INTEGER, "H5Tget_class", __LINE__, __FILE__); + dtype.close(); + + // Close datatype object + grp2.closeObjId(obj_dtype); + + // Close the group object + file1.closeObjId(obj_grp); + + // Try doing something with group, the ID should still work + num_objs = grp2.getNumObjs(); + verify_val(num_objs, 1, "H5Gget_info", __LINE__, __FILE__); + + // Close the cloned group + grp2.close(); + + PASSED(); + } // end of try block + // catch invalid action exception + catch (InvalidActionException& E) + { + cerr << " in InvalidActionException" << endl; + cerr << " *FAILED*" << endl; + cerr << " <<< " << E.getDetailMsg() << " >>>" << endl << endl; + } + // catch all other exceptions + catch (Exception& E) + { + cerr << " in Exception" << endl; + issue_fail_msg("test_file_name()", __LINE__, __FILE__, E.getCDetailMsg()); + } +} /* test_open_object_header() */ + +/*------------------------------------------------------------------------- + * Function: test_is_valid + * + * Purpose: Tests validating IDs. + * + * Return: Success: 0 + * Failure: -1 + * + * Programmer: Binh-Minh Ribler + * May 15, 2017 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +static void test_is_valid() +{ + SUBTEST("IdComponent::isValid"); + + try { + // Create a datatype + IntType int1(PredType::NATIVE_INT); + + // Check that the ID is valid + hid_t int1_id = int1.getId(); + bool is_valid = IdComponent::isValid(int1_id); + verify_val(is_valid, true, "IdComponent::isValid", __LINE__, __FILE__); + + // Create another datatype + FloatType float1(PredType::NATIVE_FLOAT); + + // Check that the ID is valid + is_valid = IdComponent::isValid(float1.getId()); + verify_val(is_valid, true, "IdComponent::isValid", __LINE__, __FILE__); + + // Close the integer type, then check the id, it should no longer be valid + int1.close(); + is_valid = IdComponent::isValid(int1_id); + verify_val(is_valid, false, "IdComponent::isValid", __LINE__, __FILE__); + + // Check that an id of -1 is invalid + is_valid = IdComponent::isValid((hid_t)-1); + verify_val(is_valid, false, "IdComponent::isValid", __LINE__, __FILE__); + + PASSED(); + } // try block + + // catch all other exceptions + catch (Exception& E) + { + cerr << " in catch " << endl; + issue_fail_msg("test_get_objtype", __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_is_valid /*------------------------------------------------------------------------- * Function: test_objects @@ -323,6 +498,8 @@ void test_object() test_get_objname(); // Test get object name from groups/datasets test_get_objname_ontypes(); // Test get object name from types test_get_objtype(); // Test get object type + test_is_valid(); // Test validating IDs + test_open_object_header(); // Test object header functions (H5O) } // test_objects diff --git a/c++/test/ttypes.cpp b/c++/test/ttypes.cpp index 9da05e6..384e913 100644 --- a/c++/test/ttypes.cpp +++ b/c++/test/ttypes.cpp @@ -248,12 +248,28 @@ static void test_query() index = tid2.getMemberIndex("ORANGE"); verify_val(index, 3, "EnumType::getMemberIndex()", __LINE__, __FILE__); - // Commit compound datatype and close it + // Commit compound datatype, and test getting the datatype creation + // prop list, then close it tid1.commit(file, CompT_NAME); + PropList tcpl = tid1.getCreatePlist(); + if (!IdComponent::isValid(tcpl.getId())) + { + // Throw an invalid action exception + throw InvalidActionException("IdComponent::isValid", "Datatype creation property list is not valid"); + } + tcpl.close(); tid1.close(); - // Commit enumeration datatype and close it + // Commit enumeration datatype, and test getting the datatype creation + // prop list, then close it tid2.commit(file, EnumT_NAME); + tcpl = tid2.getCreatePlist(); + if (!IdComponent::isValid(tcpl.getId())) + { + // Throw an invalid action exception + throw InvalidActionException("IdComponent::isValid", "Datatype creation property list is not valid"); + } + tcpl.close(); tid2.close(); // Open the datatypes for query -- cgit v0.12