From 67a679af07ec8a032f32fe54af84e673c0c3b3ae Mon Sep 17 00:00:00 2001 From: Raymond Lu Date: Tue, 29 Oct 2002 11:37:49 -0500 Subject: [svn-r6041] Purpose: Bug fix Description: #340 - get comment length for H5G; #435 - H5Aget_storage_size; #644 - H5Arename Platforms tested: eirene, arabica --- src/H5A.c | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/H5Aprivate.h | 6 +- src/H5Apublic.h | 28 ++++---- src/H5G.c | 3 +- test/tattr.c | 131 +++++++++++++++++++++++++++++++++--- 5 files changed, 338 insertions(+), 32 deletions(-) diff --git a/src/H5A.c b/src/H5A.c index b32572b..24efd72 100644 --- a/src/H5A.c +++ b/src/H5A.c @@ -959,7 +959,7 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf) /* check arguments */ if (NULL == (attr = H5I_object_verify(attr_id, H5I_ATTR))) HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not an attribute"); - if (!buf || buf_size<1) + if (!buf && buf_size) HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid buffer"); /* get the real attribute length */ @@ -970,10 +970,12 @@ H5Aget_name(hid_t attr_id, size_t buf_size, char *buf) copy_len = MIN(buf_size-1, nbytes); /* Copy all/some of the name */ - HDmemcpy(buf, attr->name, copy_len); + if(buf && copy_len>0) { + HDmemcpy(buf, attr->name, copy_len); - /* Terminate the string */ - buf[copy_len]='\0'; + /* Terminate the string */ + buf[copy_len]='\0'; + } /* Set return value */ ret_value = (ssize_t)nbytes; @@ -983,6 +985,81 @@ done: } /* H5Aget_type() */ +/*------------------------------------------------------------------------- + * Function: H5Aget_storage_size + * + * Purpose: Returns the amount of storage size that is required for this + * attribute. + * + * Return: Success: The amount of storage size allocated for the + * attribute. The return value may be zero + * if no data has been stored. + * + * Failure: Zero + * + * Programmer: Raymond Lu + * October 23, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hsize_t +H5Aget_storage_size(hid_t attr_id) +{ + H5A_t *attr=NULL; + hsize_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Aget_storage_size, 0); + H5TRACE1("h","i",attr_id); + + /* Check args */ + if (NULL==(attr=H5I_object_verify(attr_id, H5I_ATTR))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, 0, "not an attribute"); + + /* Set return value */ + ret_value = H5A_get_storage_size(attr); + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5A_get_storage_size + * + * Purpose: Private function for H5Aget_storage_size. Returns the + * amount of storage size that is required for this + * attribute. + * + * Return: Success: The amount of storage size allocated for the + * attribute. The return value may be zero + * if no data has been stored. + * + * Failure: Zero + * + * Programmer: Raymond Lu + * October 23, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +hsize_t +H5A_get_storage_size(H5A_t *attr) +{ + hsize_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5A_get_storage_size, 0); + + /* Set return value */ + ret_value = attr->data_size; + +done: + FUNC_LEAVE(ret_value); +} + + /*-------------------------------------------------------------------------- NAME H5Aget_num_attrs @@ -1042,6 +1119,121 @@ done: } /* H5Aget_num_attrs() */ +/*------------------------------------------------------------------------- + * Function: H5Arename + * + * Purpose: Rename an attribute + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Raymond Lu + * October 23, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5Arename(hid_t loc_id, char *old_name, char *new_name) +{ + H5G_entry_t *ent = NULL; /*symtab ent of object to attribute */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_API(H5Arename, FAIL); + H5TRACE3("e","iss",loc_id,old_name,new_name); + + /* check arguments */ + if (!old_name || !new_name) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "name is nil"); + if (H5I_FILE==H5I_get_type(loc_id) || H5I_ATTR==H5I_get_type(loc_id)) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "location is not valid for an attribute"); + if (NULL==(ent=H5G_loc(loc_id))) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a location"); + + /* Call private function */ + ret_value = H5A_rename(ent, old_name, new_name); + +done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5A_rename + * + * Purpose: Private function for H5Arename. Rename an attribute + * + * Return: Success: Non-negative + * + * Failure: Negative + * + * Programmer: Raymond Lu + * October 23, 2002 + * + * Modifications: + * + *------------------------------------------------------------------------- + */ +herr_t +H5A_rename(H5G_entry_t *ent, char *old_name, char *new_name) +{ + int seq, idx=FAIL; /* Index of attribute being querried */ + H5A_t *found_attr; /* Attribute with OLD_NAME */ + herr_t ret_value; /* Return value */ + + FUNC_ENTER_NOAPI(H5A_rename, FAIL); + + /* Check arguments */ + assert(ent); + assert(old_name); + assert(new_name); + + /* Build the attribute information */ + if((found_attr = HDcalloc(1, sizeof(H5A_t)))==NULL) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for attribute info"); + + /* Read in the existing attributes to check for duplicates */ + seq=0; + while(H5O_read(ent, H5O_ATTR, seq, found_attr)!=NULL) { + /* + * Compare found attribute name. + */ + if(HDstrcmp(found_attr->name,old_name)==0) { + idx = seq; + break; + } + H5O_reset (H5O_ATTR, found_attr); + seq++; + } + + if(idx<0) + HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "attribute cannot be found"); + + /* Copy the attribute name. */ + if(found_attr->name) + HDfree(found_attr->name); + found_attr->name = HDstrdup(new_name); + if(!found_attr->name) + HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "String copy failed"); + + /* Indicate entry is not opened and the attribute doesn't need fill-values. */ + found_attr->ent_opened=FALSE; + found_attr->initialized=TRUE; + + /* Modify the attribute message */ + if (H5O_modify(ent, H5O_ATTR, idx, 0, found_attr) < 0) + HGOTO_ERROR(H5E_ATTR, H5E_CANTINIT, FAIL, "unable to update attribute header messages"); + + /* Close the attribute */ + if(found_attr) H5A_close(found_attr); + +done: + FUNC_LEAVE(ret_value); +} + + /*-------------------------------------------------------------------------- NAME H5Aiterate @@ -1309,7 +1501,7 @@ done: /*------------------------------------------------------------------------- * Function: H5A_close * - * Purpose: Frees a attribute and all associated memory. + * Purpose: Frees an attribute and all associated memory. * * Return: Non-negative on success/Negative on failure * diff --git a/src/H5Aprivate.h b/src/H5Aprivate.h index d94df90..7f61a12 100644 --- a/src/H5Aprivate.h +++ b/src/H5Aprivate.h @@ -25,8 +25,10 @@ typedef struct H5A_t H5A_t; /* Private headers needed by this file */ /* Functions defined in H5A.c */ -H5_DLL H5A_t * H5A_copy(const H5A_t *old_attr); -H5_DLL herr_t H5A_close(H5A_t *attr); +H5_DLL H5A_t *H5A_copy(const H5A_t *old_attr); +H5_DLL herr_t H5A_close(H5A_t *attr); H5_DLL H5G_entry_t *H5A_entof(H5A_t *attr); +H5_DLL hsize_t H5A_get_storage_size(H5A_t *attr); +H5_DLL herr_t H5A_rename(H5G_entry_t *ent, char *old_name, char *new_name); #endif diff --git a/src/H5Apublic.h b/src/H5Apublic.h index aa7d0eb..218e481 100644 --- a/src/H5Apublic.h +++ b/src/H5Apublic.h @@ -27,20 +27,22 @@ typedef herr_t (*H5A_operator_t)(hid_t location_id/*in*/, const char *attr_name/*in*/, void *operator_data/*in,out*/); /* Public function prototypes */ -H5_DLL hid_t H5Acreate(hid_t loc_id, const char *name, hid_t type_id, - hid_t space_id, hid_t plist_id); -H5_DLL hid_t H5Aopen_name(hid_t loc_id, const char *name); -H5_DLL hid_t H5Aopen_idx(hid_t loc_id, unsigned idx); -H5_DLL herr_t H5Awrite(hid_t attr_id, hid_t type_id, const void *buf); -H5_DLL herr_t H5Aread(hid_t attr_id, hid_t type_id, void *buf); -H5_DLL herr_t H5Aclose(hid_t attr_id); -H5_DLL hid_t H5Aget_space(hid_t attr_id); -H5_DLL hid_t H5Aget_type(hid_t attr_id); +H5_DLL hid_t H5Acreate(hid_t loc_id, const char *name, hid_t type_id, + hid_t space_id, hid_t plist_id); +H5_DLL hid_t H5Aopen_name(hid_t loc_id, const char *name); +H5_DLL hid_t H5Aopen_idx(hid_t loc_id, unsigned idx); +H5_DLL herr_t H5Awrite(hid_t attr_id, hid_t type_id, const void *buf); +H5_DLL herr_t H5Aread(hid_t attr_id, hid_t type_id, void *buf); +H5_DLL herr_t H5Aclose(hid_t attr_id); +H5_DLL hid_t H5Aget_space(hid_t attr_id); +H5_DLL hid_t H5Aget_type(hid_t attr_id); H5_DLL ssize_t H5Aget_name(hid_t attr_id, size_t buf_size, char *buf); -H5_DLL int H5Aget_num_attrs(hid_t loc_id); -H5_DLL herr_t H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, - void *op_data); -H5_DLL herr_t H5Adelete(hid_t loc_id, const char *name); +H5_DLL hsize_t H5Aget_storage_size(hid_t attr_id); +H5_DLL int H5Aget_num_attrs(hid_t loc_id); +H5_DLL herr_t H5Arename(hid_t loc_id, char *old_name, char *new_name); +H5_DLL herr_t H5Aiterate(hid_t loc_id, unsigned *attr_num, H5A_operator_t op, + void *op_data); +H5_DLL herr_t H5Adelete(hid_t loc_id, const char *name); #ifdef __cplusplus } diff --git a/src/H5G.c b/src/H5G.c index f6f0633..d08ac5b 100644 --- a/src/H5G.c +++ b/src/H5G.c @@ -2415,7 +2415,8 @@ H5G_get_comment(H5G_entry_t *loc, const char *name, size_t bufsize, char *buf) buf[0] = '\0'; ret_value = 0; } else { - HDstrncpy(buf, comment.s, bufsize); + if(buf && bufsize) + HDstrncpy(buf, comment.s, bufsize); ret_value = (int)HDstrlen(comment.s); H5O_reset(H5O_NAME, &comment); } diff --git a/test/tattr.c b/test/tattr.c index 43c87dd..f211c5e 100644 --- a/test/tattr.c +++ b/test/tattr.c @@ -1,13 +1,13 @@ /**************************************************************************** - * NCSA HDF * - * Software Development Group * - * National Center for Supercomputing Applications * - * University of Illinois at Urbana-Champaign * - * 605 E. Springfield, Champaign IL 61820 * - * * - * For conditions of distribution and use, see the accompanying * - * hdf/COPYING file. * - * * + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * ****************************************************************************/ /* $Id$ */ @@ -26,6 +26,7 @@ #define FILENAME "tattr.h5" #define ATTR_NAME_LEN 16 #define ATTR_MAX_DIMS 7 +#define ATTR_TMP_NAME "temp_name" /* 3-D dataset with fixed dimensions */ #define SPACE1_NAME "Space1" @@ -43,6 +44,10 @@ #define ATTR1_DIM1 3 int attr_data1[ATTR1_DIM1]={512,-234,98123}; /* Test data for 1st attribute */ +/* rank & dimensions for another attribute */ +#define ATTR1A_NAME "Attr1_a" +int attr_data1a[ATTR1_DIM1]={256,11945,-22107}; + #define ATTR2_NAME "Attr2" #define ATTR2_RANK 2 #define ATTR2_DIM1 2 @@ -92,7 +97,10 @@ test_attr_basic_write(void) hid_t dataset; /* Dataset ID */ hid_t group; /* Group ID */ hid_t sid1,sid2; /* Dataspace ID */ - hid_t attr; /* Attribute ID */ + hid_t attr, attr2; /* Attribute ID */ + hsize_t attr_size; /* storage size for attribute */ + ssize_t attr_name_size; /* size of attribute name */ + char *attr_name; /* name of attribute */ hsize_t dims1[] = {SPACE1_DIM1, SPACE1_DIM2, SPACE1_DIM3}; hsize_t dims2[] = {ATTR1_DIM1}; hsize_t dims3[] = {ATTR2_DIM1,ATTR2_DIM2}; @@ -134,6 +142,18 @@ test_attr_basic_write(void) ret=H5Awrite(attr,H5T_NATIVE_INT,attr_data1); CHECK(ret, FAIL, "H5Awrite"); + /* Create an another attribute for the dataset */ + attr2=H5Acreate(dataset,ATTR1A_NAME,H5T_NATIVE_INT,sid2,H5P_DEFAULT); + CHECK(attr, FAIL, "H5Acreate"); + + /* Write attribute information */ + ret=H5Awrite(attr2,H5T_NATIVE_INT,attr_data1a); + CHECK(ret, FAIL, "H5Awrite"); + + /* Check storage size for attribute */ + attr_size=H5Aget_storage_size(attr); + VERIFY(attr_size, (ATTR1_DIM1*sizeof(int)), "H5A_get_storage_size"); + /* Read attribute information immediately, without closing attribute */ ret=H5Aread(attr,H5T_NATIVE_INT,read_data1); CHECK(ret, FAIL, "H5Aread"); @@ -149,6 +169,87 @@ test_attr_basic_write(void) ret=H5Aclose(attr); CHECK(ret, FAIL, "H5Aclose"); + /* Close attribute */ + ret=H5Aclose(attr2); + CHECK(ret, FAIL, "H5Aclose"); + + /* change attribute name */ + ret=H5Arename(dataset, ATTR1_NAME, ATTR_TMP_NAME); + CHECK(ret, FAIL, "H5Arename"); + + /* Open attribute again */ + attr=H5Aopen_name(dataset, ATTR_TMP_NAME); + CHECK(attr, FAIL, "H5Aopen_name"); + + /* Verify new attribute name */ + attr_name_size = H5Aget_name(attr, 0, NULL); + CHECK(attr_name_size, FAIL, "H5Aget_name"); + + if(attr_name_size>0) + attr_name = (char*)HDcalloc(attr_name_size+1, sizeof(char)); + + ret=H5Aget_name(attr, attr_name_size+1, attr_name); + CHECK(ret, FAIL, "H5Aget_name"); + ret=HDstrcmp(attr_name, ATTR_TMP_NAME); + VERIFY(ret, 0, "HDstrcmp"); + + if(attr_name) + HDfree(attr_name); + + /* Read attribute information immediately, without closing attribute */ + ret=H5Aread(attr,H5T_NATIVE_INT,read_data1); + CHECK(ret, FAIL, "H5Aread"); + + /* Verify values read in */ + for(i=0; i0) + attr_name = (char*)HDcalloc(attr_name_size+1, sizeof(char)); + + ret=H5Aget_name(attr2, attr_name_size+1, attr_name); + CHECK(ret, FAIL, "H5Aget_name"); + ret=HDstrcmp(attr_name, ATTR1A_NAME); + VERIFY(ret, 0, "HDstrcmp"); + + if(attr_name) + HDfree(attr_name); + + /* Read attribute information immediately, without closing attribute */ + ret=H5Aread(attr2,H5T_NATIVE_INT,read_data1); + CHECK(ret, FAIL, "H5Aread"); + + /* Verify values read in */ + for(i=0; i