/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Copyright by The HDF Group. * * All rights reserved. * * * * This file is part of HDF5. The full HDF5 copyright notice, including * * terms governing use, modification, and redistribution, is contained in * * the COPYING file, which can be found at the root of the source code * * distribution tree, or in https://www.hdfgroup.org/licenses. * * If you do not have access to either file, you may request a copy from * * help@hdfgroup.org. * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ #include #include "H5Include.h" #include "H5Exception.h" #include "H5Library.h" #include "H5IdComponent.h" #include "H5DataSpace.h" namespace H5 { #ifndef DOXYGEN_SHOULD_SKIP_THIS // This flag indicates whether H5Library::initH5cpp has been called to register // the terminating functions with atexit() bool IdComponent::H5cppinit = false; // This flag is used to decide whether H5dont_atexit should be called. // Subclasses that have global constants use it. This is a temporary // work-around in 1.8.16. It will be removed after HDFFV-9540 is fixed. bool IdComponent::H5dontAtexit_called = false; #endif // DOXYGEN_SHOULD_SKIP_THIS //-------------------------------------------------------------------------- // Function: IdComponent::incRefCount ///\brief Increment reference counter for a given id. //-------------------------------------------------------------------------- void IdComponent::incRefCount(const hid_t obj_id) const { if (p_valid_id(obj_id)) if (H5Iinc_ref(obj_id) < 0) throw IdComponentException(inMemFunc("incRefCount"), "incrementing object ref count failed"); } //-------------------------------------------------------------------------- // Function: IdComponent::incRefCount ///\brief Increment reference counter for the id of this object. //-------------------------------------------------------------------------- void IdComponent::incRefCount() const { incRefCount(getId()); } //-------------------------------------------------------------------------- // Function: IdComponent::decRefCount ///\brief Decrement reference counter for a given id. // Modification: // Added the check for ref counter to give a little more info // on why H5Idec_ref fails in some cases - BMR 5/19/2005 //-------------------------------------------------------------------------- void IdComponent::decRefCount(const hid_t obj_id) const { if (p_valid_id(obj_id)) if (H5Idec_ref(obj_id) < 0) { if (H5Iget_ref(obj_id) <= 0) throw IdComponentException(inMemFunc("decRefCount"), "object ref count is 0 or negative"); else throw IdComponentException(inMemFunc("decRefCount"), "decrementing object ref count failed"); } } //-------------------------------------------------------------------------- // Function: IdComponent::decRefCount ///\brief Decrement reference counter for the id of this object. //-------------------------------------------------------------------------- void IdComponent::decRefCount() const { decRefCount(getId()); } //-------------------------------------------------------------------------- // Function: IdComponent::getCounter ///\brief Returns the reference counter for a given id. ///\return Reference count //-------------------------------------------------------------------------- int IdComponent::getCounter(const hid_t obj_id) const { int counter = 0; if (p_valid_id(obj_id)) { counter = H5Iget_ref(obj_id); if (counter < 0) throw IdComponentException(inMemFunc("incRefCount"), "getting object ref count failed - negative"); } return (counter); } //-------------------------------------------------------------------------- // Function: IdComponent::getCounter ///\brief Returns the reference counter for the id of this object. ///\return Reference count //-------------------------------------------------------------------------- int IdComponent::getCounter() const { return (getCounter(getId())); } //-------------------------------------------------------------------------- // Function: getHDFObjType (static) ///\brief Given an id, returns the type of the object. ///\return a valid HDF object type, which may be one of the following: /// \li \c H5I_FILE /// \li \c H5I_GROUP /// \li \c H5I_DATATYPE /// \li \c H5I_DATASPACE /// \li \c H5I_DATASET /// \li \c H5I_ATTR /// \li or \c H5I_BADID, if no valid type can be determined or the /// input object id is invalid. //-------------------------------------------------------------------------- H5I_type_t IdComponent::getHDFObjType(const hid_t obj_id) { if (obj_id <= 0) return H5I_BADID; // invalid H5I_type_t id_type = H5Iget_type(obj_id); if (id_type <= H5I_BADID || id_type >= H5I_NTYPES) return H5I_BADID; // invalid else return id_type; // valid type } //-------------------------------------------------------------------------- // Function: getHDFObjType ///\brief Returns the type of the object. It is an overloaded function /// of the above function. ///\return a valid HDF object type, which may be one of the following: /// \li \c H5I_FILE /// \li \c H5I_GROUP /// \li \c H5I_DATATYPE /// \li \c H5I_DATASPACE /// \li \c H5I_DATASET /// \li \c H5I_ATTR /// \li or \c H5I_BADID, if no valid type can be determined or the /// input object id is invalid. //-------------------------------------------------------------------------- H5I_type_t IdComponent::getHDFObjType() const { return (getHDFObjType(getId())); } //-------------------------------------------------------------------------- // Function: getNumMembers (static) ///\brief Returns the number of members of the given type. ///\return Number of members ///\par Description /// If there is no member of the given type, getNumMembers will /// return 0. Valid types are: /// \li \c H5I_FILE (= 1) /// \li \c H5I_GROUP /// \li \c H5I_DATATYPE /// \li \c H5I_DATASPACE /// \li \c H5I_DATASET /// \li \c H5I_ATTR /// \li \c H5I_VFL /// \li \c H5I_VOL /// \li \c H5I_GENPROP_CLS /// \li \c H5I_GENPROP_LST /// \li \c H5I_ERROR_CLASS /// \li \c H5I_ERROR_MSG /// \li \c H5I_ERROR_STACK //-------------------------------------------------------------------------- hsize_t IdComponent::getNumMembers(H5I_type_t type) { hsize_t nmembers = 0; herr_t ret_value = H5Inmembers(type, &nmembers); if (ret_value < 0) throw IdComponentException("getNumMembers", "H5Inmembers failed"); else return (nmembers); } //-------------------------------------------------------------------------- // 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. //-------------------------------------------------------------------------- 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: typeExists (static) ///\brief Queries if a given type is currently registered with the /// library. ///\return true if the given type exists, and false, otherwise. ///\par Description /// Valid types are: /// \li \c H5I_FILE (= 1) /// \li \c H5I_GROUP /// \li \c H5I_DATATYPE /// \li \c H5I_DATASPACE /// \li \c H5I_DATASET /// \li \c H5I_ATTR /// \li \c H5I_VFL /// \li \c H5I_VOL /// \li \c H5I_GENPROP_CLS /// \li \c H5I_GENPROP_LST /// \li \c H5I_ERROR_CLASS /// \li \c H5I_ERROR_MSG /// \li \c H5I_ERROR_STACK //-------------------------------------------------------------------------- bool IdComponent::typeExists(H5I_type_t type) { // Call C function htri_t ret_value = H5Itype_exists(type); if (ret_value > 0) return true; else if (ret_value == 0) return false; else // Raise exception when H5Itype_exists returns a negative value throw IdComponentException("typeExists", "H5Itype_exists failed"); } //-------------------------------------------------------------------------- // Function: IdComponent::operator= ///\brief Assignment operator. ///\param rhs - IN: Reference to the existing object ///\return Reference to IdComponent instance ///\exception H5::IdComponentException when attempt to close the HDF5 /// object fails // Description // First, close the current valid id of this object. Then // copy the id from rhs to this object, and increment the // reference counter of the id to indicate that another object // is referencing that id. // Modification // 2010/5/9 - BMR // Removed close() and incRefCount() because setId/p_setId takes // care of close() and setId takes care incRefCount(). //-------------------------------------------------------------------------- IdComponent & IdComponent::operator=(const IdComponent &rhs) { if (this != &rhs) { // handling references to this id try { setId(rhs.getId()); // Note: a = b, so there are two objects with the same hdf5 id // that's why incRefCount is needed, and it is called by setId } catch (Exception &close_error) { throw FileIException(inMemFunc("operator="), close_error.getDetailMsg()); } } return *this; } //-------------------------------------------------------------------------- // Function: IdComponent::setId ///\brief Sets the identifier of this object to a new value. ///\param new_id - IN: New identifier to be set to ///\exception H5::IdComponentException when the attempt to close the HDF5 /// object fails // Description: // p_setId ensures that the current valid id of this object is // properly closed before resetting the object's id to the new id. // Modification // 2008/7/23 - BMR // Changed all subclasses' setId to p_setId and put back setId // here. p_setId is used in the library where the id provided // by a C API passed on to user's application in the form of a // C++ API object, which will be destroyed properly, and so // p_setId does not call incRefCount. On the other hand, the // public version setId is used by other applications, in which // the id passed to setId is that of another C++ API object, so // setId must call incRefCount. //-------------------------------------------------------------------------- void IdComponent::setId(const hid_t new_id) { // set to new_id p_setId(new_id); // increment the reference counter of the new id incRefCount(); } // // Implementation of protected functions for HDF5 Reference Interface // and miscellaneous helpers. // #ifndef DOXYGEN_SHOULD_SKIP_THIS //-------------------------------------------------------------------------- // Function: IdComponent::inMemFunc ///\brief Makes and returns string "::" ///\param func_name - Name of the function where failure occurs // Description /// Concatenates the class name of this object with the /// passed-in function name to create a string that indicates /// where the failure occurs. The class-name is provided by /// fromClass(). This string will be used by a base class when /// an exception is thrown. //-------------------------------------------------------------------------- H5std_string IdComponent::inMemFunc(const char *func_name) const { H5std_string full_name = func_name; full_name.insert(0, "::"); full_name.insert(0, fromClass()); return (full_name); } //-------------------------------------------------------------------------- // Function: IdComponent default constructor - private ///\brief Default constructor. //-------------------------------------------------------------------------- IdComponent::IdComponent() { // initH5cpp will register the terminating functions with atexit(). // This should only be done once. if (!H5cppinit) { H5Library::initH5cpp(); H5cppinit = true; } } //-------------------------------------------------------------------------- // Function: IdComponent::p_get_file_name (protected) // Purpose Gets the name of the file, in which this object belongs. // Exception: H5::IdComponentException // Description: // This function is protected so that the user applications can // only have access to its code via H5Location subclasses. // September 2017 // This function should be moved to H5Location now that Attribute // inherits from H5Location. //-------------------------------------------------------------------------- H5std_string IdComponent::p_get_file_name() const { hid_t temp_id = getId(); // Preliminary call to H5Fget_name to get the length of the file name ssize_t name_size = H5Fget_name(temp_id, NULL, 0); // If H5Aget_name returns a negative value, raise an exception, if (name_size < 0) { throw IdComponentException("", "H5Fget_name failed"); } // The actual message size is the cast value + 1 for the terminal ASCII NUL // (unfortunate in/out type sign mismatch) size_t actual_name_size = static_cast(name_size) + 1; // Call H5Fget_name again to get the actual file name char *name_C = new char[actual_name_size](); name_size = H5Fget_name(temp_id, name_C, actual_name_size); // Check for failure again if (name_size < 0) { delete[] name_C; throw IdComponentException("", "H5Fget_name failed"); } // Convert the C file name and return H5std_string file_name(name_C); delete[] name_C; return file_name; } // // Local functions used in this class // //-------------------------------------------------------------------------- // Function: p_valid_id // Purpose Verifies that the given id is a valid id so it can be passed // into an H5I C function. // Return true if id is valid, false, otherwise //-------------------------------------------------------------------------- bool IdComponent::p_valid_id(const hid_t obj_id) { if (obj_id <= 0) return false; H5I_type_t id_type = H5Iget_type(obj_id); return (id_type > H5I_BADID && id_type < H5I_NTYPES); } // Notes about IdComponent::id // May 2008 - BMR // Class hierarchy is revised to address bugzilla 1068... // ...member IdComponent::id is moved into subclasses, and // IdComponent::getId now becomes pure virtual function. // (reasons: 1. encountered problems when adding H5Location; // 2. Scott Meyers, item 33) #endif // DOXYGEN_SHOULD_SKIP_THIS } // namespace H5