From 0fcac5670573e802100c2a099cdc6eb8af229d12 Mon Sep 17 00:00:00 2001 From: Binh-Minh Ribler Date: Tue, 1 Apr 2014 00:59:37 -0500 Subject: [svn-r24938] Description: - Overloaded Atribute::getName to take a char* for the attribute name: ssize_t Attribute::getName(char* attr_name, size_t buf_size) - Switched the arguments in this function: ssize_t getName(size_t buf_size, H5std_string& attr_name) so it became: ssize_t getName(H5std_string& attr_name, size_t buf_size) The second argument is default to 0, and can be skipped. - Removed this function: H5std_string getName(size_t buf_size); it'll collide with the first function when that function takes a NULL for the first argument, and uses default value for the second argument. - Added more tests Platforms tested: Linux/ppc64 (ostrich) Linux/32 2.6 (jam) SunOS 5.11 (emu) --- c++/src/H5Attribute.cpp | 148 +++++++++++++++++++++++++++++++++--------------- c++/src/H5Attribute.h | 6 +- c++/src/H5DxferProp.cpp | 1 - c++/test/tattr.cpp | 118 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 222 insertions(+), 51 deletions(-) diff --git a/c++/src/H5Attribute.cpp b/c++/src/H5Attribute.cpp index a98a970..9554f95 100644 --- a/c++/src/H5Attribute.cpp +++ b/c++/src/H5Attribute.cpp @@ -299,75 +299,129 @@ H5std_string Attribute::getFileName() const //-------------------------------------------------------------------------- // Function: Attribute::getName ///\brief Gets the name of this attribute, returning its length. -///\param buf_size - IN: Desired length of the name -///\param attr_name - OUT: Buffer for the name string -///\return Length of the attribute name +///\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 -// Programmer Binh-Minh Ribler - Nov, 2001 -//-------------------------------------------------------------------------- -ssize_t Attribute::getName( size_t buf_size, H5std_string& attr_name ) const +///\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 { - char* name_C = new char[buf_size+1]; // temporary C-string for C API + // 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); - // Calls C routine H5Aget_name to get the name of the attribute - ssize_t name_size = H5Aget_name( id, buf_size, name_C ); + // 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"); + } - // If H5Aget_name returns a negative value, raise an exception, - if( name_size < 0 ) - { - throw AttributeIException("Attribute::getName", "H5Aget_name failed"); - } - // otherwise, convert the C attribute name and return - attr_name = name_C; - delete []name_C; - return( name_size ); + return(name_size); } //-------------------------------------------------------------------------- // Function: Attribute::getName -///\brief This is an overloaded member function, provided for convenience. -/// It differs from the above function in that it returns the -/// attribute's name, not the length. +///\brief Returns the name of this attribute as an \a H5std_string. ///\return Name of the attribute -///\param buf_size - IN: Desired length of the name ///\exception H5::AttributeIException -// Programmer Binh-Minh Ribler - 2000 +// Programmer Binh-Minh Ribler - May, 2004 +// Modification +// Mar 2014 - BMR +// Revised to use the modified getName() above //-------------------------------------------------------------------------- -H5std_string Attribute::getName( size_t buf_size ) const +H5std_string Attribute::getName() const { - H5std_string attr_name; - ssize_t name_size = getName( buf_size, attr_name ); - return( attr_name ); - // let caller catch exception if any + 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, (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"); + } + // If attribute's name exists, calls C routine again to get 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 functions in that it doesn't take -/// any arguments and returns the attribute's name. -///\return Name of the attribute +///\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 -// Programmer Binh-Minh Ribler - May, 2004 +///\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 +// Revised to allow buf_size to be skipped //-------------------------------------------------------------------------- -H5std_string Attribute::getName() const +ssize_t Attribute::getName(H5std_string& attr_name, size_t len) const { - // Try with 256 characters for the name first, if the name's length - // returned is more than that then, read the name again with the - // appropriate space allocation - char* name_C = new char[256]; // temporary C-string for C API - ssize_t name_size = H5Aget_name(id, 255, name_C); + 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 - H5std_string attr_name; - if (name_size >= 256) - name_size = getName(name_size, attr_name); + // Use overloaded function + name_size = getName(name_C, len+1); - // otherwise, convert the C attribute name and return - else - attr_name = name_C; + // Convert the C attribute name to return + attr_name = name_C; + + // Clean up resource + delete []name_C; + } + // Otherwise, keep attr_name intact - delete []name_C; - return( attr_name ); + // Return name size + return(name_size); } //-------------------------------------------------------------------------- diff --git a/c++/src/H5Attribute.h b/c++/src/H5Attribute.h index 4f15c7f..8332632 100644 --- a/c++/src/H5Attribute.h +++ b/c++/src/H5Attribute.h @@ -38,9 +38,9 @@ class H5_DLLCPP Attribute : public AbstractDs, public IdComponent { H5std_string getFileName() const; // Gets the name of this attribute. - ssize_t getName( size_t buf_size, H5std_string& attr_name ) const; - H5std_string getName( size_t buf_size ) const; // returns name, not its length - H5std_string getName() const; // returns name, no argument + ssize_t getName(char* attr_name, size_t buf_size = 0) const; + ssize_t getName(H5std_string& attr_name, size_t buf_size = 0) const; + H5std_string getName() const; // Gets a copy of the dataspace for this attribute. virtual DataSpace getSpace() const; diff --git a/c++/src/H5DxferProp.cpp b/c++/src/H5DxferProp.cpp index 1e5c7b8..c58eeda 100644 --- a/c++/src/H5DxferProp.cpp +++ b/c++/src/H5DxferProp.cpp @@ -284,7 +284,6 @@ H5std_string DSetMemXferPropList::getDataTransform() const { // Temporary buffer for char* expression char* exp_C = new char[exp_len+1]; - exp_C = (char *)HDmalloc(exp_len+1); HDmemset(exp_C, 0, exp_len+1); // clear buffer // Used overloaded function diff --git a/c++/test/tattr.cpp b/c++/test/tattr.cpp index 7e77e85..e2e347b 100644 --- a/c++/test/tattr.cpp +++ b/c++/test/tattr.cpp @@ -244,6 +244,123 @@ static void test_attr_basic_write() /**************************************************************** ** +** test_attr_getname(): Test getting attribute name functions. +** +** Test these functions: +** A. ssize_t Attribute::getName(char* attr_name, size_t buf_size) +** 1. With arbitrary buf_size that is larger than the name size +** 2. With arbitrary buf_size that is smaller than the name's length. +** 3. With a buf_size that equals the name's length. +** +** B. ssize_t Attribute::getName(H5std_string& attr_name, size_t buf_size) +** With buffer smaller than the actual name +** +** C. H5std_string Attribute::getName() with file's and dataset's attrs. +** +** D. ssize_t Attribute::getName(H5std_string& attr_name, size_t buf_size) +** With buffer size equals the name's length, i.e., buf_size=0 +** +****************************************************************/ +static void test_attr_getname() +{ + // Output message about test being performed + SUBTEST("Testing all overloads of Attribute::getName"); + + try { + // + // Open the file FILE_BASIC and test getName with its attribute + // + + // Open file + H5File fid1(FILE_BASIC, H5F_ACC_RDWR); + + // Check for existence of attribute FATTR1_NAME + bool attr_exists = fid1.attrExists(FATTR1_NAME); + if (attr_exists == false) + throw InvalidActionException("H5File::attrExists", "Attribute should exist but does not"); + + // Open attribute + Attribute fattr1(fid1.openAttribute(FATTR1_NAME)); + + // A. Get attribute name with + // ssize_t Attribute::getName(char* attr_name, size_t buf_size) + // using different buffer sizes and verify against FATTR1_NAME (3 cases) + + // 1. With arbitrary buf_size that is larger than the name size + size_t buf_size = FATTR1_NAME.length() + 10; + char* fattr1_name = new char[buf_size+1]; + HDmemset(fattr1_name, 0, buf_size+1); + ssize_t name_size = 0; // actual length of attribute name + name_size = fattr1.getName(fattr1_name, buf_size+1); + verify_val((const char*)fattr1_name, FATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); + delete []fattr1_name; + + // 2. With arbitrary buf_size that is smaller than the name's length. + // Let's try 4 first characters in the name. + buf_size = 4; + char short_name[5] = "File"; // to verify the read name + fattr1_name = new char[buf_size+1]; + HDmemset(fattr1_name, 0, buf_size+1); + name_size = fattr1.getName(fattr1_name, buf_size+1); + verify_val((const char*)fattr1_name, (const char*)short_name, "Attribute::getName", __LINE__, __FILE__); + delete []fattr1_name; + + // 3. With a buf_size that equals the name's length. + buf_size = FATTR1_NAME.length(); + fattr1_name = new char[buf_size+1]; + HDmemset(fattr1_name, 0, buf_size+1); + name_size = fattr1.getName(fattr1_name, buf_size+1); + verify_val(fattr1_name, FATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); + delete []fattr1_name; + + // B. Get attribute name with + // ssize_t Attribute::getName(H5std_string& attr_name, size_t buf_size) + // using buffer smaller than the actual name + buf_size = 4; + H5std_string fattr1_name2; + name_size = fattr1.getName(fattr1_name2, buf_size); + + // C. Get file attribute's name with + // H5std_string Attribute::getName() + H5std_string fattr1_name3 = fattr1.getName(); + verify_val(fattr1_name3, FATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); + + // + // Open the dataset DSET1_NAME and test getName with its attribute + // + + // Open dataset DSET1_NAME + DataSet dataset = fid1.openDataSet(DSET1_NAME); + + // Check for existence of attribute + attr_exists = dataset.attrExists(ATTR1_NAME); + if (attr_exists == false) + throw InvalidActionException("H5File::attrExists", "Attribute should exist but does not"); + + // Open attribute + Attribute attr1(dataset.openAttribute(ATTR1_NAME)); + + // Get dataset attribute's name with + // H5std_string Attribute::getName() + H5std_string dattr_name1 = attr1.getName(); + verify_val(dattr_name1, ATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); + + // D. Get attribute name with + // H5std_string Attribute::getName(H5std_string attr_name, buf_size=0) + H5std_string dattr_name2; + name_size = attr1.getName(dattr_name2); + verify_val(dattr_name2, ATTR1_NAME, "Attribute::getName", __LINE__, __FILE__); + + PASSED(); + } // end try block + + catch (Exception E) { + issue_fail_msg("test_attr_getname()", __LINE__, __FILE__, E.getCDetailMsg()); + } +} // test_attr_getname() + +/**************************************************************** +** ** test_attr_rename(): Test renaming attribute function. ** ****************************************************************/ @@ -1433,6 +1550,7 @@ void test_attr() MESSAGE(5, ("Testing Attributes\n")); test_attr_basic_write(); // Test basic H5A writing code + test_attr_getname(); // Test overloads of Attribute::getName test_attr_rename(); // Test renaming attribute test_attr_basic_read(); // Test basic H5A reading code -- cgit v0.12