summaryrefslogtreecommitdiff
path: root/tools/lib/h5diff_attr.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/lib/h5diff_attr.c')
-rw-r--r--tools/lib/h5diff_attr.c589
1 files changed, 589 insertions, 0 deletions
diff --git a/tools/lib/h5diff_attr.c b/tools/lib/h5diff_attr.c
new file mode 100644
index 0000000..5642a9b
--- /dev/null
+++ b/tools/lib/h5diff_attr.c
@@ -0,0 +1,589 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include "H5private.h"
+#include "h5tools.h"
+#include "h5tools_utils.h"
+#include "h5diff.h"
+
+#define ATTR_NAME_MAX 255
+
+typedef struct table_attr_t {
+ char *name;
+ unsigned exist[2];
+} match_attr_t;
+
+typedef struct table_attrs_t {
+ size_t size;
+ size_t nattrs;
+ size_t nattrs_only1;
+ size_t nattrs_only2;
+ match_attr_t *attrs;
+} table_attrs_t;
+
+
+/*-------------------------------------------------------------------------
+ * Function: table_attrs_init
+ *
+ * Purpose: Initialize the table
+ *
+ * Parameter:
+ * - tbl [OUT]
+ *
+ * Programmer: Jonathan Kim
+ *
+ * Date: March 15, 2011
+ *------------------------------------------------------------------------*/
+static void table_attrs_init(table_attrs_t **tbl)
+{
+ table_attrs_t* table_attrs = (table_attrs_t*) HDmalloc(sizeof(table_attrs_t));
+
+ table_attrs->size = 0;
+ table_attrs->nattrs = 0;
+ table_attrs->nattrs_only1 = 0;
+ table_attrs->nattrs_only2 = 0;
+ table_attrs->attrs = NULL;
+
+ *tbl = table_attrs;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: table_attrs_free
+ *
+ * Purpose: free given table
+ *
+ * Parameter:
+ * - table [IN]
+ *
+ * Programmer: Jonathan Kim
+ *
+ * Date: March 15, 2011
+ *------------------------------------------------------------------------*/
+static void table_attrs_free( table_attrs_t *table )
+{
+ unsigned int i;
+
+ if (table) {
+ if (table->attrs) {
+ for (i = 0; i < table->nattrs; i++) {
+ if (table->attrs[i].name) {
+ HDfree(table->attrs[i].name);
+ }
+ } /* end for */
+ HDfree(table->attrs);
+ table->attrs = NULL;
+ } /* end if */
+ HDfree(table);
+ table = NULL;
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Function: table_attr_mark_exist
+ *
+ * Purpose: mark given attribute name to table as sign of exsit
+ *
+ * Parameter:
+ * - exist [IN]
+ * - name [IN] : attribute name
+ * - table [OUT]
+ *
+ * Programmer: Jonathan Kim
+ *
+ * Date: March 15, 2011
+ *------------------------------------------------------------------------*/
+static void table_attr_mark_exist(unsigned *exist, char *name, table_attrs_t *table)
+{
+ if(table->nattrs == table->size) {
+ match_attr_t *new_attrs;
+
+ table->size = MAX(1, table->size * 2);
+ new_attrs = (match_attr_t *)HDrealloc(table->attrs, table->size * sizeof(match_attr_t));
+ if(new_attrs)
+ table->attrs = new_attrs;
+ } /* end if */
+
+ if(table->nattrs < table->size) {
+ size_t curr_val;
+
+ curr_val = table->nattrs;
+ table->attrs[curr_val].exist[0] = exist[0];
+ table->attrs[curr_val].exist[1] = exist[1];
+ if(name)
+ table->attrs[curr_val].name = (char *)HDstrdup(name);
+ table->nattrs++;
+ }
+}
+
+/*-------------------------------------------------------------------------
+ * Function: build_match_list_attrs
+ *
+ * Purpose: get list of matching attribute name from obj1 and obj2
+ *
+ * Note:
+ * Find common attribute; the algorithm for search is referred from
+ * build_match_list() in h5diff.c .
+ *
+ * Parameter:
+ * table_out [OUT] : return the list
+ *
+ * Programmer: Jonathan Kim
+ *
+ * Date: March 15, 2011
+ *------------------------------------------------------------------------*/
+static herr_t build_match_list_attrs(hid_t loc1_id, hid_t loc2_id, table_attrs_t ** table_out, diff_opt_t *options)
+{
+ H5O_info_t oinfo1, oinfo2; /* Object info */
+ hid_t attr1_id=-1; /* attr ID */
+ hid_t attr2_id=-1; /* attr ID */
+ size_t curr1 = 0;
+ size_t curr2 = 0;
+ unsigned infile[2];
+ char name1[ATTR_NAME_MAX];
+ char name2[ATTR_NAME_MAX];
+ int cmp;
+ unsigned i;
+ table_attrs_t *table_lp = NULL;
+
+ if(H5Oget_info(loc1_id, &oinfo1) < 0)
+ goto error;
+ if(H5Oget_info(loc2_id, &oinfo2) < 0)
+ goto error;
+
+ table_attrs_init( &table_lp );
+
+
+ /*--------------------------------------------------
+ * build the list
+ */
+ while(curr1 < oinfo1.num_attrs && curr2 < oinfo2.num_attrs) {
+ /*------------------
+ * open attribute1 */
+ if((attr1_id = H5Aopen_by_idx(loc1_id, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)curr1, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ goto error;
+ /* get name */
+ if(H5Aget_name(attr1_id, (size_t)ATTR_NAME_MAX, name1) < 0)
+ goto error;
+
+ /*------------------
+ * open attribute2 */
+ if((attr2_id = H5Aopen_by_idx(loc2_id, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)curr2, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ goto error;
+ /* get name */
+ if(H5Aget_name(attr2_id, (size_t)ATTR_NAME_MAX, name2) < 0)
+ goto error;
+
+ /* criteria is string compare */
+ cmp = HDstrcmp(name1, name2);
+
+ if(cmp == 0) {
+ infile[0] = 1;
+ infile[1] = 1;
+ table_attr_mark_exist(infile, name1, table_lp);
+ curr1++;
+ curr2++;
+ }
+ else if(cmp < 0) {
+ infile[0] = 1;
+ infile[1] = 0;
+ table_attr_mark_exist(infile, name1, table_lp);
+ table_lp->nattrs_only1++;
+ curr1++;
+ }
+ else {
+ infile[0] = 0;
+ infile[1] = 1;
+ table_attr_mark_exist(infile, name2, table_lp);
+ table_lp->nattrs_only2++;
+ curr2++;
+ }
+
+ /* close for next turn */
+ H5Aclose(attr1_id);
+ attr1_id = -1;
+ H5Aclose(attr2_id);
+ attr2_id = -1;
+ } /* end while */
+
+ /* list1 did not end */
+ infile[0] = 1;
+ infile[1] = 0;
+ while(curr1 < oinfo1.num_attrs) {
+ /*------------------
+ * open attribute1 */
+ if((attr1_id = H5Aopen_by_idx(loc1_id, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)curr1, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ goto error;
+ /* get name */
+ if(H5Aget_name(attr1_id, (size_t)ATTR_NAME_MAX, name1) < 0)
+ goto error;
+
+ table_attr_mark_exist(infile, name1, table_lp);
+ table_lp->nattrs_only1++;
+ curr1++;
+
+ /* close for next turn */
+ H5Aclose(attr1_id);
+ attr1_id = -1;
+ }
+
+ /* list2 did not end */
+ infile[0] = 0;
+ infile[1] = 1;
+ while(curr2 < oinfo2.num_attrs) {
+ /*------------------
+ * open attribute2 */
+ if((attr2_id = H5Aopen_by_idx(loc2_id, ".", H5_INDEX_NAME, H5_ITER_INC, (hsize_t)curr2, H5P_DEFAULT, H5P_DEFAULT)) < 0)
+ goto error;
+ /* get name */
+ if(H5Aget_name(attr2_id, (size_t)ATTR_NAME_MAX, name2) < 0)
+ goto error;
+
+ table_attr_mark_exist(infile, name2, table_lp);
+ table_lp->nattrs_only2++;
+ curr2++;
+
+ /* close for next turn */
+ H5Aclose(attr2_id);
+ }
+
+ /*------------------------------------------------------
+ * print the list
+ */
+ if(options->m_verbose_level == 2) {
+ /* if '-v2' is detected */
+ parallel_print(" obj1 obj2\n");
+ parallel_print(" --------------------------------------\n");
+ for(i = 0; i < (unsigned int) table_lp->nattrs; i++) {
+ char c1, c2;
+ c1 = (table_lp->attrs[i].exist[0]) ? 'x' : ' ';
+ c2 = (table_lp->attrs[i].exist[1]) ? 'x' : ' ';
+ parallel_print("%5c %6c %-15s\n", c1, c2, table_lp->attrs[i].name);
+ } /* end for */
+ }
+
+ if(options->m_verbose_level >= 1)
+ parallel_print("Attributes status: %d common, %d only in obj1, %d only in obj2\n",
+ table_lp->nattrs - table_lp->nattrs_only1 - table_lp->nattrs_only2,
+ table_lp->nattrs_only1, table_lp->nattrs_only2);
+
+ *table_out = table_lp;
+
+ return 0;
+
+error:
+ if (0 < attr1_id)
+ H5Aclose(attr1_id);
+ if (0 < attr2_id)
+ H5Aclose(attr2_id);
+
+ return -1;
+}
+
+/*-------------------------------------------------------------------------
+ * Function: diff_attr
+ *
+ * Purpose: compare attributes located in LOC1_ID and LOC2_ID, which are
+ * obtained either from
+ * loc_id = H5Gopen2(fid, name, H5P_DEFAULT);
+ * loc_id = H5Dopen2(fid, name);
+ * loc_id = H5Topen2(fid, name, H5P_DEFAULT);
+ *
+ * Return: number of differences found
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: November, 03, 2003
+ *
+ * Modifications:
+ * March, 02, 2007: return the number of differences found
+ *
+ *-------------------------------------------------------------------------
+ */
+
+hsize_t diff_attr(hid_t loc1_id,
+ hid_t loc2_id,
+ const char *path1,
+ const char *path2,
+ diff_opt_t *options)
+{
+ hid_t attr1_id=-1; /* attr ID */
+ hid_t attr2_id=-1; /* attr ID */
+ hid_t space1_id=-1; /* space ID */
+ hid_t space2_id=-1; /* space ID */
+ hid_t ftype1_id=-1; /* file data type ID */
+ hid_t ftype2_id=-1; /* file data type ID */
+ int vstrtype1=0; /* ftype1 is a variable string */
+ int vstrtype2=0; /* ftype2 is a variable string */
+ hid_t mtype1_id=-1; /* memory data type ID */
+ hid_t mtype2_id=-1; /* memory data type ID */
+ size_t msize1; /* memory size of memory type */
+ size_t msize2; /* memory size of memory type */
+ void *buf1=NULL; /* data buffer */
+ void *buf2=NULL; /* data buffer */
+ hbool_t buf1hasdata=FALSE; /* buffer has data */
+ hbool_t buf2hasdata=FALSE; /* buffer has data */
+ hsize_t nelmts1; /* number of elements in dataset */
+ int rank1; /* rank of dataset */
+ int rank2; /* rank of dataset */
+ hsize_t dims1[H5S_MAX_RANK];/* dimensions of dataset */
+ hsize_t dims2[H5S_MAX_RANK];/* dimensions of dataset */
+ char *name1;
+ char *name2;
+ char np1[512];
+ char np2[512];
+ unsigned u; /* Local index variable */
+ hsize_t nfound = 0;
+ hsize_t nfound_total = 0;
+ int j;
+
+ table_attrs_t * match_list_attrs = NULL;
+ if(build_match_list_attrs(loc1_id, loc2_id, &match_list_attrs, options) < 0)
+ goto error;
+
+ /* if detect any unique extra attr */
+ if(match_list_attrs->nattrs_only1 || match_list_attrs->nattrs_only2) {
+ /* exit will be 1 */
+ options->contents = 0;
+ }
+
+ for(u = 0; u < (unsigned)match_list_attrs->nattrs; u++) {
+ if((match_list_attrs->attrs[u].exist[0]) && (match_list_attrs->attrs[u].exist[1])) {
+ name1 = name2 = match_list_attrs->attrs[u].name;
+
+ /*--------------
+ * attribute 1 */
+ if((attr1_id = H5Aopen(loc1_id, name1, H5P_DEFAULT)) < 0)
+ goto error;
+
+ /*--------------
+ * attribute 2 */
+ if((attr2_id = H5Aopen(loc2_id, name2, H5P_DEFAULT)) < 0)
+ goto error;
+
+ /* get the datatypes */
+ if((ftype1_id = H5Aget_type(attr1_id)) < 0)
+ goto error;
+ vstrtype1 = H5Tis_variable_str(ftype1_id);
+ if((ftype2_id = H5Aget_type(attr2_id)) < 0)
+ goto error;
+ vstrtype2 = H5Tis_variable_str(ftype2_id);
+ /* no compare if either one but not both are variable string type */
+ if (vstrtype1 != vstrtype2) {
+ if((options->m_verbose || options->m_list_not_cmp))
+ parallel_print("Not comparable: one of attribute <%s/%s> or <%s/%s> is of variable length type\n",
+ path1, name1, path2, name2);
+ options->not_cmp = 1;
+ if (H5Tclose(ftype1_id) < 0)
+ goto error;
+ if (H5Tclose(ftype2_id) < 0)
+ goto error;
+ if (H5Aclose(attr1_id) < 0)
+ goto error;
+ if (H5Aclose(attr2_id) < 0)
+ goto error;
+
+ continue;
+ }
+
+ if((mtype1_id = h5tools_get_native_type(ftype1_id)) < 0)
+ goto error;
+ if((mtype2_id = h5tools_get_native_type(ftype2_id)) < 0)
+ goto error;
+ if((msize1 = H5Tget_size(mtype1_id)) == 0)
+ goto error;
+ if((msize2 = H5Tget_size(mtype2_id)) == 0)
+ goto error;
+
+ /* get the dataspace */
+ if((space1_id = H5Aget_space(attr1_id)) < 0)
+ goto error;
+ if((space2_id = H5Aget_space(attr2_id)) < 0)
+ goto error;
+
+ /* get dimensions */
+ if((rank1 = H5Sget_simple_extent_dims(space1_id, dims1, NULL)) < 0)
+ goto error;
+ if((rank2 = H5Sget_simple_extent_dims(space2_id, dims2, NULL)) < 0)
+ goto error;
+
+ /*----------------------------------------------------------------------
+ * check for comparable TYPE and SPACE
+ *----------------------------------------------------------------------
+ */
+
+ /* pass dims1 and dims2 for maxdims as well since attribute's maxdims
+ * are always same */
+ if(diff_can_type(ftype1_id, ftype2_id, rank1, rank2, dims1, dims2,
+ dims1, dims2, name1, name2, options, 0) != 1) {
+ if(H5Tclose(ftype1_id) < 0)
+ goto error;
+ if(H5Tclose(ftype2_id) < 0)
+ goto error;
+ if(H5Sclose(space1_id) < 0)
+ goto error;
+ if(H5Sclose(space2_id) < 0)
+ goto error;
+ if(H5Aclose(attr1_id) < 0)
+ goto error;
+ if(H5Aclose(attr2_id) < 0)
+ goto error;
+ if(H5Tclose(mtype1_id) < 0)
+ goto error;
+ if(H5Tclose(mtype2_id) < 0)
+ goto error;
+
+ continue;
+ }
+
+ /*-----------------------------------------------------------------
+ * "upgrade" the smaller memory size
+ *------------------------------------------------------------------
+ */
+ if(FAIL == match_up_memsize(ftype1_id, ftype2_id, &mtype1_id,
+ &mtype2_id, &msize1, &msize2))
+ goto error;
+
+ /*---------------------------------------------------------------------
+ * read
+ *----------------------------------------------------------------------
+ */
+ nelmts1 = 1;
+ for(j = 0; j < rank1; j++)
+ nelmts1 *= dims1[j];
+
+ buf1 = (void *)HDmalloc((size_t)(nelmts1 * msize1));
+ buf2 = (void *)HDmalloc((size_t)(nelmts1 * msize2));
+ if(buf1 == NULL || buf2 == NULL) {
+ parallel_print("cannot read into memory\n");
+ goto error;
+ }
+ if(H5Aread(attr1_id, mtype1_id, buf1) < 0) {
+ parallel_print("Failed reading attribute1 %s/%s\n", path1, name1);
+ goto error;
+ }
+ else
+ buf1hasdata = TRUE;
+
+ if(H5Aread(attr2_id, mtype2_id, buf2) < 0) {
+ parallel_print("Failed reading attribute2 %s/%s\n", path2, name2);
+ goto error;
+ }
+ else
+ buf2hasdata = TRUE;
+
+ /* format output string */
+ HDsnprintf(np1, sizeof(np1), "%s of <%s>", name1, path1);
+ HDsnprintf(np2, sizeof(np1), "%s of <%s>", name2, path2);
+
+ /*---------------------------------------------------------------------
+ * array compare
+ *----------------------------------------------------------------------
+ */
+
+ /* always print name */
+ /* verbose (-v) and report (-r) mode */
+ if(options->m_verbose || options->m_report) {
+ do_print_attrname("attribute", np1, np2);
+
+ nfound = diff_array(buf1, buf2, nelmts1, (hsize_t) 0, rank1,
+ dims1, options, np1, np2, mtype1_id, attr1_id, attr2_id);
+ print_found(nfound);
+ }
+ /* quiet mode (-q), just count differences */
+ else if(options->m_quiet) {
+ nfound = diff_array(buf1, buf2, nelmts1, (hsize_t) 0, rank1,
+ dims1, options, np1, np2, mtype1_id, attr1_id, attr2_id);
+ }
+ /* the rest (-c, none, ...) */
+ else {
+ nfound = diff_array(buf1, buf2, nelmts1, (hsize_t) 0, rank1,
+ dims1, options, np1, np2, mtype1_id, attr1_id, attr2_id);
+
+ /* print info if compatible and difference found */
+ if (nfound) {
+ do_print_attrname("attribute", np1, np2);
+ print_found(nfound);
+ } /* end if */
+ } /* end else */
+
+ /*----------------------------------------------------------------------
+ * close
+ *----------------------------------------------------------------------
+ */
+
+ /* Free buf1 and buf2, check both VLEN-data VLEN-string to reclaim any
+ * VLEN memory first */
+ if(TRUE == h5tools_detect_vlen(mtype1_id))
+ H5Dvlen_reclaim(mtype1_id, space1_id, H5P_DEFAULT, buf1);
+ HDfree(buf1);
+ buf1 = NULL;
+
+ if(TRUE == h5tools_detect_vlen(mtype2_id))
+ H5Dvlen_reclaim(mtype2_id, space2_id, H5P_DEFAULT, buf2);
+ HDfree(buf2);
+ buf2 = NULL;
+
+ if(H5Tclose(ftype1_id) < 0)
+ goto error;
+ if(H5Tclose(ftype2_id) < 0)
+ goto error;
+ if(H5Sclose(space1_id) < 0)
+ goto error;
+ if(H5Sclose(space2_id) < 0)
+ goto error;
+ if(H5Aclose(attr1_id) < 0)
+ goto error;
+ if(H5Aclose(attr2_id) < 0)
+ goto error;
+ if(H5Tclose(mtype1_id) < 0)
+ goto error;
+ if(H5Tclose(mtype2_id) < 0)
+ goto error;
+
+ nfound_total += nfound;
+ }
+ } /* u */
+
+ table_attrs_free(match_list_attrs);
+
+ return nfound_total;
+
+error:
+ H5E_BEGIN_TRY {
+ if(buf1) {
+ if(buf1hasdata && TRUE == h5tools_detect_vlen(mtype1_id))
+ H5Dvlen_reclaim(mtype1_id, space1_id, H5P_DEFAULT, buf1);
+ HDfree(buf1);
+ } /* end if */
+ if(buf2) {
+ if(buf2hasdata && TRUE == h5tools_detect_vlen(mtype2_id))
+ H5Dvlen_reclaim(mtype2_id, space2_id, H5P_DEFAULT, buf2);
+ HDfree(buf2);
+ } /* end if */
+
+ table_attrs_free(match_list_attrs);
+
+ H5Tclose(ftype1_id);
+ H5Tclose(ftype2_id);
+ H5Tclose(mtype1_id);
+ H5Tclose(mtype2_id);
+ H5Sclose(space1_id);
+ H5Sclose(space2_id);
+ H5Aclose(attr1_id);
+ H5Aclose(attr2_id);
+ } H5E_END_TRY;
+
+ options->err_stat = 1;
+ return nfound_total;
+}
+