/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 #include "H5Include.h" #include "H5Exception.h" #include "H5IdComponent.h" #include "H5DataSpace.h" namespace H5 { using std::cerr; using std::endl; #ifndef DOXYGEN_SHOULD_SKIP_THIS // This DOXYGEN_SHOULD_SKIP_THIS block is a work-around approach to control // the order of creation and deletion of the global constants. See Design Notes // in "H5PredType.cpp" for information. // Initialize a pointer for the constant DataSpace *DataSpace::ALL_ = 0; //-------------------------------------------------------------------------- // Function: DataSpace::getConstant // Creates a DataSpace object representing the HDF5 constant // H5S_ALL, pointed to by DataSpace::ALL_ // Exception H5::DataSpaceIException // Description // If DataSpace::ALL_ already points to an allocated object, throw // a DataSpaceIException. This scenario should not happen. //-------------------------------------------------------------------------- DataSpace * DataSpace::getConstant() { // Tell the C library not to clean up, H5Library::termH5cpp will call // H5close - more dependency if use H5Library::dontAtExit() if (!IdComponent::H5dontAtexit_called) { (void)H5dont_atexit(); IdComponent::H5dontAtexit_called = true; } // If the constant pointer is not allocated, allocate it. Otherwise, // throw because it shouldn't be. if (ALL_ == 0) ALL_ = new DataSpace(H5S_ALL); else throw DataSpaceIException("DataSpace::getConstant", "DataSpace::getConstant is being invoked on an allocated ALL_"); return (ALL_); } //-------------------------------------------------------------------------- // Function: DataSpace::deleteConstants // Purpose: Deletes the constant object that DataSpace::ALL_ points to //-------------------------------------------------------------------------- void DataSpace::deleteConstants() { delete ALL_; } //-------------------------------------------------------------------------- // Purpose Constant for default dataspace. //-------------------------------------------------------------------------- const DataSpace &DataSpace::ALL = *getConstant(); #endif // DOXYGEN_SHOULD_SKIP_THIS //-------------------------------------------------------------------------- // Function: DataSpace constructor ///\brief Creates a new dataspace given a dataspace type. ///\param type - IN: Type of the dataspace to be created, which /// currently can be either \c H5S_SCALAR or \c H5S_SIMPLE; /// default to \c H5S_SCALAR. ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- DataSpace::DataSpace(H5S_class_t type) : IdComponent(), id{H5Screate(type)} { if (id < 0) { throw DataSpaceIException("DataSpace constructor", "H5Screate failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace overloaded constructor ///\brief Creates a new simple dataspace. ///\param rank - IN: Number of dimensions of dataspace. ///\param dims - IN: An array of the size of each dimension. ///\param maxdims - IN: An array of the maximum size of each dimension. ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- DataSpace::DataSpace(int rank, const hsize_t *dims, const hsize_t *maxdims) : IdComponent(), id{H5Screate_simple(rank, dims, maxdims)} { if (id < 0) { throw DataSpaceIException("DataSpace constructor", "H5Screate_simple failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace overloaded constructor ///\brief Creates a DataSpace object using the id of an existing /// dataspace. ///\param existing_id - IN: Id of an existing dataspace ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- DataSpace::DataSpace(const hid_t existing_id) : IdComponent(), id(existing_id) { incRefCount(); // increment number of references to this id } //-------------------------------------------------------------------------- // Function: DataSpace copy constructor ///\brief Copy constructor: same HDF5 object as \a original ///\param original - IN: DataSpace object to copy //-------------------------------------------------------------------------- DataSpace::DataSpace(const DataSpace &original) : IdComponent(), id(original.id) { incRefCount(); // increment number of references to this id } //-------------------------------------------------------------------------- // Function: DataSpace::copy ///\brief Makes a copy of an existing dataspace. ///\param like_space - IN: Dataspace to be copied ///\exception H5::DataSpaceIException // Modification // - Replaced resetIdComponent() with decRefCount() to use C // library ID reference counting mechanism - BMR, Jun 1, 2004 // - Replaced decRefCount with close() to let the C library // handle the reference counting - BMR, Jun 1, 2006 //-------------------------------------------------------------------------- void DataSpace::copy(const DataSpace &like_space) { // If this object has an hdf5 valid id, close it if (id != H5S_ALL) { try { close(); } catch (Exception &close_error) { throw DataSpaceIException("DataSpace::copy", close_error.getDetailMsg()); } } // end if // call C routine to copy the dataspace id = H5Scopy(like_space.getId()); if (id < 0) throw DataSpaceIException("DataSpace::copy", "H5Scopy failed"); } //-------------------------------------------------------------------------- // Function: DataSpace::operator= ///\brief Assignment operator. ///\param rhs - IN: Reference to the existing dataspace ///\return Reference to DataSpace instance ///\exception H5::DataSpaceIException // Description // Makes a copy of the type on the right hand side and stores // the new id in the left hand side object. //-------------------------------------------------------------------------- DataSpace & DataSpace::operator=(const DataSpace &rhs) { if (this != &rhs) copy(rhs); return (*this); } //-------------------------------------------------------------------------- // Function: DataSpace::isSimple ///\brief Determines whether this dataspace is a simple dataspace. ///\return \c true if the dataspace is a simple dataspace, and \c false, /// otherwise ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- bool DataSpace::isSimple() const { htri_t simple = H5Sis_simple(id); if (simple > 0) return true; else if (simple == 0) return false; else { throw DataSpaceIException("DataSpace::isSimple", "H5Sis_simple returns negative value"); } } //-------------------------------------------------------------------------- // Function: DataSpace::offsetSimple ///\brief Sets the offset of this simple dataspace. ///\param offset - IN: Offset to position the selection at ///\exception H5::DataSpaceIException ///\par Description /// This function creates an offset for the selection within /// an extent, allowing the same shaped selection to be moved /// to different locations within a dataspace without requiring /// it to be re-defined. //-------------------------------------------------------------------------- void DataSpace::offsetSimple(const hssize_t *offset) const { herr_t ret_value = H5Soffset_simple(id, offset); if (ret_value < 0) { throw DataSpaceIException("DataSpace::offsetSimple", "H5Soffset_simple failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::getSimpleExtentDims ///\brief Retrieves dataspace dimension size and maximum size. ///\param dims - IN: Name of the new member ///\param maxdims - IN: Pointer to the value of the new member ///\return Number of dimensions, the same value as returned by /// \c DataSpace::getSimpleExtentNdims() ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- int DataSpace::getSimpleExtentDims(hsize_t *dims, hsize_t *maxdims) const { int ndims = H5Sget_simple_extent_dims(id, dims, maxdims); if (ndims < 0) { throw DataSpaceIException("DataSpace::getSimpleExtentDims", "H5Sget_simple_extent_dims returns negative number of dimensions"); } return (ndims); } //-------------------------------------------------------------------------- // Function: DataSpace::getSimpleExtentNdims ///\brief Returns the dimensionality of a dataspace. ///\return Number of dimensions ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- int DataSpace::getSimpleExtentNdims() const { int ndims = H5Sget_simple_extent_ndims(id); if (ndims < 0) { throw DataSpaceIException( "DataSpace::getSimpleExtentNdims", "H5Sget_simple_extent_ndims returns negative value for dimensionality of the dataspace"); } return (ndims); } //-------------------------------------------------------------------------- // Function: DataSpace::getSimpleExtentNpoints ///\brief Returns the number of elements in a dataspace. ///\return Number of elements ///\exception H5::DataSpaceIException // Modification // 12/05/00: due to C API change // return type hssize_t vs. hsize_t // num_elements = -1 when failure occurs vs. 0 //-------------------------------------------------------------------------- hssize_t DataSpace::getSimpleExtentNpoints() const { hssize_t num_elements = H5Sget_simple_extent_npoints(id); if (num_elements > -1) return (num_elements); else { throw DataSpaceIException("DataSpace::getSimpleExtentNpoints", "H5Sget_simple_extent_npoints returns negative value for the number of " "elements in the dataspace"); } } //-------------------------------------------------------------------------- // Function: DataSpace::getSimpleExtentType ///\brief Returns the current class of a dataspace. ///\return Class of the dataspace ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- H5S_class_t DataSpace::getSimpleExtentType() const { H5S_class_t class_name = H5Sget_simple_extent_type(id); if (class_name == H5S_NO_CLASS) { throw DataSpaceIException("DataSpace::getSimpleExtentType", "H5Sget_simple_extent_type returns H5S_NO_CLASS"); } return (class_name); } //-------------------------------------------------------------------------- // Function: DataSpace::extentCopy ///\brief Copies the extent of a dataspace. ///\param dest_space - IN: Dataspace to copy from ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- void DataSpace::extentCopy(const DataSpace &dest_space) const { hid_t dest_space_id = dest_space.getId(); herr_t ret_value = H5Sextent_copy(dest_space_id, id); if (ret_value < 0) { throw DataSpaceIException("DataSpace::extentCopy", "H5Sextent_copy failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::extentCopy // Purpose This is an overloaded member function, kept for backward // compatibility. It differs from the above function in that it // misses const. This wrapper will be removed in future release. // Param dest_space - IN: Dataspace to copy from // Exception H5::DataSpaceIException // Modification // Modified to call its replacement. -BMR, 2014/04/16 // Removed from documentation. -BMR, 2016/03/07 1.8.17 and 1.10.0 // Removed from code. -BMR, 2016/08/11 1.8.18 and 1.10.1 //-------------------------------------------------------------------------- // void DataSpace::extentCopy(DataSpace& dest_space) const //{ // extentCopy(dest_space); //} //-------------------------------------------------------------------------- // Function: DataSpace::setExtentSimple ///\brief Sets or resets the size of an existing dataspace. ///\param rank - IN: Rank of the dataspace ///\param current_size - IN: Array containing current size of dataspace ///\param maximum_size - IN: Array containing maximum size of dataspace ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- void DataSpace::setExtentSimple(int rank, const hsize_t *current_size, const hsize_t *maximum_size) const { herr_t ret_value; ret_value = H5Sset_extent_simple(id, rank, current_size, maximum_size); if (ret_value < 0) { throw DataSpaceIException("DataSpace::setExtentSimple", "H5Sset_extent_simple failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::setExtentNone ///\brief Removes the extent from a dataspace. /// ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- void DataSpace::setExtentNone() const { herr_t ret_value = H5Sset_extent_none(id); if (ret_value < 0) { throw DataSpaceIException("DataSpace::setExtentNone", "H5Sset_extent_none failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::getSelectNpoints ///\brief Returns the number of elements in a dataspace selection. ///\return Number of elements ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- hssize_t DataSpace::getSelectNpoints() const { hssize_t num_elements = H5Sget_select_npoints(id); if (num_elements < 0) { throw DataSpaceIException( "DataSpace::getSelectNpoints", "H5Sget_select_npoints returns negative value for number of elements in the dataspace selection"); } return (num_elements); } //-------------------------------------------------------------------------- // Function: DataSpace::getSelectHyperNblocks ///\brief Returns number of hyperslab blocks. ///\return Number of hyperslab blocks ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- hssize_t DataSpace::getSelectHyperNblocks() const { hssize_t num_blocks = H5Sget_select_hyper_nblocks(id); if (num_blocks < 0) { throw DataSpaceIException( "DataSpace::getSelectHyperNblocks", "H5Sget_select_hyper_nblocks returns negative value for the number of hyperslab blocks"); } return (num_blocks); } //-------------------------------------------------------------------------- // Function: DataSpace::getSelectHyperBlocklist ///\brief Gets the list of hyperslab blocks currently selected ///\param startblock - IN: Hyperslab block to start with ///\param numblocks - IN: Number of hyperslab blocks to get ///\param buf - IN: List of hyperslab blocks selected ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- void DataSpace::getSelectHyperBlocklist(hsize_t startblock, hsize_t numblocks, hsize_t *buf) const { herr_t ret_value; ret_value = H5Sget_select_hyper_blocklist(id, startblock, numblocks, buf); if (ret_value < 0) { throw DataSpaceIException("DataSpace::getSelectHyperBlocklist", "H5Sget_select_hyper_blocklist failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::getSelectElemNpoints ///\brief Returns the number of element points in the current selection. ///\return Number of element points ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- hssize_t DataSpace::getSelectElemNpoints() const { hssize_t num_points = H5Sget_select_elem_npoints(id); if (num_points < 0) { throw DataSpaceIException("DataSpace::getSelectElemNpoints", "H5Sget_select_elem_npoints failed"); } return (num_points); } //-------------------------------------------------------------------------- // Function: DataSpace::getSelectElemPointlist ///\brief Gets the list of element points currently selected ///\param startpoint - IN: Element point to start with ///\param numpoints - IN: Number of element points to get ///\param buf - IN: List of element points selected ///\exception H5::DataSpaceIException ///\par Description /// For information, please refer to the C API /// H5Sget_select_elem_pointlist in the HDF5 C Reference Manual. //-------------------------------------------------------------------------- void DataSpace::getSelectElemPointlist(hsize_t startpoint, hsize_t numpoints, hsize_t *buf) const { herr_t ret_value; ret_value = H5Sget_select_elem_pointlist(id, startpoint, numpoints, buf); if (ret_value < 0) { throw DataSpaceIException("DataSpace::getSelectElemPointlist", "H5Sget_select_elem_pointlist failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::getSelectBounds ///\brief Gets the bounding box containing the current selection. ///\param start - IN: Starting coordinates of the bounding box ///\param end - IN: Ending coordinates of the bounding box, i.e., /// the coordinates of the diagonally opposite corner ///\exception H5::DataSpaceIException ///\par Description /// For information, please refer to the H5Sget_select_bounds API in /// the HDF5 C Reference Manual. //-------------------------------------------------------------------------- void DataSpace::getSelectBounds(hsize_t *start, hsize_t *end) const { herr_t ret_value = H5Sget_select_bounds(id, start, end); if (ret_value < 0) { throw DataSpaceIException("DataSpace::getSelectBounds", "H5Sget_select_bounds failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::selectElements ///\brief Selects array elements to be included in the selection for /// this dataspace. ///\param op - IN: Operator specifying how the new selection is to be /// combined with the existing selection for the dataspace ///\param num_elements - IN: Number of elements to be selected ///\param coord - IN: A 2-dimensional array of 0-based values /// specifying the coordinates of the elements being selected ///\exception H5::DataSpaceIException ///\par Description /// For information, please refer to the H5Sselect_elements API in /// the HDF5 C Reference Manual. //-------------------------------------------------------------------------- void DataSpace::selectElements(H5S_seloper_t op, const size_t num_elements, const hsize_t *coord) const { herr_t ret_value; ret_value = H5Sselect_elements(id, op, num_elements, coord); if (ret_value < 0) { throw DataSpaceIException("DataSpace::selectElements", "H5Sselect_elements failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::selectAll ///\brief Selects the entire dataspace. /// ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- void DataSpace::selectAll() const { herr_t ret_value = H5Sselect_all(id); if (ret_value < 0) { throw DataSpaceIException("DataSpace::selectAll", "H5Sselect_all failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::selectNone ///\brief Resets the selection region to include no elements. /// ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- void DataSpace::selectNone() const { herr_t ret_value = H5Sselect_none(id); if (ret_value < 0) { throw DataSpaceIException("DataSpace::selectNone", "H5Sselect_none failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::selectValid ///\brief Verifies that the selection is within the extent of the /// dataspace. ///\return \c true if the selection is within the extent of the /// dataspace, and \c false, otherwise ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- bool DataSpace::selectValid() const { htri_t ret_value = H5Sselect_valid(id); if (ret_value > 0) return true; else if (ret_value == 0) return false; else { throw DataSpaceIException("DataSpace::selectValid", "H5Sselect_valid returns negative value"); } } //-------------------------------------------------------------------------- // Function: DataSpace::selectHyperslab ///\brief Selects a hyperslab region to add to the current selected region. ///\param op - IN: Operation to perform on current selection ///\param count - IN: Number of blocks included in the hyperslab ///\param start - IN: Offset of the start of hyperslab ///\param stride - IN: Hyperslab stride - default to \c NULL ///\param block - IN: Size of block in the hyperslab - default to \c NULL ///\exception H5::DataSpaceIException ///\par Description /// For information, please refer to the H5Sselect_hyperslab API in /// the HDF5 C Reference Manual. //-------------------------------------------------------------------------- void DataSpace::selectHyperslab(H5S_seloper_t op, const hsize_t *count, const hsize_t *start, const hsize_t *stride, const hsize_t *block) const { herr_t ret_value; ret_value = H5Sselect_hyperslab(id, op, start, stride, count, block); if (ret_value < 0) { throw DataSpaceIException("DataSpace::selectHyperslab", "H5Sselect_hyperslab failed"); } } //-------------------------------------------------------------------------- // Function: DataSpace::getId ///\brief Get the id of this dataspace ///\return Dataspace identifier // Modification: // May 2008 - BMR // Class hierarchy is revised to address bugzilla 1068. Class // AbstractDS and Attribute are moved out of H5Object. In // addition, member IdComponent::id is moved into subclasses, and // IdComponent::getId now becomes pure virtual function. //-------------------------------------------------------------------------- hid_t DataSpace::getId() const { return (id); } #ifndef DOXYGEN_SHOULD_SKIP_THIS //-------------------------------------------------------------------------- // Function: DataSpace::p_setId ///\brief Sets the identifier of this object to a new value. /// ///\exception H5::IdComponentException when the attempt to close the HDF5 /// object fails // Description: // The underlying reference counting in the C library ensures // that the current valid id of this object is properly closed. // Then the object's id is reset to the new id. //-------------------------------------------------------------------------- void DataSpace::p_setId(const hid_t new_id) { // handling references to this old id try { close(); } catch (Exception &close_error) { throw DataSpaceIException(inMemFunc("p_setId"), close_error.getDetailMsg()); } // reset object's id to the given id id = new_id; } #endif // DOXYGEN_SHOULD_SKIP_THIS //-------------------------------------------------------------------------- // Function: DataSpace::close ///\brief Closes this dataspace. /// ///\exception H5::DataSpaceIException //-------------------------------------------------------------------------- void DataSpace::close() { // check if id is a valid hdf5 object id before trying to close it if (p_valid_id(id)) { herr_t ret_value = H5Sclose(id); if (ret_value < 0) { throw DataSpaceIException("DataSpace::close", "H5Sclose failed"); } // reset the id id = H5I_INVALID_HID; } } //-------------------------------------------------------------------------- // Function: DataSpace destructor ///\brief Properly terminates access to this dataspace. // Modification // - Replaced resetIdComponent() with decRefCount() to use C // library ID reference counting mechanism - BMR, Jun 1, 2004 // - Replaced decRefCount with close() to let the C library // handle the reference counting - BMR, Jun 1, 2006 //-------------------------------------------------------------------------- DataSpace::~DataSpace() { try { close(); } catch (Exception &close_error) { cerr << "DataSpace::~DataSpace - " << close_error.getDetailMsg() << endl; } } } // namespace H5