summaryrefslogtreecommitdiff
path: root/c++/src/H5Attribute.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'c++/src/H5Attribute.cpp')
-rw-r--r--c++/src/H5Attribute.cpp640
1 files changed, 640 insertions, 0 deletions
diff --git a/c++/src/H5Attribute.cpp b/c++/src/H5Attribute.cpp
new file mode 100644
index 0000000..cbf3029
--- /dev/null
+++ b/c++/src/H5Attribute.cpp
@@ -0,0 +1,640 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * Copyright by The HDF Group. *
+ * Copyright by the Board of Trustees of the University of Illinois. *
+ * 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://support.hdfgroup.org/ftp/HDF5/releases. *
+ * If you do not have access to either file, you may request a copy from *
+ * help@hdfgroup.org. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#ifdef OLD_HEADER_FILENAME
+#include <iostream.h>
+#else
+#include <iostream>
+#endif
+#include <string>
+
+#include "H5private.h" // for HDfree
+#include "H5Include.h"
+#include "H5Exception.h"
+#include "H5IdComponent.h"
+#include "H5PropList.h"
+#include "H5FaccProp.h"
+#include "H5FcreatProp.h"
+#include "H5OcreatProp.h"
+#include "H5DcreatProp.h"
+#include "H5LaccProp.h"
+#include "H5Location.h"
+#include "H5Object.h"
+#include "H5AbstractDs.h"
+#include "H5DataType.h"
+#include "H5DataSpace.h"
+#include "H5Attribute.h"
+
+namespace H5 {
+using std::cerr;
+using std::endl;
+
+class H5_DLLCPP H5Object; // forward declaration for UserData4Aiterate
+
+//--------------------------------------------------------------------------
+// Function: Attribute default constructor
+///\brief Default constructor: Creates a stub attribute
+// Programmer Binh-Minh Ribler - May, 2004
+//--------------------------------------------------------------------------
+Attribute::Attribute() : AbstractDs(), H5Location(), id(H5I_INVALID_HID) {}
+
+//--------------------------------------------------------------------------
+// Function: Attribute copy constructor
+///\brief Copy constructor: makes a copy of the original Attribute object.
+///\param original - IN: Original Attribute object to copy
+// Programmer Binh-Minh Ribler - 2000
+//--------------------------------------------------------------------------
+Attribute::Attribute(const Attribute& original) : AbstractDs(), H5Location(), id(original.id)
+{
+ incRefCount(); // increment number of references to this id
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute overloaded constructor
+///\brief Creates an Attribute object using the id of an existing
+/// attribute.
+///\param existing_id - IN: Id of an existing attribute
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - 2000
+//--------------------------------------------------------------------------
+Attribute::Attribute(const hid_t existing_id) : AbstractDs(), H5Location(), id(existing_id)
+{
+ incRefCount(); // increment number of references to this id
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::write
+///\brief Writes data to this attribute.
+///\param mem_type - IN: Attribute datatype (in memory)
+///\param buf - IN: Data to be written
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - 2000
+//--------------------------------------------------------------------------
+void Attribute::write(const DataType& mem_type, const void *buf) const
+{
+ herr_t ret_value = H5Awrite(id, mem_type.getId(), buf);
+ if (ret_value < 0)
+ {
+ throw AttributeIException("Attribute::write", "H5Awrite failed");
+ }
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::write
+///\brief This is an overloaded member function, provided for convenience.
+/// It writes a \a H5std_string to this attribute.
+///\param mem_type - IN: Attribute datatype (in memory)
+///\param strg - IN: Data to be written
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - Apr, 2003
+//--------------------------------------------------------------------------
+void Attribute::write(const DataType& mem_type, const H5std_string& strg) const
+{
+ // Check if this attribute has variable-len string or fixed-len string and
+ // proceed appropriately.
+ htri_t is_variable_len = H5Tis_variable_str(mem_type.getId());
+ if (is_variable_len < 0)
+ {
+ throw AttributeIException("Attribute::write", "H5Tis_variable_str failed");
+ }
+ // Convert string to C-string
+ const char* strg_C;
+ strg_C = strg.c_str(); // strg_C refers to the contents of strg as a C-str
+ herr_t ret_value = 0;
+
+ // Pass string in differently depends on variable or fixed length
+ if (!is_variable_len)
+ {
+ ret_value = H5Awrite(id, mem_type.getId(), strg_C);
+ }
+ else
+ {
+ // passing third argument by address
+ ret_value = H5Awrite(id, mem_type.getId(), &strg_C);
+ }
+ if (ret_value < 0)
+ {
+ throw AttributeIException("Attribute::write", "H5Awrite failed");
+ }
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::read
+///\brief Reads data from this attribute.
+///\param mem_type - IN: Attribute datatype (in memory)
+///\param buf - OUT: Buffer for read data
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - 2000
+//--------------------------------------------------------------------------
+void Attribute::read(const DataType& mem_type, void *buf) const
+{
+ herr_t ret_value = H5Aread(id, mem_type.getId(), buf);
+ if (ret_value < 0)
+ {
+ throw AttributeIException("Attribute::read", "H5Aread failed");
+ }
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::read
+///\brief This is an overloaded member function, provided for convenience.
+/// It reads a \a H5std_string from this attribute.
+///\param mem_type - IN: Attribute datatype (in memory)
+///\param strg - IN: Buffer for read string
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - Apr, 2003
+// Modification
+// Mar 2008
+// Corrected a misunderstanding that H5Aread would allocate
+// space for the buffer. Obtained the attribute size and
+// allocated memory properly. -BMR
+// Apr 2009
+// Used getInMemDataSize to get attribute data size. -BMR
+// Jul 2009
+// Divided into specific private functions for fixed- and
+// variable-len string data: p_read_fixed_len and
+// p_read_variable_len. This should improve readability. -BMR
+//--------------------------------------------------------------------------
+void Attribute::read(const DataType& mem_type, H5std_string& strg) const
+{
+ // Check if this attribute has variable-len string or fixed-len string and
+ // proceed appropriately.
+ htri_t is_variable_len = H5Tis_variable_str(mem_type.getId());
+ if (is_variable_len < 0)
+ {
+ throw AttributeIException("Attribute::read", "H5Tis_variable_str failed");
+ }
+
+ if (!is_variable_len) // only allocate for fixed-len string
+ {
+ p_read_fixed_len(mem_type, strg);
+ }
+ else
+ {
+ p_read_variable_len(mem_type, strg);
+ }
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::getInMemDataSize
+///\brief Gets the size in memory of the attribute's data.
+///\return Size of data (in memory)
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - Apr 2009
+//--------------------------------------------------------------------------
+size_t Attribute::getInMemDataSize() const
+{
+ const char *func = "Attribute::getInMemDataSize";
+
+ // Get the data type of this attribute
+ hid_t mem_type_id = H5Aget_type(id);
+ if (mem_type_id < 0)
+ {
+ throw AttributeIException(func, "H5Aget_type failed");
+ }
+
+ // Get the data type's size by first getting its native type then getting
+ // the native type's size.
+ hid_t native_type = H5Tget_native_type(mem_type_id, H5T_DIR_DEFAULT);
+ if (native_type < 0)
+ {
+ throw AttributeIException(func, "H5Tget_native_type failed");
+ }
+ size_t type_size = H5Tget_size(native_type);
+ if (type_size == 0)
+ {
+ throw AttributeIException(func, "H5Tget_size failed");
+ }
+
+ // Close the native type and the datatype of this attribute.
+ if (H5Tclose(native_type) < 0)
+ {
+ throw DataSetIException(func, "H5Tclose(native_type) failed");
+ }
+ if (H5Tclose(mem_type_id) < 0)
+ {
+ throw DataSetIException(func, "H5Tclose(mem_type_id) failed");
+ }
+
+ // Get number of elements of the attribute by first getting its dataspace
+ // then getting the number of elements in the dataspace
+ hid_t space_id = H5Aget_space(id);
+ if (space_id < 0)
+ {
+ throw AttributeIException(func, "H5Aget_space failed");
+ }
+ hssize_t num_elements = H5Sget_simple_extent_npoints(space_id);
+ if (num_elements < 0)
+ {
+ throw AttributeIException(func, "H5Sget_simple_extent_npoints failed");
+ }
+
+ // Close the dataspace
+ if (H5Sclose(space_id) < 0)
+ {
+ throw DataSetIException(func, "H5Sclose failed");
+ }
+
+ // Calculate and return the size of the data
+ size_t data_size = type_size * num_elements;
+ return(data_size);
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::getSpace
+///\brief Gets a copy of the dataspace for this attribute.
+///\return Dataspace instance
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - 2000
+//--------------------------------------------------------------------------
+DataSpace Attribute::getSpace() const
+{
+ // Calls C function H5Aget_space to get the id of the dataspace
+ hid_t dataspace_id = H5Aget_space(id);
+
+ // If the dataspace id is valid, create and return the DataSpace object
+ if (dataspace_id > 0)
+ {
+ DataSpace dataspace;
+ f_DataSpace_setId(&dataspace, dataspace_id);
+ return(dataspace);
+ }
+ else
+ {
+ throw AttributeIException("Attribute::getSpace", "H5Aget_space failed");
+ }
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::getName
+///\brief Gets the name of this attribute, returning its length.
+///\param attr_name - OUT: Buffer for the name string as char*
+///\param buf_size - IN: Length of the buffer, default to 0
+///\return Actual length of the attribute name
+///\exception H5::AttributeIException
+///\par Description
+/// This function retrieves \a buf_size chars of the attribute's
+/// name including null termination. Thus, if the actual length
+/// of the name is more than buf_size-1, the retrieved name will
+/// be truncated to accommodate the null terminator.
+/// To get length of the attribute's name for buffer allocation,
+/// an application can call this function passing in NULL for the
+/// first argument and ignore the second argument.
+// Programmer Binh-Minh Ribler - Mar, 2014
+//--------------------------------------------------------------------------
+ssize_t Attribute::getName(char* attr_name, size_t buf_size) const
+{
+ // H5Aget_name will get buf_size-1 chars of the name to null terminate it
+ ssize_t name_size = H5Aget_name(id, buf_size, attr_name);
+
+ // If H5Aget_name returns a negative value, raise an exception
+ if (name_size < 0)
+ {
+ throw AttributeIException("Attribute::getName", "H5Aget_name failed");
+ }
+ else if (name_size == 0)
+ {
+ throw AttributeIException("Attribute::getName", "Attribute must have a name, name length is 0");
+ }
+ // Return length of the name
+ return(name_size);
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::getName
+///\brief Returns the name of this attribute as an \a H5std_string.
+///\return Name of the attribute
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - May, 2004
+// Modification
+// Mar 2014 - BMR
+// Revised to use the modified getName() above
+//--------------------------------------------------------------------------
+H5std_string Attribute::getName() const
+{
+ H5std_string attr_name(""); // attribute name to return
+
+ // Preliminary call to get the size of the attribute name
+ ssize_t name_size = H5Aget_name(id, static_cast<size_t>(0), NULL);
+
+ // If H5Aget_name failed, throw exception
+ if (name_size < 0)
+ {
+ throw AttributeIException("Attribute::getName", "H5Aget_name failed");
+ }
+ else if (name_size == 0)
+ {
+ throw AttributeIException("Attribute::getName", "Attribute must have a name, name length is 0");
+ }
+ // Attribute's name exists, retrieve it
+ else if (name_size > 0)
+ {
+ char* name_C = new char[name_size+1]; // temporary C-string
+ HDmemset(name_C, 0, name_size+1); // clear buffer
+
+ // Use overloaded function
+ name_size = getName(name_C, name_size+1);
+
+ // Convert the C attribute name to return
+ attr_name = name_C;
+
+ // Clean up resource
+ delete []name_C;
+
+ }
+ // Return attribute's name
+ return(attr_name);
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::getName
+///\brief This is an overloaded member function, provided for convenience.
+/// It differs from the above function in that it takes an integer
+/// specifying a desired length to be retrieved of the name.
+///\return Name (or part of name) of the attribute
+///\param len - IN: Desired length of the name
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - 2000
+// Modification
+// Mar 2014 - BMR
+// Revised to use the new getName() below
+//--------------------------------------------------------------------------
+H5std_string Attribute::getName(size_t len) const
+{
+ H5std_string attr_name;
+ ssize_t name_size = getName(attr_name, len);
+ if (name_size < 0)
+ return("");
+ else
+ return(attr_name);
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::getName
+///\brief Gets the name of this attribute, returning its length.
+///\param attr_name - OUT: Buffer for the name string as \a H5std_string
+///\param len - IN: Desired length of the name, default to 0
+///\return Actual length of the attribute name
+///\exception H5::AttributeIException
+///\par Description
+/// This function retrieves the attribute's name as a string. The
+/// buf_size can specify a specific length or default to 0, in
+/// which case the entire name will be retrieved.
+// Programmer Binh-Minh Ribler - Nov, 2001
+// Modification
+// Mar 2014 - BMR
+// Added to replace getName(size_t, H5std_string&) so that it'll
+// allow the argument "len" to be skipped.
+//--------------------------------------------------------------------------
+ssize_t Attribute::getName(H5std_string& attr_name, size_t len) const
+{
+ ssize_t name_size = 0;
+
+ // If no length is provided, get the entire attribute name
+ if (len == 0)
+ {
+ attr_name = getName();
+ name_size = attr_name.length();
+ }
+ // If length is provided, get that number of characters in name
+ else
+ {
+ char* name_C = new char[len+1]; // temporary C-string
+ HDmemset(name_C, 0, len+1); // clear buffer
+
+ // Use overloaded function
+ name_size = getName(name_C, len+1);
+
+ // Convert the C attribute name to return
+ attr_name = name_C;
+
+ // Clean up resource
+ delete []name_C;
+ }
+ // Otherwise, keep attr_name intact
+
+ // Return name size
+ return(name_size);
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::getName
+// Purpose This function is replaced by the previous function, which
+// provides more convenient prototype. It will be removed
+// in future release.
+// Param len - IN: Desired length of the name
+// Param attr_name - OUT: Buffer for the name string
+// Return Actual length of the attribute name
+// Exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - Nov, 2001
+// 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
+//--------------------------------------------------------------------------
+//ssize_t Attribute::getName(size_t len, H5std_string& attr_name) const
+//{
+// return (getName(attr_name, len));
+//}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::getStorageSize
+///\brief Returns the amount of storage size required for this attribute.
+///\return Size of the storage or 0, for no data
+///\exception H5::AttributeIException
+// Note: H5Dget_storage_size returns 0 when there is no data. This
+// function should have no failure. (from SLU)
+// Programmer Binh-Minh Ribler - Mar, 2005
+//--------------------------------------------------------------------------
+hsize_t Attribute::getStorageSize() const
+{
+ hsize_t storage_size = H5Aget_storage_size(id);
+ return (storage_size);
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::getId
+///\brief Get the id of this attribute
+///\return Attribute identifier
+// Description:
+// 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.
+// Programmer Binh-Minh Ribler - May, 2008
+// Modification
+// Aug 2016 - BMR
+// Note that Attribute is now inheriting from H5Location, because
+// an attribute id can be used to specify a location in HDF5
+// library.
+//--------------------------------------------------------------------------
+hid_t Attribute::getId() const
+{
+ return(id);
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::p_get_type (private)
+// Purpose Gets the datatype of this attribute.
+// Return Id of the datatype
+// Exception H5::AttributeIException
+// Description
+// This private function is used in AbstractDs.
+// Programmer Binh-Minh Ribler - 2000
+//--------------------------------------------------------------------------
+hid_t Attribute::p_get_type() const
+{
+ hid_t type_id = H5Aget_type(id);
+ if (type_id > 0)
+ return(type_id);
+ else
+ {
+ throw AttributeIException("", "H5Aget_type failed");
+ }
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::p_read_fixed_len (private)
+// brief Reads a fixed length \a H5std_string from an attribute.
+// param mem_type - IN: Attribute datatype (in memory)
+// param strg - IN: Buffer for read string
+// exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - Jul, 2009
+// Modification
+// Jul 2009
+// Separated the fixed length case from the original
+// Attribute::read
+//--------------------------------------------------------------------------
+void Attribute::p_read_fixed_len(const DataType& mem_type, H5std_string& strg) const
+{
+ // Only allocate for fixed-len string.
+
+ // Get the size of the attribute's data
+ size_t attr_size = getInMemDataSize();
+
+ // If there is data, allocate buffer and read it.
+ if (attr_size > 0)
+ {
+ char *strg_C = new char[attr_size+1];
+ herr_t ret_value = H5Aread(id, mem_type.getId(), strg_C);
+ if (ret_value < 0)
+ {
+ delete []strg_C; // de-allocate for fixed-len string
+ throw AttributeIException("Attribute::read", "H5Aread failed");
+ }
+ // Get string from the C char* and release resource allocated locally
+ strg_C[attr_size] = '\0';
+ strg = strg_C;
+ delete []strg_C;
+ }
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute::p_read_variable_len (private)
+// brief Reads a variable length \a H5std_string from an attribute.
+// param mem_type - IN: Attribute datatype (in memory)
+// param strg - IN: Buffer for read string
+// exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - Jul, 2009
+// Modification
+// Jul 2009
+// Separated the variable length case from the original
+// Attribute::read. -BMR
+//--------------------------------------------------------------------------
+void Attribute::p_read_variable_len(const DataType& mem_type, H5std_string& strg) const
+{
+ // Prepare and call C API to read attribute.
+ char *strg_C;
+
+ // Read attribute, no allocation for variable-len string; C library will
+ herr_t ret_value = H5Aread(id, mem_type.getId(), &strg_C);
+
+ if (ret_value < 0)
+ {
+ throw AttributeIException("Attribute::read", "H5Aread failed");
+ }
+
+ // Get string from the C char* and release resource allocated by C API
+ strg = strg_C;
+ HDfree(strg_C);
+}
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+//--------------------------------------------------------------------------
+// Function: Attribute::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 underlaying 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.
+// Programmer Binh-Minh Ribler - 2000
+//--------------------------------------------------------------------------
+void Attribute::p_setId(const hid_t new_id)
+{
+ // handling references to this old id
+ try {
+ close();
+ }
+ catch (Exception& close_error) {
+ throw AttributeIException("Attribute::p_setId", close_error.getDetailMsg());
+ }
+ // reset object's id to the given id
+ id = new_id;
+}
+#endif // DOXYGEN_SHOULD_SKIP_THIS
+
+//--------------------------------------------------------------------------
+// Function: Attribute::close
+///\brief Closes this attribute.
+///
+///\exception H5::AttributeIException
+// Programmer Binh-Minh Ribler - Mar 9, 2005
+//--------------------------------------------------------------------------
+void Attribute::close()
+{
+ if (p_valid_id(id))
+ {
+ herr_t ret_value = H5Aclose(id);
+ if (ret_value < 0)
+ {
+ throw AttributeIException("Attribute::close", "H5Aclose failed");
+ }
+ // reset the id
+ id = H5I_INVALID_HID;
+ }
+}
+
+//--------------------------------------------------------------------------
+// Function: Attribute destructor
+///\brief Properly terminates access to this attribute.
+// Programmer Binh-Minh Ribler - 2000
+// 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
+//--------------------------------------------------------------------------
+Attribute::~Attribute()
+{
+ try {
+ close();
+ }
+ catch (Exception& close_error) {
+ cerr << "Attribute::~Attribute - " << close_error.getDetailMsg() << endl;
+ }
+}
+
+} // end namespace