From 60df159d33d8793dd5764e2ae032e0e89fc44c9b Mon Sep 17 00:00:00 2001 From: Binh-Minh Ribler Date: Fri, 21 Mar 2014 18:23:05 -0500 Subject: [svn-r24865] Description: - Added another overload for char* argument: ssize_t getComment(const char* name, const size_t buf_size, char* comment) - Changed default value to 0 for the other two getComment methods - Added HDmemset to after every char string allocation to clear the buffer Platforms tested: Linux/ppc64 (ostrich) Linux/32 2.6 (jam) Linux/64 2.6 (platypus)/PGI compilers --- c++/src/H5CommonFG.cpp | 9 +++- c++/src/H5DataSet.cpp | 10 ++-- c++/src/H5EnumType.cpp | 4 +- c++/src/H5Exception.cpp | 23 ++++++++ c++/src/H5Exception.h | 7 +++ c++/src/H5IdComponent.cpp | 3 ++ c++/src/H5Location.cpp | 134 +++++++++++++++++++++++++++++----------------- c++/src/H5Location.h | 5 +- c++/src/H5PropList.cpp | 5 ++ c++/test/dsets.cpp | 11 ++++ c++/test/trefer.cpp | 6 ++- 11 files changed, 156 insertions(+), 61 deletions(-) diff --git a/c++/src/H5CommonFG.cpp b/c++/src/H5CommonFG.cpp index 3bf4b4f..fc8b08d 100644 --- a/c++/src/H5CommonFG.cpp +++ b/c++/src/H5CommonFG.cpp @@ -436,6 +436,7 @@ H5std_string CommonFG::getLinkval( const char* name, size_t size ) const if (val_size > 0) { value_C = new char[val_size+1]; // temporary C-string for C API + HDmemset(value_C, 0, val_size+1); // clear buffer ret_value = H5Lget_val(getLocId(), name, value_C, val_size, H5P_DEFAULT); if( ret_value < 0 ) @@ -881,6 +882,8 @@ H5std_string CommonFG::getObjnameByIdx(hsize_t idx) const // now, allocate C buffer to get the name char* name_C = new char[name_len+1]; + HDmemset(name_C, 0, name_len+1); // clear buffer + name_len = H5Lget_name_by_idx(getLocId(), ".", H5_INDEX_NAME, H5_ITER_INC, idx, name_C, name_len+1, H5P_DEFAULT); // clean up and return the string @@ -924,8 +927,10 @@ ssize_t CommonFG::getObjnameByIdx(hsize_t idx, char* name, size_t size) const //-------------------------------------------------------------------------- ssize_t CommonFG::getObjnameByIdx(hsize_t idx, H5std_string& name, size_t size) const { - char* name_C = new char[size]; - ssize_t name_len = getObjnameByIdx(idx, name_C, size); + char* name_C = new char[size+1]; // temporary C-string for object name + HDmemset(name_C, 0, size+1); // clear buffer + + ssize_t name_len = getObjnameByIdx(idx, name_C, size+1); if(name_len < 0) throwException("getObjnameByIdx", "H5Lget_name_by_idx failed"); diff --git a/c++/src/H5DataSet.cpp b/c++/src/H5DataSet.cpp index 0722ef9..699f982 100644 --- a/c++/src/H5DataSet.cpp +++ b/c++/src/H5DataSet.cpp @@ -629,7 +629,7 @@ hid_t DataSet::getId() const //-------------------------------------------------------------------------- // Function: DataSet::p_read_fixed_len (private) -// brief Reads a fixed length \a H5std_string from an dataset. +// brief Reads a fixed length \a H5std_string from a dataset. // param mem_type - IN: DataSet datatype (in memory) // param strg - IN: Buffer for read string // exception H5::DataSetIException @@ -643,14 +643,14 @@ void DataSet::p_read_fixed_len(const hid_t mem_type_id, const hid_t mem_space_id // Only allocate for fixed-len string. // Get the size of the dataset's data - size_t attr_size = getInMemDataSize(); + size_t data_size = getInMemDataSize(); // If there is data, allocate buffer and read it. - if (attr_size > 0) + if (data_size > 0) { - char *strg_C = NULL; + char *strg_C = new char [data_size+1]; + HDmemset(strg_C, 0, data_size+1); // clear buffer - strg_C = new char [(size_t)attr_size+1]; herr_t ret_value = H5Dread(id, mem_type_id, mem_space_id, file_space_id, xfer_plist_id, strg_C); if( ret_value < 0 ) diff --git a/c++/src/H5EnumType.cpp b/c++/src/H5EnumType.cpp index ff632af..04bb9e0 100644 --- a/c++/src/H5EnumType.cpp +++ b/c++/src/H5EnumType.cpp @@ -30,6 +30,7 @@ #include "H5AtomType.h" #include "H5IntType.h" #include "H5EnumType.h" +#include "H5private.h" // for HDmemset #ifndef H5_NO_NAMESPACE namespace H5 { @@ -150,6 +151,7 @@ void EnumType::insert( const H5std_string& name, void *value ) const H5std_string EnumType::nameOf( void *value, size_t size ) const { char* name_C = new char[size+1]; // temporary C-string for C API + HDmemset(name_C, 0, size+1); // clear buffer // Calls C routine H5Tenum_nameof to get the name of the specified enum type herr_t ret_value = H5Tenum_nameof( id, value, name_C, size ); @@ -160,7 +162,7 @@ H5std_string EnumType::nameOf( void *value, size_t size ) const throw DataTypeIException("EnumType::nameOf", "H5Tenum_nameof failed"); } // otherwise, create the string to hold the datatype name and return it - H5std_string name = H5std_string(name_C); + H5std_string name(name_C); delete []name_C; return( name ); } diff --git a/c++/src/H5Exception.cpp b/c++/src/H5Exception.cpp index ddc1d00..492abed 100644 --- a/c++/src/H5Exception.cpp +++ b/c++/src/H5Exception.cpp @@ -522,6 +522,29 @@ LibraryIException::LibraryIException(const H5std_string& func_name, const H5std_ LibraryIException::~LibraryIException() throw() {} //-------------------------------------------------------------------------- +// Subclass: LocationException +// Programmer Binh-Minh Ribler - 2014 +//-------------------------------------------------------------------------- +//-------------------------------------------------------------------------- +// Function: LocationException default constructor +///\brief Default constructor. +//-------------------------------------------------------------------------- +LocationException::LocationException():Exception(){} +//-------------------------------------------------------------------------- +// Function: LocationException overloaded constructor +///\brief Creates a LocationException with the name of the function, +/// in which the failure occurs, and an optional detailed message. +///\param func_name - IN: Name of the function where failure occurs +///\param message - IN: Message on the failure +//-------------------------------------------------------------------------- +LocationException::LocationException(const H5std_string& func_name, const H5std_string& message) : Exception(func_name, message) {} +//-------------------------------------------------------------------------- +// Function: LocationException destructor +///\brief Noop destructor. +//-------------------------------------------------------------------------- +LocationException::~LocationException() throw() {} + +//-------------------------------------------------------------------------- // Subclass: IdComponentException // Programmer Binh-Minh Ribler - 2000 //-------------------------------------------------------------------------- diff --git a/c++/src/H5Exception.h b/c++/src/H5Exception.h index d747af3..7d71022 100644 --- a/c++/src/H5Exception.h +++ b/c++/src/H5Exception.h @@ -155,6 +155,13 @@ class H5_DLLCPP LibraryIException : public Exception { virtual ~LibraryIException() throw(); }; +class H5_DLLCPP LocationException : public Exception { + public: + LocationException(const H5std_string& func_name, const H5std_string& message = DEFAULT_MSG); + LocationException(); + virtual ~LocationException() throw(); +}; + class H5_DLLCPP IdComponentException : public Exception { public: IdComponentException(const H5std_string& func_name, const H5std_string& message = DEFAULT_MSG); diff --git a/c++/src/H5IdComponent.cpp b/c++/src/H5IdComponent.cpp index c60d05c..cdf4272 100644 --- a/c++/src/H5IdComponent.cpp +++ b/c++/src/H5IdComponent.cpp @@ -25,6 +25,7 @@ #include "H5Library.h" #include "H5IdComponent.h" #include "H5DataSpace.h" +#include "H5private.h" // for HDmemset #ifndef H5_NO_NAMESPACE namespace H5 { @@ -289,6 +290,8 @@ H5std_string IdComponent::p_get_file_name() const // Call H5Fget_name again to get the actual file name char* name_C = new char[name_size+1]; // temporary C-string for C API + HDmemset(name_C, 0, name_size+1); // clear buffer + name_size = H5Fget_name(temp_id, name_C, name_size+1); // Check for failure again diff --git a/c++/src/H5Location.cpp b/c++/src/H5Location.cpp index b413a17..fdbfd61 100644 --- a/c++/src/H5Location.cpp +++ b/c++/src/H5Location.cpp @@ -32,6 +32,7 @@ #include "H5File.h" #include "H5DataSet.h" #include "H5Attribute.h" +#include "H5private.h" // for HDmemset #ifndef H5_NO_NAMESPACE namespace H5 { @@ -355,7 +356,7 @@ void H5Location::flush(H5F_scope_t scope) const herr_t ret_value = H5Fflush(getId(), scope); if( ret_value < 0 ) { - throw Exception(inMemFunc("flush"), "H5Fflush failed"); + throw LocationException(inMemFunc("flush"), "H5Fflush failed"); } } @@ -363,7 +364,7 @@ void H5Location::flush(H5F_scope_t scope) const // Function: H5Location::getFileName ///\brief Gets the name of the file, in which this HDF5 object belongs. ///\return File name -///\exception H5::IdComponentException +///\exception H5::LocationException // Programmer Binh-Minh Ribler - Jul, 2004 //-------------------------------------------------------------------------- H5std_string H5Location::getFileName() const @@ -371,7 +372,7 @@ H5std_string H5Location::getFileName() const try { return(p_get_file_name()); } - catch (IdComponentException E) { + catch (LocationException E) { throw FileIException(inMemFunc("getFileName"), E.getDetailMsg()); } } @@ -381,7 +382,7 @@ H5std_string H5Location::getFileName() const ///\brief Sets or resets the comment for an object specified by its name. ///\param name - IN: Name of the object ///\param comment - IN: New comment -///\exception H5::Exception +///\exception H5::LocationException ///\par Description /// If \a comment is an empty string or a null pointer, the comment /// message is removed from the object. @@ -400,7 +401,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 Exception(inMemFunc("setComment"), "H5Oset_comment_by_name failed"); + throw LocationException(inMemFunc("setComment"), "H5Oset_comment_by_name failed"); } //-------------------------------------------------------------------------- @@ -427,7 +428,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 Exception(inMemFunc("setComment"), "H5Oset_comment_by_name failed"); + throw LocationException(inMemFunc("setComment"), "H5Oset_comment_by_name failed"); } //-------------------------------------------------------------------------- @@ -446,7 +447,7 @@ void H5Location::setComment(const H5std_string& comment) const // Function: H5Location::removeComment ///\brief Removes the comment from an object specified by its name. ///\param name - IN: Name of the object -///\exception H5::Exception +///\exception H5::LocationException // Programmer Binh-Minh Ribler - May 2005 (moved from CommonFG, Sep 2013) // 2007: QAK modified to use H5O APIs; however the first parameter is // no longer just file or group, this function should be moved @@ -457,7 +458,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 Exception(inMemFunc("removeComment"), "H5Oset_comment_by_name failed"); + throw LocationException(inMemFunc("removeComment"), "H5Oset_comment_by_name failed"); } //-------------------------------------------------------------------------- @@ -474,52 +475,87 @@ void H5Location::removeComment(const H5std_string& name) const //-------------------------------------------------------------------------- // Function: H5Location::getComment -///\brief Retrieves comment for the specified object and its comment's -/// length. -///\param name - IN: Name of the object -///\param bufsize - IN: Length of the comment to retrieve +///\brief Retrieves the comment for this location, returning its length. +///\param name - IN: Name of the object +///\param buf_size - IN: Length of the comment to retrieve +///\param comment - OUT: Retrieved comment +///\return Actual length of the comment +///\exception H5::LocationException +///\par Description +/// This function retrieves \a buf_size characters of the comment +/// including the null terminator. Thus, if the actual length +/// of the comment is more than buf_size-1, the retrieved comment +/// will be truncated to accommodate the null terminator. +// Programmer Binh-Minh Ribler - Mar 2014 +//-------------------------------------------------------------------------- +ssize_t H5Location::getComment(const char* name, const size_t buf_size, char* comment) const +{ + // H5Oget_comment_by_name will get buf_size chars of the comment including + // the null terminator + ssize_t comment_len; + comment_len = H5Oget_comment_by_name(getId(), name, comment, buf_size, H5P_DEFAULT); + + // 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"); + } + + // Return the comment length, which might be different from buf_size + return(comment_len); +} + +//-------------------------------------------------------------------------- +// Function: H5Location::getComment +///\brief Returns the comment as \a string for this location, +/// returning its length. +///\param name - IN: Name of the object +///\param buf_size - IN: Length of the comment to retrieve, default to 0 ///\return Comment string -///\exception H5::Exception +///\exception H5::LocationException // Programmer Binh-Minh Ribler - 2000 (moved from CommonFG, Sep 2013) -// 2007: QAK modified to use H5O APIs; however the first parameter is -// no longer just file or group, this function should be moved -// to another class to accommodate attribute, dataset, and named -// datatype. - BMR //-------------------------------------------------------------------------- -H5std_string H5Location::getComment(const char* name, size_t bufsize) const +H5std_string H5Location::getComment(const char* name, const size_t buf_size) const { - // bufsize is default to 256 - // temporary variable - hid_t loc_id = getId(); // temporary variable + // Initialize string to "", so that if there is no comment, the returned + // string will be empty + H5std_string comment(""); - // temporary C-string for the object's comment; bufsize already including - // null character - char* comment_C = new char[bufsize]; - ssize_t ret_value = H5Oget_comment_by_name(loc_id, name, comment_C, bufsize, H5P_DEFAULT); + // Preliminary call to get the comment's length + ssize_t comment_len = H5Oget_comment_by_name(getId(), name, NULL, (size_t)0, H5P_DEFAULT); - // if the actual length of the comment is longer than bufsize and bufsize - // was the default value, i.e., not given by the user, then call - // H5Oget_comment_by_name again with the correct value. - // If the call to H5Oget_comment_by_name returned an error, skip this block - // and throw an exception below. - if (ret_value >= 0 && (size_t)ret_value > bufsize && bufsize == 256) - { - size_t new_size = ret_value; - delete []comment_C; - comment_C = new char[new_size]; // new_size including null terminator - ret_value = H5Oget_comment_by_name(loc_id, name, comment_C, new_size, H5P_DEFAULT); - } + // 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"); + } - // if H5Oget_comment_by_name returns SUCCEED, return the string comment, - // otherwise, throw an exception - if (ret_value < 0) { - delete []comment_C; - throw Exception(inMemFunc("getComment"), "H5Oget_comment_by_name failed"); - } + // If comment exists, calls C routine again to get it + else if (comment_len > 0) + { + size_t tmp_len = buf_size; - H5std_string comment = H5std_string(comment_C); - delete []comment_C; - return (comment); + // If buffer size is not provided, use comment length + if (tmp_len == 0) + tmp_len = comment_len; + + // Temporary buffer for char* comment + char* comment_C = new char[tmp_len+1]; + HDmemset(comment_C, 0, tmp_len+1); // clear buffer + + // Used overloaded function + ssize_t comment_len = getComment(name, tmp_len, comment_C); + + // Convert the C comment to return + comment = comment_C; + + // Clean up resource + delete []comment_C; + } + // Otherwise, keep comment intact + + // Return the string comment + return(comment); } //-------------------------------------------------------------------------- @@ -529,9 +565,9 @@ H5std_string H5Location::getComment(const char* name, size_t bufsize) const /// \c H5std_string for \a name. // Programmer Binh-Minh Ribler - 2000 (moved from CommonFG, Sep 2013) //-------------------------------------------------------------------------- -H5std_string H5Location::getComment(const H5std_string& name, size_t bufsize) const +H5std_string H5Location::getComment(const H5std_string& name, const size_t buf_size) const { - return(getComment(name.c_str(), bufsize)); + return(getComment(name.c_str(), buf_size)); } #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -542,7 +578,7 @@ H5std_string H5Location::getComment(const H5std_string& name, size_t bufsize) co // name - IN: Name of the object to be referenced // dataspace - IN: Dataspace with selection // ref_type - IN: Type of reference; default to \c H5R_DATASET_REGION -// Exception H5::IdComponentException +// Exception H5::ReferenceException // Programmer Binh-Minh Ribler - May, 2004 //-------------------------------------------------------------------------- void H5Location::p_reference(void* ref, const char* name, hid_t space_id, H5R_type_t ref_type) const diff --git a/c++/src/H5Location.h b/c++/src/H5Location.h index bbe86fc..11dbf85 100644 --- a/c++/src/H5Location.h +++ b/c++/src/H5Location.h @@ -104,8 +104,9 @@ class H5_DLLCPP H5Location : public IdComponent { void setComment(const H5std_string& comment) const; // Retrieves comment for the HDF5 object specified by its name. - H5std_string getComment(const char* name, size_t bufsize=256) const; - H5std_string getComment(const H5std_string& name, size_t bufsize=256) const; + ssize_t getComment(const char* name, const size_t buf_size, char* comment) const; + H5std_string getComment(const char* name, size_t buf_size=0) const; + H5std_string getComment(const H5std_string& name, size_t buf_size=0) const; // Removes the comment for the HDF5 object specified by its name. void removeComment(const char* name) const; diff --git a/c++/src/H5PropList.cpp b/c++/src/H5PropList.cpp index 9476d46..a49995d 100644 --- a/c++/src/H5PropList.cpp +++ b/c++/src/H5PropList.cpp @@ -390,8 +390,13 @@ void PropList::getProperty(const char* name, void* value) const //-------------------------------------------------------------------------- H5std_string PropList::getProperty(const char* name) const { + // Get property size first size_t size = getPropSize(name); + + // Allocate buffer then get the property char* prop_strg_C = new char[size+1]; // temporary C-string for C API + HDmemset(prop_strg_C, 0, size+1); // clear buffer + herr_t ret_value = H5Pget(id, name, prop_strg_C); // call C API // Throw exception if H5Pget returns failure diff --git a/c++/test/dsets.cpp b/c++/test/dsets.cpp index 811d8c7..b6922c2 100644 --- a/c++/test/dsets.cpp +++ b/c++/test/dsets.cpp @@ -120,6 +120,11 @@ test_create( H5File& file) // way to open an existing dataset for accessing. dataset = new DataSet (file.openDataSet (DSET_DEFAULT_NAME)); + // Get and verify the comment from this dataset, using + // H5std_string getComment(const H5std_string& name, ) + H5std_string comment = file.getComment(DSET_DEFAULT_NAME); + verify_val(comment, "This is a dataset", "H5Location::getComment", __LINE__, __FILE__); + // Close the dataset when accessing is completed delete dataset; @@ -1067,6 +1072,12 @@ void test_dset() nerrors += test_multiopen (file)<0 ?1:0; nerrors += test_types(file)<0 ?1:0; + // Get part of the comment, random length using + // ssize_t getComment(const char* name, const size_t buf_size, char* comment) + char* comment = new char[11]; + ssize_t comment_len = file.getComment("emit diagnostics", 10, comment); + verify_val((const char*)comment, "Causes dia", "H5Location::getComment", __LINE__, __FILE__); + // Close group "emit diagnostics". grp.close(); diff --git a/c++/test/trefer.cpp b/c++/test/trefer.cpp index 36c2ee4..e7a28de 100644 --- a/c++/test/trefer.cpp +++ b/c++/test/trefer.cpp @@ -316,11 +316,13 @@ static void test_reference_obj(void) // Dereference group object from the location where 'dataset' is located group.dereference(dataset, &rbuf[2]); - // Get group's comment + // Get group's comment using + // H5std_string getComment(const char* name, ) H5std_string read_comment1 = group.getComment(".", 10); verify_val(read_comment1.c_str(), write_comment, "Group::getComment",__LINE__,__FILE__); - // Test that getComment handles failures gracefully + // Test that getComment handles failures gracefully, using + // H5std_string getComment(const char* name, ) try { H5std_string read_comment_tmp = group.getComment(NULL); } -- cgit v0.12