/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 "h5diff.h" #include #include /*------------------------------------------------------------------------- * Function: h5diff * * Purpose: public function, can be called in an applicattion program. * return differences between 2 HDF5 files * * Return: An exit status of 0 means no differences were found, 1 means some * differences were found. * * 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, options_t options) { int nobjects1, nobjects2; info_t *info1=NULL; info_t *info2=NULL; hid_t file1_id, file2_id; int nfound; /*------------------------------------------------------------------------- * 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: No such file or directory\n", fname1 ); exit(1); } if ((file2_id=H5Fopen(fname2,H5F_ACC_RDONLY,H5P_DEFAULT))<0 ) { printf("h5diff: %s: No such file or directory\n", fname2 ); exit(1); } /* enable error reporting */ } H5E_END_TRY; /*------------------------------------------------------------------------- * get the number of objects in the files *------------------------------------------------------------------------- */ nobjects1 = H5get_object_info( file1_id, NULL ); nobjects2 = H5get_object_info( file2_id, NULL ); /*------------------------------------------------------------------------- * get the list of objects in the files *------------------------------------------------------------------------- */ info1 = (info_t*) malloc( nobjects1 * sizeof(info_t)); info2 = (info_t*) malloc( nobjects2 * sizeof(info_t)); if (info1==NULL || info2==NULL) return 0; H5get_object_info( file1_id, info1 ); H5get_object_info( file2_id, info2 ); /*------------------------------------------------------------------------- * object name was supplied *------------------------------------------------------------------------- */ if ( objname1 ) { assert(objname2); nfound=compare(file1_id,fname1,objname1,nobjects1,info1, file2_id,fname2,objname2,nobjects2,info2,options); } /*------------------------------------------------------------------------- * compare all *------------------------------------------------------------------------- */ else { nfound=match(file1_id,nobjects1,info1, file2_id,nobjects2,info2,options); } info_free(info1,nobjects1); info_free(info2,nobjects2); /* close */ assert( (H5Fclose(file1_id)) >=0); assert( (H5Fclose(file2_id)) >=0); return nfound; } /*------------------------------------------------------------------------- * Function: 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 * * Comments: * * Modifications: * *------------------------------------------------------------------------- */ int match( hid_t file1_id, int nobjects1, info_t *info1, hid_t file2_id, int nobjects2, info_t *info2, options_t options ) { int cmp; int more_names_exist = (nobjects1>0 && nobjects2>0) ? 1 : 0; int curr1=0; int curr2=0; int i; /*build a common list */ table_t *table=NULL; unsigned infile[2]; char c1, c2; int nfound=0; /*------------------------------------------------------------------------- * build the list *------------------------------------------------------------------------- */ 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; table_add_flags(infile, info1[curr1].name, info1[curr1].type, table ); curr1++; curr2++; } else if ( cmp < 0 ) { infile[0]=1; infile[1]=0; table_add_flags(infile, info1[curr1].name, info1[curr1].type, table ); curr1++; } else { infile[0]=0; infile[1]=1; table_add_flags(infile, info2[curr2].name, info2[curr2].type, table ); curr2++; } more_names_exist = (curr1nobjs; 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].objname); } 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].objname, file2_id, table->objs[i].objname, options, table->objs[i].type ); } /* free table */ table_free(table); return nfound; } /*------------------------------------------------------------------------- * Function: compare * * Purpose: get objects form list, and check for the same type * * Return: Number of differences found * * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu * * Date: May 9, 2003 * * Comments: * * Modifications: * *------------------------------------------------------------------------- */ int compare( hid_t file1_id, const char *file1_name, const char *obj1_name, int nobjects1, info_t *info1, hid_t file2_id, const char *file2_name, const char *obj2_name, int nobjects2, info_t *info2, options_t options ) { int f1=0, f2=0; int nfound=0; int i = info_getindex( obj1_name, nobjects1, info1 ); int j = info_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 ) { printf("Comparison not supported\n"); printf("<%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 0; } 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 * * Return: Number of differences found * * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu * * Date: May 9, 2003 * * Comments: * * Modifications: * *------------------------------------------------------------------------- */ int diff( hid_t file1_id, const char *obj1_name, hid_t file2_id, const char *obj2_name, options_t options, int type ) { int nfound=0; switch ( type ) { case H5G_DATASET: nfound=diff_dataset(file1_id,file2_id,obj1_name,obj2_name,options); break; default: printf("Comparison not supported\n"); printf("<%s> is of type %s and <%s> is of type %s\n", obj1_name, get_type(type), obj2_name, get_type(type) ); break; } if (options.verbose) printf("\n"); return nfound; } /*------------------------------------------------------------------------- * Function: list * * Purpose: print list of objects in file * * Return: void * * Programmer: Pedro Vicente, pvn@ncsa.uiuc.edu * * Date: May 9, 2003 * * Comments: * * Modifications: * *------------------------------------------------------------------------- */ #ifdef NOT_YET void list( const char *filename, int nobjects, info_t *info ) { int i; printf("File <%s>: # of entries = %d\n", filename, nobjects ); for ( i = 0; i < nobjects; i++) { switch ( info[i].type ) { case H5G_GROUP: printf("%s %20s\n", info[i].name, "group" ); break; case H5G_DATASET: printf("%s %20s\n", info[i].name, "dataset" ); break; case H5G_TYPE: printf("%s %20s\n", info[i].name, "datatype" ); break; case H5G_LINK: printf("%s %20s\n", info[i].name, "link" ); break; default: printf("%s %20s\n", info[i].name, "User defined object" ); break; } } } #endif