summaryrefslogtreecommitdiffstats
path: root/tools/lib/h5diff.c
diff options
context:
space:
mode:
authorcvs2svn <no_author@cvs2svn>2004-04-20 00:19:46 (GMT)
committercvs2svn <no_author@cvs2svn>2004-04-20 00:19:46 (GMT)
commitbeb0079ae11d4932a1ce91545e49801ac206c75a (patch)
tree85b7e33258ef83d4dd9809f03a0cfb5477390720 /tools/lib/h5diff.c
parentc39de522e9559c382b7e705e7cb68fde263837b2 (diff)
downloadhdf5-beb0079ae11d4932a1ce91545e49801ac206c75a.zip
hdf5-beb0079ae11d4932a1ce91545e49801ac206c75a.tar.gz
hdf5-beb0079ae11d4932a1ce91545e49801ac206c75a.tar.bz2
[svn-r8396] This commit was manufactured by cvs2svn to create branch 'hdf5_1_6'.
Diffstat (limited to 'tools/lib/h5diff.c')
-rw-r--r--tools/lib/h5diff.c537
1 files changed, 537 insertions, 0 deletions
diff --git a/tools/lib/h5diff.c b/tools/lib/h5diff.c
new file mode 100644
index 0000000..9ac321b
--- /dev/null
+++ b/tools/lib/h5diff.c
@@ -0,0 +1,537 @@
+/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ * 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 files COPYING and Copyright.html. COPYING can be found at the root *
+ * of the source code distribution tree; Copyright.html can be found at the *
+ * root level of an installed copy of the electronic HDF5 document set and *
+ * is linked from the top-level documents page. It can also be found at *
+ * http://hdf.ncsa.uiuc.edu/HDF5/doc/Copyright.html. If you do not have *
+ * access to either file, you may request a copy from hdfhelp@ncsa.uiuc.edu. *
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+#include <stdlib.h>
+#include "h5diff.h"
+#include "H5private.h"
+
+/*-------------------------------------------------------------------------
+ * Function: h5diff
+ *
+ * Purpose: public function, can be called in an applicattion program.
+ * return differences between 2 HDF5 files
+ *
+ * Return: Number of differences found; -1 for error.
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: October 22, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+
+int h5diff(const char *fname1,
+ const char *fname2,
+ const char *objname1,
+ const char *objname2,
+ diff_opt_t *options)
+{
+ int nobjects1, nobjects2;
+ trav_info_t *info1=NULL;
+ trav_info_t *info2=NULL;
+ hid_t file1_id, file2_id;
+ int nfound=0;
+
+/*-------------------------------------------------------------------------
+ * open the files first; if they are not valid, no point in continuing
+ *-------------------------------------------------------------------------
+ */
+
+ /* disable error reporting */
+ H5E_BEGIN_TRY {
+
+ /* Open the files */
+ if ((file1_id=H5Fopen(fname1,H5F_ACC_RDONLY,H5P_DEFAULT))<0 )
+ {
+ printf("h5diff: <%s>: unable to open file\n", fname1 );
+ nfound = -1;
+ }
+ if ((file2_id=H5Fopen(fname2,H5F_ACC_RDONLY,H5P_DEFAULT))<0 )
+ {
+ printf("h5diff: <%s>: unable to open file\n", fname2 );
+ nfound = -1;
+ }
+ /* enable error reporting */
+ } H5E_END_TRY;
+ if (nfound<0)
+ return -1;
+
+/*-------------------------------------------------------------------------
+ * get the number of objects in the files
+ *-------------------------------------------------------------------------
+ */
+
+ nobjects1 = h5trav_getinfo( file1_id, NULL );
+ nobjects2 = h5trav_getinfo( file2_id, NULL );
+
+/*-------------------------------------------------------------------------
+ * get the list of objects in the files
+ *-------------------------------------------------------------------------
+ */
+
+ info1 = (trav_info_t*) malloc( nobjects1 * sizeof(trav_info_t));
+ info2 = (trav_info_t*) malloc( nobjects2 * sizeof(trav_info_t));
+ if (info1==NULL || info2==NULL)
+ {
+ nfound=-1;
+ goto out;
+ }
+
+ h5trav_getinfo( file1_id, info1 );
+ h5trav_getinfo( file2_id, info2 );
+
+/*-------------------------------------------------------------------------
+ * object name was supplied
+ *-------------------------------------------------------------------------
+ */
+
+ if ( objname1 )
+ {
+ assert(objname2);
+ nfound=diff_compare(file1_id,fname1,objname1,nobjects1,info1,
+ file2_id,fname2,objname2,nobjects2,info2,options);
+ }
+
+/*-------------------------------------------------------------------------
+ * compare all
+ *-------------------------------------------------------------------------
+ */
+
+ else
+ {
+ nfound=diff_match(file1_id,nobjects1,info1,
+ file2_id,nobjects2,info2,options);
+ }
+
+
+ h5trav_freeinfo(info1,nobjects1);
+ h5trav_freeinfo(info2,nobjects2);
+
+out:
+ /* close */
+ H5Fclose(file1_id);
+ H5Fclose(file2_id);
+
+ return nfound;
+
+
+}
+
+
+
+/*-------------------------------------------------------------------------
+ * Function: diff_match
+ *
+ * Purpose: Find common objects; the algorithm used for this search is the
+ * cosequential match algorithm and is described in
+ * Folk, Michael; Zoellick, Bill. (1992). File Structures. Addison-Wesley.
+ *
+ * Return: Number of differences found
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: May 9, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+int diff_match( hid_t file1_id,
+ int nobjects1,
+ trav_info_t *info1,
+ hid_t file2_id,
+ int nobjects2,
+ trav_info_t *info2,
+ diff_opt_t *options )
+{
+ int more_names_exist = (nobjects1>0 && nobjects2>0) ? 1 : 0;
+ trav_table_t *table=NULL;
+ int cmp;
+ int curr1=0;
+ int curr2=0;
+ unsigned infile[2];
+ char c1, c2;
+ int nfound=0, i;
+
+/*-------------------------------------------------------------------------
+ * build the list
+ *-------------------------------------------------------------------------
+ */
+ trav_table_init( &table );
+
+
+ while ( more_names_exist )
+ {
+ /* criteria is string compare */
+ cmp = strcmp( info1[curr1].name, info2[curr2].name );
+ if ( cmp == 0 )
+ {
+ infile[0]=1; infile[1]=1;
+ trav_table_addflags(infile, info1[curr1].name, info1[curr1].type, table );
+
+ curr1++;
+ curr2++;
+ }
+ else if ( cmp < 0 )
+ {
+ infile[0]=1; infile[1]=0;
+ trav_table_addflags(infile, info1[curr1].name, info1[curr1].type, table );
+ curr1++;
+ }
+ else
+ {
+ infile[0]=0; infile[1]=1;
+ trav_table_addflags(infile, info2[curr2].name, info2[curr2].type, table );
+ curr2++;
+ }
+
+ more_names_exist = (curr1<nobjects1 && curr2<nobjects2) ? 1 : 0;
+
+
+ } /* end while */
+
+ /* list1 did not end */
+ if (curr1<nobjects1)
+ {
+ while ( curr1<nobjects1 )
+ {
+ infile[0]=1; infile[1]=0;
+ trav_table_addflags(infile, info1[curr1].name, info1[curr1].type, table );
+ curr1++;
+ }
+ }
+
+ /* list2 did not end */
+ if (curr2<nobjects2)
+ {
+ while ( curr2<nobjects2 )
+ {
+ infile[0]=0; infile[1]=1;
+ trav_table_addflags(infile, info2[curr2].name, info2[curr2].type, table );
+ curr2++;
+ }
+ }
+
+/*-------------------------------------------------------------------------
+ * print the list
+ *-------------------------------------------------------------------------
+ */
+
+ if (options->verbose)
+ {
+ printf("\n");
+ printf("file1 file2\n");
+ printf("---------------------------------------\n");
+ for (i = 0; i < table->nobjs; i++)
+ {
+ c1 = (table->objs[i].flags[0]) ? 'x' : ' ';
+ c2 = (table->objs[i].flags[1]) ? 'x' : ' ';
+ printf("%5c %6c %-15s\n", c1, c2, table->objs[i].name);
+ }
+ printf("\n");
+ }
+
+
+/*-------------------------------------------------------------------------
+ * do the diff for common objects
+ *-------------------------------------------------------------------------
+ */
+
+ for (i = 0; i < table->nobjs; i++)
+ {
+ if ( table->objs[i].flags[0] && table->objs[i].flags[1] )
+ nfound+=diff( file1_id,
+ table->objs[i].name,
+ file2_id,
+ table->objs[i].name,
+ options,
+ table->objs[i].type );
+ }
+
+ /* free table */
+ trav_table_free(table);
+
+
+/*-------------------------------------------------------------------------
+ * do the diff for the root.
+ * this is a special case, we get an ID for the root group and call diff()
+ * with this ID; it compares only the root group attributes
+ *-------------------------------------------------------------------------
+ */
+
+ nfound+=diff( file1_id,
+ "/",
+ file2_id,
+ "/",
+ options,
+ H5G_GROUP );
+
+
+ return nfound;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: diff_compare
+ *
+ * Purpose: get objects from list, and check for the same type
+ *
+ * Return: Number of differences found
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: May 9, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+
+int diff_compare( hid_t file1_id,
+ const char *file1_name,
+ const char *obj1_name,
+ int nobjects1,
+ trav_info_t *info1,
+ hid_t file2_id,
+ const char *file2_name,
+ const char *obj2_name,
+ int nobjects2,
+ trav_info_t *info2,
+ diff_opt_t *options )
+{
+
+ int f1=0, f2=0;
+ int nfound=0;
+
+ int i = h5trav_getindex( obj1_name, nobjects1, info1 );
+ int j = h5trav_getindex( obj2_name, nobjects2, info2 );
+
+ if ( i == -1 )
+ {
+ printf( "Object <%s> could not be found in <%s>\n", obj1_name, file1_name );
+ f1=1;
+ }
+ if ( j == -1 )
+ {
+ printf( "Object <%s> could not be found in <%s>\n", obj2_name, file2_name );
+ f2=1;
+ }
+ if ( f1 || f2 )
+ return -1;
+
+ /* use the name with "/" first, as obtained by iterator function */
+ obj1_name=info1[i].name;
+ obj2_name=info2[j].name;
+
+ /* objects are not the same type */
+ if ( info1[i].type != info2[j].type && options->verbose)
+ {
+ printf("Comparison not possible: <%s> is of type %s and <%s> is of type %s\n",
+ obj1_name, get_type(info1[i].type),
+ obj2_name, get_type(info2[j].type) );
+ return 1;
+ }
+
+ nfound=diff( file1_id, obj1_name, file2_id, obj2_name, options, info1[i].type );
+
+ return nfound;
+}
+
+
+/*-------------------------------------------------------------------------
+ * Function: diff
+ *
+ * Purpose: switch between types and choose the diff function
+ * TYPE is either
+ * H5G_LINK Object is a symbolic link
+ * H5G_GROUP Object is a group
+ * H5G_DATASET Object is a dataset
+ * H5G_TYPE Object is a named data type
+ *
+ * Return: Number of differences found
+ *
+ * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu
+ *
+ * Date: May 9, 2003
+ *
+ *-------------------------------------------------------------------------
+ */
+
+int diff( hid_t file1_id,
+ const char *path1,
+ hid_t file2_id,
+ const char *path2,
+ diff_opt_t *options,
+ H5G_obj_t type )
+{
+ hid_t type1_id=-1;
+ hid_t type2_id=-1;
+ hid_t grp1_id=-1;
+ hid_t grp2_id=-1;
+ int ret;
+ H5G_stat_t sb1;
+ H5G_stat_t sb2;
+ char *buf1=NULL;
+ char *buf2=NULL;
+ int nfound=-1;
+
+ switch ( type )
+ {
+/*-------------------------------------------------------------------------
+ * H5G_DATASET
+ *-------------------------------------------------------------------------
+ */
+ case H5G_DATASET:
+ if (options->verbose)
+ printf( "Dataset: <%s> and <%s>\n",path1,path2);
+ nfound=diff_dataset(file1_id,file2_id,path1,path2,options);
+ break;
+
+/*-------------------------------------------------------------------------
+ * H5G_TYPE
+ *-------------------------------------------------------------------------
+ */
+ case H5G_TYPE:
+ if (options->verbose)
+ printf( "Datatype: <%s> and <%s>\n",path1,path2);
+
+ if ((type1_id = H5Topen(file1_id, path1))<0)
+ goto out;
+ if ((type2_id = H5Topen(file2_id, path2))<0)
+ goto out;
+
+ if ((ret = H5Tequal(type1_id,type2_id))<0)
+ goto out;
+
+ /* if H5Tequal is > 0 then the datatypes refer to the same datatype */
+ nfound = (ret>0) ? 0 : 1;
+
+/*-------------------------------------------------------------------------
+ * compare attributes
+ * the if condition refers to cases when the dataset is a referenced object
+ *-------------------------------------------------------------------------
+ */
+ if (path1)
+ nfound=diff_attr(type1_id,type2_id,path1,path2,options);
+
+ if ( H5Tclose(type1_id)<0)
+ goto out;
+ if ( H5Tclose(type2_id)<0)
+ goto out;
+
+ break;
+
+/*-------------------------------------------------------------------------
+ * H5G_GROUP
+ *-------------------------------------------------------------------------
+ */
+ case H5G_GROUP:
+ if (options->verbose)
+ printf( "Group: <%s> and <%s>\n",path1,path2);
+
+ if ((grp1_id = H5Gopen(file1_id, path1))<0)
+ goto out;
+ if ((grp2_id = H5Gopen(file2_id, path2))<0)
+ goto out;
+
+ ret = HDstrcmp(path1,path2);
+
+ /* if "path1" != "path2" then the groups are "different" */
+ nfound = (ret!=0) ? 1 : 0;
+
+ /*-------------------------------------------------------------------------
+ * compare attributes
+ * the if condition refers to cases when the dataset is a referenced object
+ *-------------------------------------------------------------------------
+ */
+ if (path1)
+ nfound=diff_attr(grp1_id,grp2_id,path1,path2,options);
+
+ if ( H5Gclose(grp1_id)<0)
+ goto out;
+ if ( H5Gclose(grp2_id)<0)
+ goto out;
+
+ break;
+
+
+/*-------------------------------------------------------------------------
+ * H5G_LINK
+ *-------------------------------------------------------------------------
+ */
+ case H5G_LINK:
+ if (options->verbose)
+ printf( "Link: <%s> and <%s>\n",path1,path2);
+
+ if (H5Gget_objinfo(file1_id,path1,FALSE,&sb1)<0)
+ goto out;
+ if (H5Gget_objinfo(file1_id,path1,FALSE,&sb2)<0)
+ goto out;
+
+ buf1 = malloc(sb1.linklen);
+ buf2 = malloc(sb2.linklen);
+
+ if (H5Gget_linkval(file1_id,path1,sb1.linklen,buf1)<0)
+ goto out;
+ if (H5Gget_linkval(file2_id,path2,sb1.linklen,buf2)<0)
+ goto out;
+
+ ret = HDstrcmp(buf1,buf2);
+
+ /* if "buf1" != "buf2" then the links are "different" */
+ nfound = (ret!=0) ? 1 : 0;
+
+ if (buf1) {
+ free(buf1);
+ buf1=NULL;
+ }
+
+ if (buf2) {
+ free(buf2);
+ buf2=NULL;
+ }
+
+ break;
+
+
+ default:
+ nfound=0;
+ if (options->verbose) {
+ printf("Comparison not supported: <%s> and <%s> are of type %s\n",
+ path1, path2, get_type(type) );
+ }
+ break;
+ }
+
+
+ out:
+
+ /* close */
+ /* disable error reporting */
+ H5E_BEGIN_TRY {
+ H5Tclose(type1_id);
+ H5Tclose(type2_id);
+ H5Gclose(grp1_id);
+ H5Tclose(grp2_id);
+ /* enable error reporting */
+ } H5E_END_TRY;
+
+ if (buf1)
+ free(buf1);
+ if (buf2)
+ free(buf2);
+
+ return nfound;
+}
+
+
+
+
+