From 8df5c966e09c34524c39d4afe71029ef6664d687 Mon Sep 17 00:00:00 2001 From: Binh-Minh Ribler Date: Wed, 10 May 2017 10:20:28 -0500 Subject: Improvement of class hierarchy Description: - Moved class Attribute to be derived from class H5Location instead of IdComponent because an attribute id can be used as loc_id in C APIs. - Copied wrappers of H5A APIs in H5Location into H5Object because H5A functions do not take an attribute id as loc_id. The original wrappers will be deprecated in future releases. - Revised comments Platforms tested: Linux/32 2.6 (jam) Linux/64 (platypus) Darwin (osx1010test) --- c++/src/H5Attribute.cpp | 6 +- c++/src/H5Attribute.h | 4 +- c++/src/H5IdComponent.h | 2 - c++/src/H5Location.cpp | 36 ++++++--- c++/src/H5Location.h | 47 ++++++----- c++/src/H5Object.cpp | 210 +++++++++++++++++++++++++++++++++++++++++++++++- c++/src/H5Object.h | 24 ++++++ c++/test/tfile.cpp | 12 +++ 8 files changed, 298 insertions(+), 43 deletions(-) diff --git a/c++/src/H5Attribute.cpp b/c++/src/H5Attribute.cpp index cb0186a..55ccfe7 100644 --- a/c++/src/H5Attribute.cpp +++ b/c++/src/H5Attribute.cpp @@ -49,7 +49,7 @@ namespace H5 { ///\brief Default constructor: Creates a stub attribute // Programmer Binh-Minh Ribler - May, 2004 //-------------------------------------------------------------------------- -Attribute::Attribute() : AbstractDs(), IdComponent(), id(H5I_INVALID_HID) {} +Attribute::Attribute() : AbstractDs(), H5Location(), id(H5I_INVALID_HID) {} //-------------------------------------------------------------------------- // Function: Attribute copy constructor @@ -57,7 +57,7 @@ Attribute::Attribute() : AbstractDs(), IdComponent(), id(H5I_INVALID_HID) {} ///\param original - IN: Original Attribute object to copy // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- -Attribute::Attribute(const Attribute& original) : AbstractDs(), IdComponent(), id(original.id) +Attribute::Attribute(const Attribute& original) : AbstractDs(), H5Location(), id(original.id) { incRefCount(); // increment number of references to this id } @@ -70,7 +70,7 @@ Attribute::Attribute(const Attribute& original) : AbstractDs(), IdComponent(), i ///\exception H5::AttributeIException // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- -Attribute::Attribute(const hid_t existing_id) : AbstractDs(), IdComponent(), id(existing_id) +Attribute::Attribute(const hid_t existing_id) : AbstractDs(), H5Location(), id(existing_id) { incRefCount(); // increment number of references to this id } diff --git a/c++/src/H5Attribute.h b/c++/src/H5Attribute.h index 10f46ae..33145bc 100644 --- a/c++/src/H5Attribute.h +++ b/c++/src/H5Attribute.h @@ -27,8 +27,8 @@ namespace H5 { inherits from IdComponent because an attribute is an HDF5 component that is identified by an identifier. */ -// Inheritance: multiple IdComponent/AbstractDs -class H5_DLLCPP Attribute : public AbstractDs, public IdComponent { +// Inheritance: multiple H5Location/AbstractDs +class H5_DLLCPP Attribute : public AbstractDs, public H5Location { public: // Copy constructor: makes a copy of an existing Attribute object. diff --git a/c++/src/H5IdComponent.h b/c++/src/H5IdComponent.h index 0f83168..e9d0c84 100644 --- a/c++/src/H5IdComponent.h +++ b/c++/src/H5IdComponent.h @@ -19,8 +19,6 @@ namespace H5 { -//class DataSpace; - /*! \class IdComponent \brief Class IdComponent provides wrappers of the C functions that operate on an HDF5 identifier. diff --git a/c++/src/H5Location.cpp b/c++/src/H5Location.cpp index 855e6d2..60f9c3b 100644 --- a/c++/src/H5Location.cpp +++ b/c++/src/H5Location.cpp @@ -84,9 +84,19 @@ H5Location::H5Location() : IdComponent() {} #endif // DOXYGEN_SHOULD_SKIP_THIS +/*************************************************************************** + Notes for H5A wrappers + ====================== +May, 2017 (1.8.19) + These H5A wrappers are copied from H5Object to prevent an attribute + id being passed in to H5A APIs. The original H5A wrapper functions + here will be deprecated in future releases. + +***************************************************************************/ + //-------------------------------------------------------------------------- // Function: H5Location::createAttribute -///\brief Creates an attribute for a group, dataset, or named datatype. +///\brief Deprecated - Creates an attribute for a group, dataset, or named datatype. ///\param name - IN: Name of the attribute ///\param data_type - IN: Datatype for the attribute ///\param data_space - IN: Dataspace for the attribute - only simple @@ -125,7 +135,7 @@ Attribute H5Location::createAttribute(const char* name, const DataType& data_typ //-------------------------------------------------------------------------- // Function: H5Location::createAttribute -///\brief This is an overloaded member function, provided for convenience. +///\brief Deprecated - This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes /// a reference to an \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 @@ -137,7 +147,7 @@ Attribute H5Location::createAttribute(const H5std_string& name, const DataType& //-------------------------------------------------------------------------- // Function: H5Location::openAttribute -///\brief Opens an attribute given its name. +///\brief Deprecated - Opens an attribute given its name. ///\param name - IN: Name of the attribute ///\return Attribute instance ///\exception H5::AttributeIException @@ -160,7 +170,7 @@ Attribute H5Location::openAttribute(const char* name) const //-------------------------------------------------------------------------- // Function: H5Location::openAttribute -///\brief This is an overloaded member function, provided for convenience. +///\brief Deprecated - This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes /// a reference to an \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 @@ -172,7 +182,7 @@ Attribute H5Location::openAttribute(const H5std_string& name) const //-------------------------------------------------------------------------- // Function: H5Location::openAttribute -///\brief Opens an attribute given its index. +///\brief Deprecated - Opens an attribute given its index. ///\param idx - IN: Index of the attribute, a 0-based, non-negative integer ///\return Attribute instance ///\exception H5::AttributeIException @@ -196,7 +206,7 @@ Attribute H5Location::openAttribute(const unsigned int idx) const //-------------------------------------------------------------------------- // Function: H5Location::iterateAttrs -///\brief Iterates a user's function over all the attributes of an H5 +///\brief Deprecated - Iterates a user's function over all the attributes of an H5 /// object, which may be a group, dataset or named datatype. ///\param user_op - IN: User's function to operate on each attribute ///\param _idx - IN/OUT: Starting (IN) and ending (OUT) attribute indices @@ -241,7 +251,7 @@ int H5Location::iterateAttrs(attr_operator_t user_op, unsigned *_idx, void *op_d //-------------------------------------------------------------------------- // Function: H5Location::getNumAttrs -///\brief Returns the number of attributes attached to this HDF5 object. +///\brief Deprecated - Returns the number of attributes attached to this HDF5 object. ///\return Number of attributes ///\exception H5::AttributeIException // Programmer Binh-Minh Ribler - 2000 @@ -258,7 +268,7 @@ int H5Location::getNumAttrs() const //-------------------------------------------------------------------------- // Function: H5Location::attrExists -///\brief Checks whether the named attribute exists at this location. +///\brief Deprecated - Checks whether the named attribute exists at this location. ///\param name - IN: Name of the attribute to be queried ///\exception H5::AttributeIException // Programmer Binh-Minh Ribler - 2013 @@ -279,7 +289,7 @@ bool H5Location::attrExists(const char* name) const //-------------------------------------------------------------------------- // Function: H5Location::attrExists -///\brief This is an overloaded member function, provided for convenience. +///\brief Deprecated - This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes /// a reference to an \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 @@ -291,7 +301,7 @@ bool H5Location::attrExists(const H5std_string& name) const //-------------------------------------------------------------------------- // Function: H5Location::removeAttr -///\brief Removes the named attribute from this object. +///\brief Deprecated - Removes the named attribute from this object. ///\param name - IN: Name of the attribute to be removed ///\exception H5::AttributeIException // Programmer Binh-Minh Ribler - 2000 @@ -305,7 +315,7 @@ void H5Location::removeAttr(const char* name) const //-------------------------------------------------------------------------- // Function: H5Location::removeAttr -///\brief This is an overloaded member function, provided for convenience. +///\brief Deprecated - This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes /// a reference to an \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 @@ -317,7 +327,7 @@ void H5Location::removeAttr(const H5std_string& name) const //-------------------------------------------------------------------------- // Function: H5Location::renameAttr -///\brief Renames the named attribute from this object. +///\brief Deprecated - Renames the named attribute from this object. ///\param oldname - IN: Name of the attribute to be renamed ///\param newname - IN: New name ame of the attribute ///\exception H5::AttributeIException @@ -332,7 +342,7 @@ void H5Location::renameAttr(const char* oldname, const char* newname) const //-------------------------------------------------------------------------- // Function: H5Location::renameAttr -///\brief This is an overloaded member function, provided for convenience. +///\brief Deprecated - This is an overloaded member function, provided for convenience. /// It differs from the above function in that it takes /// a reference to an \c H5std_string for the names. // Programmer Binh-Minh Ribler - Mar, 2005 diff --git a/c++/src/H5Location.h b/c++/src/H5Location.h index c49b23b..edc2b53 100644 --- a/c++/src/H5Location.h +++ b/c++/src/H5Location.h @@ -36,33 +36,26 @@ class UserData4Aiterate { // user data for attribute iteration }; /*! \class H5Location - \brief H5Location is an abstract base class, added in version 1.8.12. - - It provides a collection of wrappers for the C functions that take a - location identifier to specify the HDF5 object. The location identifier - can be either file, group, dataset, attribute, or named datatype. + \brief H5Location is an abstract base class, providing a collection of + wrappers of the C functions that take a location identifier, which can be + either file, group, dataset, attribute, or named datatype. */ // Inheritance: IdComponent - -// Most of these methods were in H5Object but are now moved here because -// a location can be a file, group, dataset, or named datatype. -BMR, 2013-10-1 -// Wrappers for H5A functions that operate existing attributes are in H5Object. -// -BMR, 2017-05-04 class H5_DLLCPP H5Location : public IdComponent { public: // Creates an attribute for the specified object at this location // PropList is currently not used, so always be default. - Attribute createAttribute(const char* name, const DataType& type, const DataSpace& space, const PropList& create_plist = PropList::DEFAULT) const; - Attribute createAttribute(const H5std_string& name, const DataType& type, const DataSpace& space, const PropList& create_plist = PropList::DEFAULT) const; + virtual Attribute createAttribute(const char* name, const DataType& type, const DataSpace& space, const PropList& create_plist = PropList::DEFAULT) const; + virtual Attribute createAttribute(const H5std_string& name, const DataType& type, const DataSpace& space, const PropList& create_plist = PropList::DEFAULT) const; // Given its name, opens the attribute that belongs to an object at // this location. - Attribute openAttribute(const char* name) const; - Attribute openAttribute(const H5std_string& name) const; + virtual Attribute openAttribute(const char* name) const; + virtual Attribute openAttribute(const H5std_string& name) const; // Given its index, opens the attribute that belongs to an object at // this location. - Attribute openAttribute(const unsigned int idx) const; + virtual Attribute openAttribute(const unsigned int idx) const; // Flushes all buffers associated with this location to disk. void flush(H5F_scope_t scope) const; @@ -84,19 +77,19 @@ class H5_DLLCPP H5Location : public IdComponent { // misleading, so getRefObjType is used in the new function instead. // Iterate user's function over the attributes at this location. - int iterateAttrs(attr_operator_t user_op, unsigned* idx = NULL, void* op_data = NULL); + virtual int iterateAttrs(attr_operator_t user_op, unsigned* idx = NULL, void* op_data = NULL); // Checks whether the named attribute exists at this location. - bool attrExists(const char* name) const; - bool attrExists(const H5std_string& name) const; + virtual bool attrExists(const char* name) const; + virtual bool attrExists(const H5std_string& name) const; // Renames the named attribute to a new name. - void renameAttr(const char* oldname, const char* newname) const; - void renameAttr(const H5std_string& oldname, const H5std_string& newname) const; + virtual void renameAttr(const char* oldname, const char* newname) const; + virtual void renameAttr(const H5std_string& oldname, const H5std_string& newname) const; // Removes the named attribute from this location. - void removeAttr(const char* name) const; - void removeAttr(const H5std_string& name) const; + virtual void removeAttr(const char* name) const; + virtual void removeAttr(const H5std_string& name) const; // Sets the comment for an HDF5 object specified by its name. void setComment(const char* name, const char* comment) const; @@ -177,3 +170,13 @@ class H5_DLLCPP H5Location : public IdComponent { } // namespace H5 #endif // __H5Location_H + +// Modification +// Oct 1, 2013 -BMR +// H5Location is added in version 1.8.12. +// Most of these methods were in H5Object but are now moved here +// because a location can be a file, group, dataset, or named datatype. +// May 04, 2017 -BMR +// Wrappers for H5A functions are copied to H5Object because H5A +// functions do not take an attribute id as loc_id. The original +// wrappers will be deprecated in future releases. diff --git a/c++/src/H5Object.cpp b/c++/src/H5Object.cpp index 60e7afb..933e8ec 100644 --- a/c++/src/H5Object.cpp +++ b/c++/src/H5Object.cpp @@ -22,8 +22,8 @@ #include "H5PropList.h" #include "H5DataSpace.h" #include "H5AbstractDs.h" -#include "H5Attribute.h" #include "H5Location.h" +#include "H5Attribute.h" #include "H5Object.h" #include "H5DataType.h" @@ -64,6 +64,214 @@ H5Object::H5Object() : H5Location() {} //-------------------------------------------------------------------------- // H5Object::H5Object(const H5Object& original) : H5Location() {} +/*************************************************************************** + Notes for H5A wrappers + ====================== +May, 2017 (1.8.19) + These H5A wrappers are copied from H5Location to prevent an attribute + id being passed in to H5A APIs. The original H5A wrapper functions + in H5Location will be deprecated in future releases. + +***************************************************************************/ + +//-------------------------------------------------------------------------- +// Function: H5Object::createAttribute +///\brief Creates an attribute for a group, dataset, or named datatype. +///\param name - IN: Name of the attribute +///\param data_type - IN: Datatype for the attribute +///\param data_space - IN: Dataspace for the attribute - only simple +/// dataspaces are allowed at this time +///\param create_plist - IN: Creation property list - default to +/// PropList::DEFAULT +///\return Attribute instance +///\exception H5::AttributeIException +///\par Description +/// The attribute name specified in \a name must be unique. +/// Attempting to create an attribute with the same name as an +/// existing attribute will raise an exception, leaving the +/// pre-existing attribute intact. To overwrite an existing +/// attribute with a new attribute of the same name, first +/// delete the existing one with \c H5Object::removeAttr, then +/// recreate it with this function. +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +Attribute H5Object::createAttribute(const char* name, const DataType& data_type, const DataSpace& data_space, const PropList& create_plist) const +{ + hid_t type_id = data_type.getId(); + hid_t space_id = data_space.getId(); + hid_t plist_id = create_plist.getId(); + hid_t attr_id = H5Acreate2(getId(), name, type_id, space_id, plist_id, H5P_DEFAULT); + + // If the attribute id is valid, create and return the Attribute object + if (attr_id > 0) + { + Attribute attr; + f_Attribute_setId(&attr, attr_id); + return(attr); + } + else + throw AttributeIException(inMemFunc("createAttribute"), "H5Acreate2 failed"); +} + +//-------------------------------------------------------------------------- +// Function: H5Object::createAttribute +///\brief This is an overloaded member function, provided for convenience. +/// It differs from the above function in that it takes +/// a reference to an \c H5std_string for \a name. +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +Attribute H5Object::createAttribute(const H5std_string& name, const DataType& data_type, const DataSpace& data_space, const PropList& create_plist) const +{ + return(createAttribute(name.c_str(), data_type, data_space, create_plist)); +} + +//-------------------------------------------------------------------------- +// Function: H5Object::openAttribute +///\brief Opens an attribute given its name. +///\param name - IN: Name of the attribute +///\return Attribute instance +///\exception H5::AttributeIException +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +Attribute H5Object::openAttribute(const char* name) const +{ + hid_t attr_id = H5Aopen(getId(), name, H5P_DEFAULT); + if (attr_id > 0) + { + Attribute attr; + f_Attribute_setId(&attr, attr_id); + return(attr); + } + else + { + throw AttributeIException(inMemFunc("openAttribute"), "H5Aopen failed"); + } +} + +//-------------------------------------------------------------------------- +// Function: H5Object::openAttribute +///\brief This is an overloaded member function, provided for convenience. +/// It differs from the above function in that it takes +/// a reference to an \c H5std_string for \a name. +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +Attribute H5Object::openAttribute(const H5std_string& name) const +{ + return(openAttribute(name.c_str())); +} + +//-------------------------------------------------------------------------- +// Function: H5Object::openAttribute +///\brief Opens an attribute given its index. +///\param idx - IN: Index of the attribute, a 0-based, non-negative integer +///\return Attribute instance +///\exception H5::AttributeIException +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +Attribute H5Object::openAttribute(const unsigned int idx) const +{ + hid_t attr_id = H5Aopen_by_idx(getId(), ".", H5_INDEX_CRT_ORDER, + H5_ITER_INC, static_cast(idx), H5P_DEFAULT, H5P_DEFAULT); + if (attr_id > 0) + { + Attribute attr; + f_Attribute_setId(&attr, attr_id); + return(attr); + } + else + { + throw AttributeIException(inMemFunc("openAttribute"), "H5Aopen_by_idx failed"); + } +} + +//-------------------------------------------------------------------------- +// Function: H5Object::attrExists +///\brief Checks whether the named attribute exists at this location. +///\param name - IN: Name of the attribute to be queried +///\exception H5::AttributeIException +// Programmer Binh-Minh Ribler - 2013 +//-------------------------------------------------------------------------- +bool H5Object::attrExists(const char* name) const +{ + // Call C routine H5Aexists to determine whether an attribute exists + // at this location, which could be specified by a file, group, dataset, + // or named datatype. + herr_t ret_value = H5Aexists(getId(), name); + if(ret_value > 0) + return true; + else if(ret_value == 0) + return false; + else // Raise exception when H5Aexists returns a negative value + throw AttributeIException(inMemFunc("attrExists"), "H5Aexists failed"); +} + +//-------------------------------------------------------------------------- +// Function: H5Object::attrExists +///\brief This is an overloaded member function, provided for convenience. +/// It differs from the above function in that it takes +/// a reference to an \c H5std_string for \a name. +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +bool H5Object::attrExists(const H5std_string& name) const +{ + return(attrExists(name.c_str())); +} + +//-------------------------------------------------------------------------- +// Function: H5Object::removeAttr +///\brief Removes the named attribute from this object. +///\param name - IN: Name of the attribute to be removed +///\exception H5::AttributeIException +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +void H5Object::removeAttr(const char* name) const +{ + herr_t ret_value = H5Adelete(getId(), name); + if(ret_value < 0) + throw AttributeIException(inMemFunc("removeAttr"), "H5Adelete failed"); +} + +//-------------------------------------------------------------------------- +// Function: H5Object::removeAttr +///\brief This is an overloaded member function, provided for convenience. +/// It differs from the above function in that it takes +/// a reference to an \c H5std_string for \a name. +// Programmer Binh-Minh Ribler - 2000 +//-------------------------------------------------------------------------- +void H5Object::removeAttr(const H5std_string& name) const +{ + removeAttr(name.c_str()); +} + +//-------------------------------------------------------------------------- +// Function: H5Object::renameAttr +///\brief Renames the named attribute from this object. +///\param oldname - IN: Name of the attribute to be renamed +///\param newname - IN: New name ame of the attribute +///\exception H5::AttributeIException +// Programmer Binh-Minh Ribler - Mar, 2005 +//-------------------------------------------------------------------------- +void H5Object::renameAttr(const char* oldname, const char* newname) const +{ + herr_t ret_value = H5Arename(getId(), oldname, newname); + if (ret_value < 0) + throw AttributeIException(inMemFunc("renameAttr"), "H5Arename failed"); +} + +//-------------------------------------------------------------------------- +// Function: H5Object::renameAttr +///\brief This is an overloaded member function, provided for convenience. +/// It differs from the above function in that it takes +/// a reference to an \c H5std_string for the names. +// Programmer Binh-Minh Ribler - Mar, 2005 +//-------------------------------------------------------------------------- +void H5Object::renameAttr(const H5std_string& oldname, const H5std_string& newname) const +{ + renameAttr (oldname.c_str(), newname.c_str()); +} + +// end of Notes for H5A wrappers + //-------------------------------------------------------------------------- // Function: getObjName ///\brief Given an id, returns the type of the object. diff --git a/c++/src/H5Object.h b/c++/src/H5Object.h index fa9e8a9..b118bb8 100644 --- a/c++/src/H5Object.h +++ b/c++/src/H5Object.h @@ -37,6 +37,30 @@ namespace H5 { // Inheritance: H5Location -> IdComponent class H5_DLLCPP H5Object : public H5Location { public: + // Creates an attribute for the specified object + // PropList is currently not used, so always be default. + Attribute createAttribute(const char* name, const DataType& type, const DataSpace& space, const PropList& create_plist = PropList::DEFAULT) const; + Attribute createAttribute(const H5std_string& name, const DataType& type, const DataSpace& space, const PropList& create_plist = PropList::DEFAULT) const; + + // Given its name, opens the attribute that belongs to this object. + Attribute openAttribute(const char* name) const; + Attribute openAttribute(const H5std_string& name) const; + + // Given its index, opens the attribute that belongs to this object. + Attribute openAttribute(const unsigned int idx) const; + + // Checks whether the named attribute exists for this object. + bool attrExists(const char* name) const; + bool attrExists(const H5std_string& name) const; + + // Renames the named attribute of this object to a new name. + void renameAttr(const char* oldname, const char* newname) const; + void renameAttr(const H5std_string& oldname, const H5std_string& newname) const; + + // Removes the named attribute from this object. + void removeAttr(const char* name) const; + void removeAttr(const H5std_string& name) const; + // Gets the name of this HDF5 object, i.e., Group, DataSet, or // DataType. ssize_t getObjName(char *obj_name, size_t buf_size = 0) const; diff --git a/c++/test/tfile.cpp b/c++/test/tfile.cpp index bd229d7..6e12dfd 100644 --- a/c++/test/tfile.cpp +++ b/c++/test/tfile.cpp @@ -601,6 +601,18 @@ static void test_file_attribute() n_attrs = dataset.getNumAttrs(); verify_val(n_attrs, 1, "DataSet::getNumAttrs()", __LINE__, __FILE__); + // Get and verify the number of attributes at the location specified + // by a dataset's attribute + n_attrs = 0; + n_attrs = dattr.getNumAttrs(); + verify_val(n_attrs, 1, "Attribute::getNumAttrs()", __LINE__, __FILE__); + + // Get and verify the number of attributes at the location specified + // by a file's attribute + n_attrs = 0; + n_attrs = fattr1.getNumAttrs(); + verify_val(n_attrs, 2, "Attribute::getNumAttrs()", __LINE__, __FILE__); + // Read back attribute's data HDmemset(rdata, 0, sizeof(rdata)); dattr.read(PredType::NATIVE_INT, rdata); -- cgit v0.12