diff options
author | Binh-Minh Ribler <bmribler@hdfgroup.org> | 2014-03-23 21:30:43 (GMT) |
---|---|---|
committer | Binh-Minh Ribler <bmribler@hdfgroup.org> | 2014-03-23 21:30:43 (GMT) |
commit | 74079aa0de09be6c57244bb4d33fcda51f7a2f4c (patch) | |
tree | ccce4a37a0a538d1a8871a3d2828e7f1f30746e4 | |
parent | e18ee63c5a5c294d1949d83b1d34ae1fe15086ae (diff) | |
download | hdf5-74079aa0de09be6c57244bb4d33fcda51f7a2f4c.zip hdf5-74079aa0de09be6c57244bb4d33fcda51f7a2f4c.tar.gz hdf5-74079aa0de09be6c57244bb4d33fcda51f7a2f4c.tar.bz2 |
[svn-r24870] 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
- Added a null terminator to the comment returned from the C call, in
getComment methods
- Some minor cleanup
Merged from trunk: -r24865 -r24867
Platforms tested:
Linux/ppc64 (ostrich)
Linux/32 2.6 (jam)
SunOS 5.11 (emu)
-rw-r--r-- | c++/src/H5CommonFG.cpp | 9 | ||||
-rw-r--r-- | c++/src/H5DataSet.cpp | 10 | ||||
-rw-r--r-- | c++/src/H5EnumType.cpp | 4 | ||||
-rw-r--r-- | c++/src/H5Exception.cpp | 23 | ||||
-rw-r--r-- | c++/src/H5Exception.h | 7 | ||||
-rw-r--r-- | c++/src/H5File.h | 14 | ||||
-rw-r--r-- | c++/src/H5Group.h | 7 | ||||
-rw-r--r-- | c++/src/H5IdComponent.cpp | 3 | ||||
-rw-r--r-- | c++/src/H5Location.cpp | 138 | ||||
-rw-r--r-- | c++/src/H5Location.h | 5 | ||||
-rw-r--r-- | c++/src/H5PropList.cpp | 5 | ||||
-rw-r--r-- | c++/test/dsets.cpp | 11 | ||||
-rw-r--r-- | c++/test/trefer.cpp | 6 |
13 files changed, 171 insertions, 71 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 1a26045..7f2f152 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 555eb89..47263c7 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/H5File.h b/c++/src/H5File.h index 06b4fec..694d688 100644 --- a/c++/src/H5File.h +++ b/c++/src/H5File.h @@ -76,6 +76,7 @@ class H5_DLLCPP H5File : public H5Location, public CommonFG { // Reopens this file. void reOpen(); // added for better name + #ifndef DOXYGEN_SHOULD_SKIP_THIS void reopen(); // obsolete in favor of reOpen() @@ -102,6 +103,12 @@ class H5_DLLCPP H5File : public H5Location, public CommonFG { // H5File destructor. virtual ~H5File(); + protected: +#ifndef DOXYGEN_SHOULD_SKIP_THIS + // Sets the HDF5 file id. + virtual void p_setId(const hid_t new_id); +#endif // DOXYGEN_SHOULD_SKIP_THIS + private: hid_t id; // HDF5 file id @@ -109,13 +116,6 @@ class H5_DLLCPP H5File : public H5Location, public CommonFG { // constructors taking a string or a char* void p_get_file( const char* name, unsigned int flags, const FileCreatPropList& create_plist, const FileAccPropList& access_plist ); - protected: -#ifndef DOXYGEN_SHOULD_SKIP_THIS - // Sets the HDF5 file id. - virtual void p_setId(const hid_t new_id); - -#endif // DOXYGEN_SHOULD_SKIP_THIS - }; #ifndef H5_NO_NAMESPACE } diff --git a/c++/src/H5Group.h b/c++/src/H5Group.h index 8194344..100b214 100644 --- a/c++/src/H5Group.h +++ b/c++/src/H5Group.h @@ -59,14 +59,15 @@ class H5_DLLCPP Group : public H5Object, public CommonFG { // Creates a copy of an existing group using its id. Group( const hid_t group_id ); - private: - hid_t id; // HDF5 group id - protected: #ifndef DOXYGEN_SHOULD_SKIP_THIS // Sets the group id. virtual void p_setId(const hid_t new_id); #endif // DOXYGEN_SHOULD_SKIP_THIS + + private: + hid_t id; // HDF5 group id + }; #ifndef H5_NO_NAMESPACE } 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 88c56ee..7a705f2 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,91 @@ 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"); + } + // If the comment is longer than the provided buffer size, the C library + // will not null terminate it + if (comment_len >= buf_size) + comment[buf_size-1] = '\0'; + + // Return the actual 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+1, 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 +569,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 +582,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 db22bff..0e46b4d 100644 --- a/c++/src/H5Location.h +++ b/c++/src/H5Location.h @@ -103,8 +103,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..72d7977 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, <buf_size=0, by default>) + 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", 11, 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 ae1ab02..d2581a3 100644 --- a/c++/test/trefer.cpp +++ b/c++/test/trefer.cpp @@ -317,11 +317,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, <buf_size=0 by default>) 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, <buf_size=0 by default>) try { H5std_string read_comment_tmp = group.getComment(NULL); } |