00001 #include <stdio.h>
00002 #include <ctype.h>
00003 #include <string.h>
00004 #include <stdlib.h>
00005 #include <math.h>
00006
00007 #include "cgns_io.h"
00008 #include "getargs.h"
00009
00010 static int nocase = 0;
00011 static int nospace = 0;
00012 static int quiet = 0;
00013 static int follow_links = 0;
00014 static int recurse = 0;
00015 static int node_data = 0;
00016 static double tol = 0.0;
00017
00018 static int cgio1, cgio2;
00019
00020 static char options[] = "ciqrfdt:";
00021 static char *usgmsg[] = {
00022 "usage : cgnsdiff [options] CGNSfile1 [dataset1] CGNSfile2 [dataset2]",
00023 "options:",
00024 " -c : case insensitive names",
00025 " -i : ignore white space in names",
00026 " -q : print only if they differ",
00027 " -f : follow links",
00028 " -r : recurse (used only when dataset given)",
00029 " -d : compare node data also",
00030 " -t<tol> : tolerance for comparing floats/doubles (default 0)",
00031 NULL
00032 };
00033
00034 static void err_exit (char *msg, char *name)
00035 {
00036 char errmsg[128];
00037
00038 fflush (stdout);
00039 if (cgio_error_message (sizeof(errmsg), errmsg)) {
00040 if (msg != NULL)
00041 fprintf (stderr, "%s:", msg);
00042 if (name != NULL)
00043 fprintf (stderr, "%s:", name);
00044 fprintf (stderr, "%s\n", errmsg);
00045 }
00046 else {
00047 if (msg != NULL)
00048 fprintf (stderr, "%s", msg);
00049 if (name != NULL) {
00050 if (msg != NULL) putc (':', stderr);
00051 fprintf (stderr, "%s", name);
00052 }
00053 putc ('\n', stderr);
00054 }
00055 cgio_cleanup ();
00056 exit (1);
00057 }
00058
00059 static size_t data_size (char *type, int ndim, int *dims, int *size)
00060 {
00061 int n;
00062 size_t bytes;
00063
00064 *size = 0;
00065 if (ndim < 1) return 0;
00066 if (0 == strcmp (type, "C1") ||
00067 0 == strcmp (type, "B1"))
00068 bytes = sizeof(char);
00069 else if (0 == strcmp (type, "I4") ||
00070 0 == strcmp (type, "U4"))
00071 bytes = sizeof(int);
00072 else if (0 == strcmp (type, "I8") ||
00073 0 == strcmp (type, "U8"))
00074 bytes = sizeof(long);
00075 else if (0 == strcmp (type, "R4")) {
00076 *size = 4;
00077 bytes = sizeof(float);
00078 }
00079 else if (0 == strcmp (type, "R8")) {
00080 *size = 8;
00081 bytes = sizeof(double);
00082 }
00083 else if (0 == strcmp (type, "X4")) {
00084 *size = 4;
00085 bytes = 2 * sizeof(float);
00086 }
00087 else if (0 == strcmp (type, "X8")) {
00088 *size = 8;
00089 bytes = 2 * sizeof(double);
00090 }
00091 else
00092 return 0;
00093
00094 for (n = 0; n < ndim; n++)
00095 bytes *= (size_t)dims[n];
00096 return bytes;
00097 }
00098
00099 static int compare_bytes (size_t cnt, unsigned char *d1, unsigned char *d2)
00100 {
00101 size_t n;
00102
00103 for (n = 0; n < cnt; n++) {
00104 if (d1[n] != d2[n]) return 1;
00105 }
00106 return 0;
00107 }
00108
00109 static int compare_floats (size_t cnt, float *d1, float *d2)
00110 {
00111 size_t n;
00112
00113 for (n = 0; n < cnt; n++) {
00114 if (fabs(d1[n] - d2[n]) > tol) return 1;
00115 }
00116 return 0;
00117 }
00118
00119 static int compare_doubles (size_t cnt, double *d1, double *d2)
00120 {
00121 size_t n;
00122
00123 for (n = 0; n < cnt; n++) {
00124 if (fabs(d1[n] - d2[n]) > tol) return 1;
00125 }
00126 return 0;
00127 }
00128
00129 static void compare_data (char *name1, double id1, char *name2, double id2)
00130 {
00131 int n, err;
00132 size_t bytes;
00133 char label1[CGIO_MAX_NAME_LENGTH+1];
00134 char type1[CGIO_MAX_NAME_LENGTH+1];
00135 int ndim1, dims1[CGIO_MAX_DIMENSIONS];
00136 char label2[CGIO_MAX_NAME_LENGTH+1];
00137 char type2[CGIO_MAX_NAME_LENGTH+1];
00138 int ndim2, dims2[CGIO_MAX_DIMENSIONS];
00139 void *data1, *data2;
00140
00141
00142
00143 if (cgio_get_label (cgio1, id1, label1))
00144 err_exit (name1, "cgio_get_label");
00145 if (cgio_get_label (cgio2, id2, label2))
00146 err_exit (name2, "cgio_get_label");
00147 if (strcmp (label1, label2)) {
00148 printf ("%s <> %s : labels differ\n", name1, name2);
00149 return;
00150 }
00151
00152
00153
00154 if (cgio_get_data_type (cgio1, id1, type1))
00155 err_exit (name1, "cgio_get_data_type");
00156 if (cgio_get_data_type (cgio2, id2, type2))
00157 err_exit (name2, "cgio_get_data_type");
00158 if (strcmp (type1, type2)) {
00159 printf ("%s <> %s : data types differ\n", name1, name2);
00160 return;
00161 }
00162
00163
00164
00165 if (cgio_get_dimensions (cgio1, id1, &ndim1, dims1))
00166 err_exit (name1, "cgio_get_dimensions");
00167 if (cgio_get_dimensions (cgio2, id2, &ndim2, dims2))
00168 err_exit (name2, "cgio_get_dimensions");
00169 if (ndim1 != ndim2) {
00170 printf ("%s <> %s : number of dimensions differ\n", name1, name2);
00171 return;
00172 }
00173
00174
00175
00176 if (ndim1 > 0) {
00177 for (n = 0; n < ndim1; n++) {
00178 if (dims1[n] != dims2[n]) {
00179 printf ("%s <> %s : dimensions differ\n", name1, name2);
00180 return;
00181 }
00182 }
00183 }
00184
00185 if (!node_data || ndim1 <= 0) return;
00186
00187
00188
00189 bytes = data_size (type1, ndim1, dims1, &n);
00190 if (bytes > 0) {
00191 data1 = malloc (bytes);
00192 if (data1 == NULL) {
00193 fprintf (stderr, "%s:malloc failed for node data\n", name1);
00194 exit (1);
00195 }
00196 data2 = malloc (bytes);
00197 if (data2 == NULL) {
00198 fprintf (stderr, "%s:malloc failed for node data\n", name2);
00199 exit (1);
00200 }
00201 if (cgio_read_all_data (cgio1, id1, data1))
00202 err_exit (name1, "cgio_read_all_data");
00203 if (cgio_read_all_data (cgio2, id2, data2))
00204 err_exit (name2, "cgio_read_all_data");
00205 if (tol > 0.0 && n) {
00206 if (n == 4)
00207 err = compare_floats (bytes >> 2, data1, data2);
00208 else
00209 err = compare_doubles (bytes >> 3, data1, data2);
00210 }
00211 else {
00212 err = compare_bytes (bytes, (unsigned char *)data1,
00213 (unsigned char *)data2);
00214 }
00215 free (data1);
00216 free (data2);
00217 if (err)
00218 printf ("%s <> %s : data values differ\n", name1, name2);
00219 }
00220 }
00221
00222 static void copy_name (char *name, char *newname)
00223 {
00224 int n1, n2;
00225
00226 if (nospace) {
00227 if (nocase) {
00228 for (n1 = 0, n2 = 0; name[n1]; n1++) {
00229 if (!isspace (name[n1]))
00230 newname[n2++] = tolower (name[n1]);
00231 }
00232 }
00233 else {
00234 for (n1 = 0, n2 = 0; name[n1]; n1++) {
00235 if (!isspace (name[n1]))
00236 newname[n2++] = name[n1];
00237 }
00238 }
00239 newname[n2] = 0;
00240 }
00241 else if (nocase) {
00242 for (n1 = 0; name[n1]; n1++)
00243 newname[n1] = tolower (name[n1]);
00244 newname[n1] = 0;
00245 }
00246 else
00247 strcpy (newname, name);
00248 }
00249
00250 static int sort_children (const void *v1, const void *v2)
00251 {
00252 char p1[33], p2[33];
00253
00254 copy_name ((char *)v1, p1);
00255 copy_name ((char *)v2, p2);
00256 return strcmp (p1, p2);
00257 }
00258
00259 static int find_name (char *name, int nlist, char *namelist)
00260 {
00261 int cmp, mid, lo = 0, hi = nlist - 1;
00262 char p1[33], p2[33];
00263
00264 copy_name (name, p1);
00265 copy_name (namelist, p2);
00266 if (0 == strcmp (p1, p2)) return 0;
00267 copy_name (&namelist[33*hi], p2);
00268 if (0 == strcmp (p1, p2)) return hi;
00269
00270 while (lo <= hi) {
00271 mid = (lo + hi) >> 1;
00272 copy_name (&namelist[33*mid], p2);
00273 cmp = strcmp (p1, p2);
00274 if (0 == cmp) return mid;
00275 if (cmp > 0)
00276 lo = mid + 1;
00277 else
00278 hi = mid - 1;
00279 }
00280 return -1;
00281 }
00282
00283 static void compare_nodes (char *name1, double id1, char *name2, double id2)
00284 {
00285 int n1, n2, nc1, nc2, nret;
00286 char *p, *children1 = NULL, *children2 = NULL;
00287 char path1[1024], path2[1024];
00288 double cid1, cid2;
00289
00290 compare_data (name1, id1, name2, id2);
00291 if (!recurse) return;
00292 if (!follow_links) {
00293 if (cgio_is_link (cgio1, id1, &nret))
00294 err_exit (name1, "cgio_is_link");
00295 if (nret > 0) return;
00296 if (cgio_is_link (cgio2, id2, &nret))
00297 err_exit (name2, "cgio_is_link");
00298 if (nret > 0) return;
00299 }
00300
00301 if (cgio_number_children (cgio1, id1, &nc1))
00302 err_exit (name1, "cgio_number_children");
00303 if (nc1) {
00304 children1 = (char *) malloc (33 * nc1);
00305 if (children1 == NULL) {
00306 fprintf (stderr, "%s:malloc failed for children names\n", name1);
00307 exit (1);
00308 }
00309 if (cgio_children_names (cgio1, id1, 1, nc1, 33,
00310 &nret, children1))
00311 err_exit (name1, "cgio_children_names");
00312 if (nc1 > 1)
00313 qsort (children1, nc1, 33, sort_children);
00314 }
00315
00316 if (cgio_number_children (cgio2, id2, &nc2))
00317 err_exit (name2, "cgio_number_children");
00318 if (nc2) {
00319 children2 = (char *) malloc (33 * nc2);
00320 if (children2 == NULL) {
00321 fprintf (stderr, "%s:malloc failed for children names\n", name2);
00322 exit (1);
00323 }
00324 if (cgio_children_names (cgio2, id2, 1, nc2, 33,
00325 &nret, children2))
00326 err_exit (name2, "cgio_children_names");
00327 if (nc2 > 1)
00328 qsort (children2, nc2, 33, sort_children);
00329 }
00330
00331 if (0 == strcmp (name1, "/")) name1 = "";
00332 if (0 == strcmp (name2, "/")) name2 = "";
00333 if (nc1 == 0) {
00334 if (nc2 == 0) return;
00335 for (n2 = 0; n2 < nc2; n2++)
00336 printf ("> %s/%s\n", name2, &children2[33*n2]);
00337 free (children2);
00338 return;
00339 }
00340 if (nc2 == 0) {
00341 for (n1 = 0; n1 < nc1; n1++)
00342 printf ("< %s/%s\n", name1, &children1[33*n1]);
00343 free (children1);
00344 return;
00345 }
00346
00347 for (n1 = 0, n2 = 0; n1 < nc1; n1++) {
00348 p = &children1[33*n1];
00349 nret = find_name (p, nc2, children2);
00350 if (nret < 0) {
00351 printf ("< %s/%s\n", name1, p);
00352 continue;
00353 }
00354 while (n2 < nret) {
00355 printf ("> %s/%s\n", name2, &children2[33*n2]);
00356 n2++;
00357 }
00358 if (cgio_get_node_id (cgio1, id1, p, &cid1))
00359 err_exit (name1, "cgio_get_node_id");
00360 sprintf (path1, "%s/%s", name1, p);
00361 p = &children2[33*n2];
00362 if (cgio_get_node_id (cgio2, id2, p, &cid2))
00363 err_exit (name2, "cgio_get_node_id");
00364 sprintf (path2, "%s/%s", name2, p);
00365 compare_nodes (path1, cid1, path2, cid2);
00366 n2++;
00367 }
00368 while (n2 < nc2-1) {
00369 printf ("> %s/%s\n", name2, &children2[33*n2]);
00370 n2++;
00371 }
00372 free (children1);
00373 free (children2);
00374 }
00375
00376 int main (int argc, char *argv[])
00377 {
00378 double root1, root2;
00379 double node1, node2;
00380 int n;
00381 char *file1, *file2;
00382 char *ds1 = NULL;
00383 char *ds2 = NULL;
00384
00385 if (argc < 3)
00386 print_usage (usgmsg, NULL);
00387 while ((n = getargs (argc, argv, options)) > 0) {
00388 switch (n) {
00389 case 'c':
00390 nocase = 1;
00391 break;
00392 case 'i':
00393 nospace = 1;
00394 break;
00395 case 'q':
00396 quiet = 1;
00397 break;
00398 case 'f':
00399 follow_links = 1;
00400 break;
00401 case 'r':
00402 recurse = 1;
00403 break;
00404 case 'd':
00405 node_data = 1;
00406 break;
00407 case 't':
00408 tol = atof (argarg);
00409 break;
00410 }
00411 }
00412
00413 if (argind > argc - 2)
00414 print_usage (usgmsg, "CGNSfile1 and/or CGNSfile2 not given");
00415
00416 file1 = argv[argind++];
00417 if (cgio_open_file (file1, 'r', CGIO_FILE_NONE, &cgio1))
00418 err_exit (file1, "cgio_open_file");
00419 if (cgio_get_root_id (cgio1, &root1))
00420 err_exit (file1, "cgio_get_root_id");
00421 if (argind < argc - 1)
00422 ds1 = argv[argind++];
00423
00424 file2 = argv[argind++];
00425 if (cgio_open_file (file2, 'r', CGIO_FILE_NONE, &cgio2))
00426 err_exit (file2, "cgio_open_file");
00427 if (cgio_get_root_id (cgio2, &root2))
00428 err_exit (file2, "cgio_get_root_id");
00429 if (argind < argc)
00430 ds2 = argv[argind++];
00431
00432 if (ds1 == NULL) {
00433 recurse = 1;
00434 compare_nodes ("/", root1, "/", root2);
00435 }
00436 else {
00437 if (cgio_get_node_id (cgio1, root1, ds1, &node1))
00438 err_exit (ds1, "cgio_get_node_id");
00439 if (ds2 == NULL) ds2 = ds1;
00440 if (cgio_get_node_id (cgio2, root2, ds2, &node2))
00441 err_exit (ds2, "cgio_get_node_id");
00442 compare_nodes (ds1, node1, ds2, node2);
00443 }
00444
00445 cgio_close_file (cgio1);
00446 cgio_close_file (cgio2);
00447 return 0;
00448 }
00449