SDDSlib
Loading...
Searching...
No Matches
sddsdiff.c File Reference

Compare two SDDS files. More...

#include "mdb.h"
#include "SDDS.h"
#include "scan.h"
#include "SDDSutils.h"
#include <float.h>

Go to the source code of this file.

Macros

#define SDDS_COLUMN_TYPE   0
 
#define SDDS_PARAMETER_TYPE   1
 
#define SDDS_ARRAY_TYPE   2
 
#define COMPARE_COMMON_COLUMN   0x0001U
 
#define COMPARE_COMMON_PARAMETER   0x0002U
 
#define COMPARE_COMMON_ARRAY   0x0004U
 

Enumerations

enum  option_type {
  CLO_COMPARECOMMON , CLO_COLUMNS , CLO_PARAMETERS , CLO_ARRAYS ,
  CLO_TOLERANCE , CLO_PRECISION , CLO_FORMAT , CLO_EXACT ,
  CLO_ABSOLUTE , CLO_ROWLABEL , CLO_IGNORE_UNITS , N_OPTIONS
}
 

Functions

long CompareDefinitions (SDDS_DATASET *dataset1, SDDS_DATASET *dataset2, char *file1, char *file2, int32_t *names, char ***name, int32_t **dataType, long type, long compareCommon, char *rowLabelColumn, long notCompareRowLabel, short ignoreUnits)
 
long CompareData (SDDS_DATASET *dataset1, SDDS_DATASET *dataset2, char *file1, char *file2, long names, char **name, int32_t *dataType, long type, long page, long double tolerance, long double precisionTolerance, char *floatFormat, char *doubleFormat, char *ldoubleFormat, char *stringFormat, long absolute, void *rowLabel, long rowLabelType, char *labelName)
 
long compare_two_data (void *data1, void *data2, long index, long datatype, long first, long flags, char *name, long page, long double tolerance, long double precisionTolerance, char *floatFormat, char *doubleFormat, char *ldoubleFormat, char *stringFormat, char *longFormat, char *ulongFormat, char *shortFormat, char *ushortFormat, char *charFormat, long absolute, long parameter, char *labelName)
 
void printTitle (long flags, char *name, long page, long absolute, char *labelName)
 
int main (int argc, char **argv)
 

Variables

char * option [N_OPTIONS]
 
char * USAGE1
 
char * USAGE2
 

Detailed Description

Compare two SDDS files.

This program compares two SDDS (Self Describing Data Sets) files by checking their definitions and data. It supports various options to customize the comparison, such as specifying which columns, parameters, or arrays to compare, setting tolerance levels for numerical comparisons, and more.

Usage

sddsdiff <file1> <file2> [options]

Options

-compareCommon[=column|parameter|array] -columns=<col1>[,<col2>...] -parameters=<par1>[,<par2>...] -arrays=<array1>[,<array2>...] -tolerance=

-precision=<integer> -format=float=<string>|double=<string>|longdouble=<string>|string=<string> -exact -absolute -rowlabel=<column-name>[,nocomparison] -ignoreUnits

License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
H. Shang, R. Soliday, L. Emery, M. Borland

Definition in file sddsdiff.c.

Macro Definition Documentation

◆ COMPARE_COMMON_ARRAY

#define COMPARE_COMMON_ARRAY   0x0004U

Definition at line 113 of file sddsdiff.c.

◆ COMPARE_COMMON_COLUMN

#define COMPARE_COMMON_COLUMN   0x0001U

Definition at line 111 of file sddsdiff.c.

◆ COMPARE_COMMON_PARAMETER

#define COMPARE_COMMON_PARAMETER   0x0002U

Definition at line 112 of file sddsdiff.c.

◆ SDDS_ARRAY_TYPE

#define SDDS_ARRAY_TYPE   2

Definition at line 102 of file sddsdiff.c.

◆ SDDS_COLUMN_TYPE

#define SDDS_COLUMN_TYPE   0

Definition at line 100 of file sddsdiff.c.

◆ SDDS_PARAMETER_TYPE

#define SDDS_PARAMETER_TYPE   1

Definition at line 101 of file sddsdiff.c.

Enumeration Type Documentation

◆ option_type

enum option_type

Definition at line 45 of file sddsdiff.c.

45 {
46 CLO_COMPARECOMMON,
47 CLO_COLUMNS,
48 CLO_PARAMETERS,
49 CLO_ARRAYS,
50 CLO_TOLERANCE,
51 CLO_PRECISION,
52 CLO_FORMAT,
53 CLO_EXACT,
54 CLO_ABSOLUTE,
55 CLO_ROWLABEL,
56 CLO_IGNORE_UNITS,
57 N_OPTIONS
58};

Function Documentation

◆ compare_two_data()

long compare_two_data ( void * data1,
void * data2,
long index,
long datatype,
long first,
long flags,
char * name,
long page,
long double tolerance,
long double precisionTolerance,
char * floatFormat,
char * doubleFormat,
char * ldoubleFormat,
char * stringFormat,
char * longFormat,
char * ulongFormat,
char * shortFormat,
char * ushortFormat,
char * charFormat,
long absolute,
long parameter,
char * labelName )

Definition at line 904 of file sddsdiff.c.

910 {
911 char *str1, *str2;
912 long double ldval1, ldval2, ldenominator, ldabs1, ldabs2, lddiff;
913 double dval1, dval2, denominator, dabs1, dabs2, ddiff;
914 float fval1, fval2, fabs1, fabs2, fdenominator, fdiff;
915 int32_t lval1, lval2, labs1, labs2, ldiff, uldiff;
916 uint32_t ulval1, ulval2;
917 int64_t llval1, llval2, llabs1, llabs2, lldiff, ulldiff;
918 uint64_t ullval1, ullval2;
919 short sval1, sval2, sabs1, sabs2, sdiff, usdiff;
920 unsigned short usval1, usval2;
921 char cval1, cval2;
922 long returnValue = 0, printIndex;
923 long double tol;
924
925 printIndex = index + 1;
926 if (parameter)
927 printIndex = page;
928
929 if (tolerance < 0)
930 tol = 0L;
931 else
932 tol = tolerance;
933
934 switch (datatype) {
935 case SDDS_STRING:
936 str1 = *((char **)data1 + index);
937 str2 = *((char **)data2 + index);
938 returnValue = strcmp(trim_spaces(str1), trim_spaces(str2));
939 if (returnValue != 0) {
940 if (first)
941 printTitle(flags, name, page, absolute, labelName);
942 if (labelName) {
943 fprintf(stdout, stringFormat, str1, str2, returnValue);
944 } else
945 fprintf(stdout, stringFormat, printIndex, str1, str2, returnValue);
946 }
947 break;
948 case SDDS_LONGDOUBLE:
949 ldval1 = *((long double *)data1 + index);
950 ldval2 = *((long double *)data2 + index);
951 if (absolute) {
952 ldabs1 = fabsl(ldval1);
953 ldabs2 = fabsl(ldval2);
954 } else {
955 ldabs1 = ldval1;
956 ldabs2 = ldval2;
957 }
958 lddiff = ldabs1 - ldabs2;
959 if ((isnan(ldval1) && !isnan(ldval2)) || (isinf(ldval1) && !isinf(ldval2)))
960 returnValue = 1;
961 else if (ldabs1 != ldabs2) {
962 if (tolerance) {
963 if (fabsl(lddiff) > tol)
964 returnValue = 1;
965 } else {
966 if (ldabs1 == 0L || ldabs2 == 0L) {
967 if (fabsl(ldabs1 - ldabs2) > precisionTolerance)
968 returnValue = 1;
969 } else {
970 ldabs1 = fabsl(ldval1);
971 ldabs2 = fabsl(ldval2);
972 ldenominator = (ldabs1 < ldabs2) ? ldabs1 : ldabs2;
973 if (fabsl(ldval1 - ldval2) / ldenominator > precisionTolerance)
974 returnValue = 1;
975 }
976 }
977 }
978 if (returnValue) {
979 if (first)
980 printTitle(flags, name, page, absolute, labelName);
981 if (labelName)
982 fprintf(stdout, ldoubleFormat, ldval1, ldval2, lddiff);
983 else
984 fprintf(stdout, ldoubleFormat, printIndex, ldval1, ldval2, lddiff);
985 }
986 break;
987 case SDDS_DOUBLE:
988 dval1 = *((double *)data1 + index);
989 dval2 = *((double *)data2 + index);
990 if (absolute) {
991 dabs1 = fabs(dval1);
992 dabs2 = fabs(dval2);
993 } else {
994 dabs1 = dval1;
995 dabs2 = dval2;
996 }
997 ddiff = dabs1 - dabs2;
998 if ((isnan(dval1) && !isnan(dval2)) || (isinf(dval1) && !isinf(dval2)))
999 returnValue = 1;
1000 else if (dabs1 != dabs2) {
1001 if (tolerance) {
1002 if (fabs(ddiff) > tol)
1003 returnValue = 1;
1004 } else {
1005 if (dabs1 == 0 || dabs2 == 0) {
1006 if (fabs(dabs1 - dabs2) > precisionTolerance)
1007 returnValue = 1;
1008 } else {
1009 dabs1 = fabs(dval1);
1010 dabs2 = fabs(dval2);
1011 denominator = (dabs1 < dabs2) ? dabs1 : dabs2;
1012 if (fabs(dval1 - dval2) / denominator > precisionTolerance)
1013 returnValue = 1;
1014 }
1015 }
1016 }
1017 if (returnValue) {
1018 if (first)
1019 printTitle(flags, name, page, absolute, labelName);
1020 if (labelName)
1021 fprintf(stdout, doubleFormat, dval1, dval2, ddiff);
1022 else
1023 fprintf(stdout, doubleFormat, printIndex, dval1, dval2, ddiff);
1024 }
1025 break;
1026 case SDDS_FLOAT:
1027 fval1 = *((float *)data1 + index);
1028 fval2 = *((float *)data2 + index);
1029 if (absolute) {
1030 fabs1 = fabs(fval1);
1031 fabs2 = fabs(fval2);
1032 } else {
1033 fabs1 = fval1;
1034 fabs2 = fval2;
1035 }
1036 fdiff = fabs1 - fabs2;
1037 if ((isnan(fval1) && !isnan(fval2)) || (isinf(fval1) && !isinf(fval2)))
1038 returnValue = 1;
1039 else if (fabs1 != fabs2) {
1040 if (tolerance) {
1041 if (fabs(fdiff) > tol)
1042 returnValue = 1;
1043 } else {
1044 if (fabs1 == 0 || fabs2 == 0) {
1045 if (fabs(fabs1 - fabs2) > precisionTolerance)
1046 returnValue = 1;
1047 } else {
1048 fabs1 = fabs(fval1);
1049 fabs2 = fabs(fval2);
1050 fdenominator = (fabs1 < fabs2) ? fabs1 : fabs2;
1051 if (fabs(fval1 - fval2) / fdenominator > precisionTolerance)
1052 returnValue = 1;
1053 }
1054 }
1055 }
1056 if (returnValue) {
1057 if (first)
1058 printTitle(flags, name, page, absolute, labelName);
1059 if (labelName)
1060 fprintf(stdout, floatFormat, fval1, fval2, fdiff);
1061 else
1062 fprintf(stdout, floatFormat, printIndex, fval1, fval2, fdiff);
1063 }
1064 break;
1065 case SDDS_ULONG64:
1066 ullval1 = *((uint64_t *)data1 + index);
1067 ullval2 = *((uint64_t *)data2 + index);
1068 ulldiff = ullval1 - ullval2;
1069 if (labs(ulldiff) > tol)
1070 returnValue = 1;
1071 if (returnValue) {
1072 if (first)
1073 printTitle(flags, name, page, absolute, labelName);
1074 if (labelName)
1075 fprintf(stdout, ulongFormat, ullval1, ullval2, ulldiff);
1076 else
1077 fprintf(stdout, ulongFormat, printIndex, ullval1, ullval2, ulldiff);
1078 }
1079 break;
1080 case SDDS_LONG64:
1081 llval1 = *((int64_t *)data1 + index);
1082 llval2 = *((int64_t *)data2 + index);
1083 if (absolute) {
1084 llabs1 = labs(llval1);
1085 llabs2 = labs(llval2);
1086 } else {
1087 llabs1 = llval1;
1088 llabs2 = llval2;
1089 }
1090 lldiff = llabs1 - llabs2;
1091 if (llabs(lldiff) > tol)
1092 returnValue = 1;
1093 if (returnValue) {
1094 if (first)
1095 printTitle(flags, name, page, absolute, labelName);
1096 if (labelName)
1097 fprintf(stdout, longFormat, llval1, llval2, lldiff);
1098 else
1099 fprintf(stdout, longFormat, printIndex, llval1, llval2, lldiff);
1100 }
1101 break;
1102 case SDDS_ULONG:
1103 ulval1 = *((uint32_t *)data1 + index);
1104 ulval2 = *((uint32_t *)data2 + index);
1105 uldiff = ulval1 - ulval2;
1106 if (labs(uldiff) > tol)
1107 returnValue = 1;
1108 if (returnValue) {
1109 if (first)
1110 printTitle(flags, name, page, absolute, labelName);
1111 if (labelName)
1112 fprintf(stdout, ulongFormat, ulval1, ulval2, uldiff);
1113 else
1114 fprintf(stdout, ulongFormat, printIndex, ulval1, ulval2, uldiff);
1115 }
1116 break;
1117 case SDDS_LONG:
1118 lval1 = *((int32_t *)data1 + index);
1119 lval2 = *((int32_t *)data2 + index);
1120 if (absolute) {
1121 labs1 = abs(lval1);
1122 labs2 = abs(lval2);
1123 } else {
1124 labs1 = lval1;
1125 labs2 = lval2;
1126 }
1127 ldiff = labs1 - labs2;
1128 if (labs(ldiff) > tol)
1129 returnValue = 1;
1130 if (returnValue) {
1131 if (first)
1132 printTitle(flags, name, page, absolute, labelName);
1133 if (labelName)
1134 fprintf(stdout, longFormat, lval1, lval2, ldiff);
1135 else
1136 fprintf(stdout, longFormat, printIndex, lval1, lval2, ldiff);
1137 }
1138 break;
1139 case SDDS_SHORT:
1140 sval1 = *((short *)data1 + index);
1141 sval2 = *((short *)data2 + index);
1142 if (absolute) {
1143 sabs1 = abs(sval1);
1144 sabs2 = abs(sval2);
1145 } else {
1146 sabs1 = sval1;
1147 sabs2 = sval2;
1148 }
1149 sdiff = sabs1 - sabs2;
1150 if (abs(sdiff) > tol)
1151 returnValue = 1;
1152 if (returnValue) {
1153 if (first)
1154 printTitle(flags, name, page, absolute, labelName);
1155 if (labelName)
1156 fprintf(stdout, shortFormat, sval1, sval2, sdiff);
1157 else
1158 fprintf(stdout, shortFormat, printIndex, sval1, sval2, sdiff);
1159 }
1160 break;
1161 case SDDS_USHORT:
1162 usval1 = *((unsigned short *)data1 + index);
1163 usval2 = *((unsigned short *)data2 + index);
1164 usdiff = usval1 - usval2;
1165 if (abs(usdiff) > tol)
1166 returnValue = 1;
1167 if (returnValue) {
1168 if (first)
1169 printTitle(flags, name, page, absolute, labelName);
1170 if (labelName)
1171 fprintf(stdout, ushortFormat, usval1, usval2, usdiff);
1172 else
1173 fprintf(stdout, ushortFormat, printIndex, usval1, usval2, usdiff);
1174 }
1175 break;
1176 case SDDS_CHARACTER:
1177 cval1 = *((char *)data1 + index);
1178 cval2 = *((char *)data2 + index);
1179 if (cval1 != cval2) {
1180 returnValue = 1;
1181 if (first)
1182 printTitle(flags, name, page, absolute, labelName);
1183 if (labelName)
1184 fprintf(stdout, charFormat, cval1, cval2, cval1 - cval2);
1185 else
1186 fprintf(stdout, charFormat, printIndex, cval1, cval2, cval1 - cval2);
1187 }
1188 break;
1189 default:
1190 fprintf(stderr, "Unknown data type %ld.\n", datatype);
1191 exit(EXIT_FAILURE);
1192 }
1193 return returnValue;
1194}
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
Definition SDDStypes.h:67
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
Definition SDDStypes.h:31
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49
char * trim_spaces(char *s)
Trims leading and trailing spaces from a string.
Definition trim_spaces.c:28

◆ CompareData()

long CompareData ( SDDS_DATASET * dataset1,
SDDS_DATASET * dataset2,
char * file1,
char * file2,
long names,
char ** name,
int32_t * dataType,
long type,
long page,
long double tolerance,
long double precisionTolerance,
char * floatFormat,
char * doubleFormat,
char * ldoubleFormat,
char * stringFormat,
long absolute,
void * rowLabel,
long rowLabelType,
char * labelName )

Definition at line 723 of file sddsdiff.c.

726 {
727 long diff = 0, i, first = 1;
728 int64_t rows, j;
729 char fFormat[2048], dFormat[2048], ldFormat[2048], strFormat[2048], lFormat[2048], ulFormat[2048], ushortFormat[2048], shortFormat[2048], cFormat[2048], labelFormat[1024];
730 SDDS_ARRAY *array1, *array2;
731 void *data1, *data2;
732
733 array1 = array2 = NULL;
734 data1 = data2 = NULL;
735
736 if (!rowLabel) {
737 snprintf(fFormat, sizeof(fFormat), "%%20ld%s%s%s\n", floatFormat, floatFormat, floatFormat);
738 snprintf(dFormat, sizeof(dFormat), "%%20ld%s%s%s\n", doubleFormat, doubleFormat, doubleFormat);
739 snprintf(ldFormat, sizeof(ldFormat), "%%20ld%s%s%s\n", ldoubleFormat, ldoubleFormat, ldoubleFormat);
740 snprintf(strFormat, sizeof(strFormat), "%%20ld%s%s%%25ld\n", stringFormat, stringFormat);
741 snprintf(lFormat, sizeof(lFormat), "%s", "%20ld%25ld%25ld\n");
742 snprintf(ulFormat, sizeof(ulFormat), "%s", "%20ld%25lu%25lu%25ld\n");
743 snprintf(shortFormat, sizeof(shortFormat), "%s", "%20ld%25hd%25hd%25hd\n");
744 snprintf(ushortFormat, sizeof(ushortFormat), "%s", "%20ld%25hu%25hu%25hd\n");
745 snprintf(cFormat, sizeof(cFormat), "%s", "%20ld%25c%25c%25d\n");
746 }
747 switch (type) {
748 case SDDS_COLUMN_TYPE:
749 rows = SDDS_CountRowsOfInterest(dataset1);
750 if (!rows)
751 break;
752 for (i = 0; i < names; i++) {
753 first = 1;
754 if (!(data1 = SDDS_GetColumn(dataset1, name[i])) || !(data2 = SDDS_GetColumn(dataset2, name[i]))) {
755 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
756 exit(EXIT_FAILURE);
757 }
758 for (j = 0; j < rows; j++) {
759 if (rowLabel) {
760 switch (rowLabelType) {
761 case SDDS_STRING:
762 snprintf(labelFormat, sizeof(labelFormat), "%20s", ((char **)rowLabel)[j]);
763 break;
764 case SDDS_LONGDOUBLE:
765 snprintf(labelFormat, sizeof(labelFormat), "%20.15Le", ((long double *)rowLabel)[j]);
766 break;
767 case SDDS_DOUBLE:
768 snprintf(labelFormat, sizeof(labelFormat), "%20.10e", ((double *)rowLabel)[j]);
769 break;
770 case SDDS_FLOAT:
771 snprintf(labelFormat, sizeof(labelFormat), "%20.5e", ((float *)rowLabel)[j]);
772 break;
773 case SDDS_ULONG64:
774 snprintf(labelFormat, sizeof(labelFormat), "%20" PRIu64, ((uint64_t *)rowLabel)[j]);
775 break;
776 case SDDS_LONG64:
777 snprintf(labelFormat, sizeof(labelFormat), "%20" PRId64, ((int64_t *)rowLabel)[j]);
778 break;
779 case SDDS_ULONG:
780 snprintf(labelFormat, sizeof(labelFormat), "%20" PRIu32, ((uint32_t *)rowLabel)[j]);
781 break;
782 case SDDS_LONG:
783 snprintf(labelFormat, sizeof(labelFormat), "%20" PRId32, ((int32_t *)rowLabel)[j]);
784 break;
785 case SDDS_USHORT:
786 snprintf(labelFormat, sizeof(labelFormat), "%20hu", ((unsigned short *)rowLabel)[j]);
787 break;
788 case SDDS_SHORT:
789 snprintf(labelFormat, sizeof(labelFormat), "%20hd", ((short *)rowLabel)[j]);
790 break;
791 case SDDS_CHARACTER:
792 snprintf(labelFormat, sizeof(labelFormat), "%20c", ((char *)rowLabel)[j]);
793 break;
794 default:
795 fprintf(stderr, "Unknown data type for rowlabel.\n");
796 exit(EXIT_FAILURE);
797 }
798 snprintf(fFormat, sizeof(fFormat), "%s%s%s%s\n", labelFormat, floatFormat, floatFormat, floatFormat);
799 snprintf(dFormat, sizeof(dFormat), "%s%s%s%s\n", labelFormat, doubleFormat, doubleFormat, doubleFormat);
800 snprintf(ldFormat, sizeof(ldFormat), "%s%s%s%s\n", labelFormat, ldoubleFormat, ldoubleFormat, ldoubleFormat);
801 snprintf(strFormat, sizeof(strFormat), "%s%s%s%%25ld\n", labelFormat, stringFormat, stringFormat);
802 snprintf(lFormat, sizeof(lFormat), "%s%%25ld%%25ld%%25ld\n", labelFormat);
803 snprintf(ulFormat, sizeof(ulFormat), "%s%%25lu%%25lu%%25ld\n", labelFormat);
804 snprintf(shortFormat, sizeof(shortFormat), "%s%%25hd%%25hd%%25hd\n", labelFormat);
805 snprintf(ushortFormat, sizeof(ushortFormat), "%s%%25hu%%25hu%%25hd\n", labelFormat);
806 snprintf(cFormat, sizeof(cFormat), "%s%%25c%%25c%%25d\n", labelFormat);
807 }
808 if (compare_two_data(data1, data2, j, dataType[i], first, SDDS_COLUMN_TYPE, name[i], page, tolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 0, rowLabelColumn) != 0) {
809 diff++;
810 if (first)
811 first = 0;
812 }
813 if (dataType[i] == SDDS_STRING) {
814 free((char *)((char **)data1)[j]);
815 free((char *)((char **)data2)[j]);
816 }
817 }
818 free((char **)data1);
819 free((char **)data2);
820 data1 = data2 = NULL;
821 }
822 break;
823 case SDDS_PARAMETER_TYPE:
824 for (i = 0; i < names; i++) {
825 first = 1;
826 if (!(data1 = SDDS_GetParameter(dataset1, name[i], NULL)) || !(data2 = SDDS_GetParameter(dataset2, name[i], NULL))) {
827 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
828 exit(EXIT_FAILURE);
829 }
830 if (compare_two_data(data1, data2, 0, dataType[i], first, SDDS_PARAMETER_TYPE, name[i], page, tolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 1, NULL) != 0) {
831 diff++;
832 if (first)
833 first = 0;
834 }
835 if (dataType[i] == SDDS_STRING) {
836 free(*((char **)data1));
837 free(*((char **)data2));
838 }
839 free(data1);
840 free(data2);
841 data1 = data2 = NULL;
842 }
843 break;
844 case SDDS_ARRAY_TYPE:
845 for (i = 0; i < names; i++) {
846 first = 1;
847 if (!(array1 = SDDS_GetArray(dataset1, name[i], NULL)) || !(array2 = SDDS_GetArray(dataset2, name[i], NULL))) {
848 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
849 exit(EXIT_FAILURE);
850 }
851 if (array1->elements != array2->elements) {
852 fprintf(stderr, "Array \"%s\" has %" PRId32 " elements in \"%s\", but %" PRId32 " elements in \"%s\".\n", name[i], array1->elements, file1, array2->elements, file2);
853 diff++;
854 } else {
855 for (j = 0; j < array1->elements; j++) {
856 if (compare_two_data(array1->data, array2->data, j, dataType[i], first, SDDS_ARRAY_TYPE, name[i], page, tolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 0, NULL) != 0) {
857 diff++;
858 if (first)
859 first = 0;
860 }
861 }
862 }
863 SDDS_FreeArray(array1);
864 SDDS_FreeArray(array2);
865 array1 = array2 = NULL;
866 }
867 break;
868 }
869 return diff;
870}
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
SDDS_ARRAY * SDDS_GetArray(SDDS_DATASET *SDDS_dataset, char *array_name, SDDS_ARRAY *memory)
Retrieves an array from the current data table of an SDDS dataset.
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
void SDDS_FreeArray(SDDS_ARRAY *array)
Frees memory allocated for an SDDS array structure.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432

◆ CompareDefinitions()

long CompareDefinitions ( SDDS_DATASET * dataset1,
SDDS_DATASET * dataset2,
char * file1,
char * file2,
int32_t * names,
char *** name,
int32_t ** dataType,
long type,
long compareCommon,
char * rowLabelColumn,
long notCompareRowLabel,
short ignoreUnits )

Definition at line 442 of file sddsdiff.c.

442 {
443 size_t same_items;
444 long sames, free_same_name = 0;
445 int32_t *same, *datatype;
446 int32_t names1, names2;
447 char **name1, **name2, *def, **same_name;
448 long type1, type2, i, returnValue = 0, first = 1;
449 int32_t index1, index2;
450 char *units1, *units2;
451 units1 = units2 = NULL;
452 name1 = name2 = same_name = NULL;
453 names1 = names2 = 0;
454 def = NULL;
455 same_items = 0;
456 same = datatype = NULL;
457
458 type1 = type2 = -1;
459
460 switch (type) {
461 case SDDS_COLUMN_TYPE:
462 name1 = SDDS_GetColumnNames(dataset1, &names1);
463 name2 = SDDS_GetColumnNames(dataset2, &names2);
464 SDDS_CopyString(&def, "column");
465 break;
466 case SDDS_PARAMETER_TYPE:
467 name1 = SDDS_GetParameterNames(dataset1, &names1);
468 name2 = SDDS_GetParameterNames(dataset2, &names2);
469 SDDS_CopyString(&def, "parameter");
470 break;
471 case SDDS_ARRAY_TYPE:
472 name1 = SDDS_GetArrayNames(dataset1, &names1);
473 name2 = SDDS_GetArrayNames(dataset2, &names2);
474 SDDS_CopyString(&def, "array");
475 break;
476 default:
477 fprintf(stderr, "Unknown type given for CompareDefinitions().\n");
478 return 1;
479 }
480 if (names1 == 0 && names2 == 0)
481 return 0;
482 if (*names) {
483 if (!names1 || !names2) {
484 fprintf(stderr, "Error: One of the files does not have any %s.\n", def);
485 returnValue = 1;
486 }
487 if (!returnValue) {
488 for (i = 0; i < *names; i++) {
489 if (rowLabelColumn && notCompareRowLabel && strcmp((*name)[i], rowLabelColumn) == 0)
490 continue;
491 if (-1 == match_string((*name)[i], name1, names1, EXACT_MATCH)) {
492 fprintf(stderr, "Error: File \"%s\" does not have %s \"%s\".\n", file1, def, (*name)[i]);
493 returnValue = 1;
494 break;
495 }
496 if (-1 == match_string((*name)[i], name2, names2, EXACT_MATCH)) {
497 fprintf(stderr, "Error: File \"%s\" does not have %s \"%s\".\n", file2, def, (*name)[i]);
498 returnValue = 1;
499 break;
500 }
501 }
502 }
503 if (returnValue) {
504 for (i = 0; i < names1; i++)
505 free(name1[i]);
506 free(name1);
507 for (i = 0; i < names2; i++)
508 free(name2[i]);
509 free(name2);
510 free(def);
511 return returnValue;
512 }
513 same_items = *names;
514 same_name = *name;
515 compareCommon = 0;
516 } else {
517 if (!names1 && !names2) {
518 free(def);
519 return 0;
520 }
521 if (compareCommon && (!names1 || !names2)) {
522 if (names1) {
523 for (i = 0; i < names1; i++)
524 free(name1[i]);
525 free(name1);
526 }
527 if (names2) {
528 for (i = 0; i < names2; i++)
529 free(name2[i]);
530 free(name2);
531 }
532 *names = 0;
533 return 0;
534 }
535 if (names1 != names2 && !compareCommon && !notCompareRowLabel)
536 returnValue = 1;
537 if (returnValue) {
538 fprintf(stderr, "Error: Two files have different numbers of %ss:\n \"%s\" has %" PRId32 " %ss while \"%s\" has %" PRId32 " %ss.\n", def, file1, names1, def, file2, names2, def);
539 for (i = 0; i < names2; i++)
540 free(name2[i]);
541 free(name2);
542 for (i = 0; i < names1; i++)
543 free(name1[i]);
544 free(name1);
545 free(def);
546 return returnValue;
547 }
548 same_items = 0;
549 for (i = 0; i < names1; i++) {
550 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name1[i]) == 0)
551 continue;
552 if (-1 == match_string(name1[i], name2, names2, EXACT_MATCH)) {
553 if (!compareCommon) {
554 if (first) {
555 fprintf(stderr, " Following %ss of \"%s\" are not in \"%s\":\n", def, file1, file2);
556 first = 0;
557 }
558 fprintf(stderr, " %s\n", name1[i]);
559 returnValue++;
560 }
561 } else {
562 same_name = (char **)SDDS_Realloc(same_name, sizeof(*same_name) * (same_items + 1));
563 same_name[same_items] = name1[i];
564 same_items++;
565 }
566 }
567 if (!compareCommon) {
568 if (!first)
569 fprintf(stderr, "\n");
570 first = 1;
571 for (i = 0; i < names2; i++) {
572 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name2[i]) == 0)
573 continue;
574 if (-1 == match_string(name2[i], name1, names1, EXACT_MATCH)) {
575 if (first) {
576 fprintf(stderr, " Following %ss of \"%s\" are not in \"%s\":\n", def, file2, file1);
577 first = 0;
578 }
579 fprintf(stderr, " %s\n", name2[i]);
580 returnValue++;
581 }
582 }
583 if (!first)
584 fprintf(stderr, "\n");
585 }
586 if (same_items)
587 free_same_name = 1;
588 }
589 sames = same_items;
590 if (same_items) {
591 datatype = (int32_t *)malloc(sizeof(*datatype) * same_items);
592 same = (int32_t *)malloc(sizeof(*same) * same_items);
593 /* Check the units and type */
594 for (i = 0; i < same_items; i++) {
595 same[i] = 1;
596 switch (type) {
597 case SDDS_COLUMN_TYPE:
598 index1 = SDDS_GetColumnIndex(dataset1, same_name[i]);
599 index2 = SDDS_GetColumnIndex(dataset2, same_name[i]);
600 type1 = SDDS_GetColumnType(dataset1, index1);
601 type2 = SDDS_GetColumnType(dataset2, index2);
602 if (!ignoreUnits) {
603 if (SDDS_GetColumnInformation(dataset1, "units", &units1, SDDS_GET_BY_INDEX, index1) != SDDS_STRING) {
604 SDDS_SetError("Units field of column has wrong data type!");
605 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
606 exit(EXIT_FAILURE);
607 }
608 if (SDDS_GetColumnInformation(dataset2, "units", &units2, SDDS_GET_BY_INDEX, index2) != SDDS_STRING) {
609 SDDS_SetError("Units field of column has wrong data type!");
610 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
611 exit(EXIT_FAILURE);
612 }
613 }
614 break;
615 case SDDS_PARAMETER_TYPE:
616 index1 = SDDS_GetParameterIndex(dataset1, same_name[i]);
617 index2 = SDDS_GetParameterIndex(dataset2, same_name[i]);
618 type1 = SDDS_GetParameterType(dataset1, index1);
619 type2 = SDDS_GetParameterType(dataset2, index2);
620 if (!ignoreUnits) {
621 if (SDDS_GetParameterInformation(dataset1, "units", &units1, SDDS_GET_BY_INDEX, index1) != SDDS_STRING) {
622 SDDS_SetError("Units field of parameter has wrong data type!");
623 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
624 exit(EXIT_FAILURE);
625 }
626 if (SDDS_GetParameterInformation(dataset2, "units", &units2, SDDS_GET_BY_INDEX, index2) != SDDS_STRING) {
627 SDDS_SetError("Units field of parameter has wrong data type!");
628 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
629 exit(EXIT_FAILURE);
630 }
631 }
632 break;
633 case SDDS_ARRAY_TYPE:
634 index1 = SDDS_GetArrayIndex(dataset1, same_name[i]);
635 index2 = SDDS_GetArrayIndex(dataset2, same_name[i]);
636 type1 = SDDS_GetArrayType(dataset1, index1);
637 type2 = SDDS_GetArrayType(dataset2, index2);
638 if (!ignoreUnits) {
639 if (SDDS_GetArrayInformation(dataset1, "units", &units1, SDDS_GET_BY_INDEX, index1) != SDDS_STRING) {
640 SDDS_SetError("Units field of array has wrong data type!");
641 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
642 exit(EXIT_FAILURE);
643 }
644 if (SDDS_GetArrayInformation(dataset2, "units", &units2, SDDS_GET_BY_INDEX, index2) != SDDS_STRING) {
645 SDDS_SetError("Units field of array has wrong data type!");
646 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
647 exit(EXIT_FAILURE);
648 }
649 }
650 break;
651 }
652 datatype[i] = type1;
653 if (type1 != type2) {
654 if (first && !compareCommon) {
655 fprintf(stderr, "The type of the following %ss do not match in the two files:\n", def);
656 fprintf(stderr, "%20s\t%20s\t%20s\n", "Name", file1, file2);
657 first = 0;
658 }
659 if (!compareCommon) {
660 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], SDDS_type_name[type1 - 1], SDDS_type_name[type2 - 1]);
661 returnValue++;
662 }
663 sames--;
664 same[i] = 0;
665 } else if ((units1 && units2 && strcasecmp(units1, units2) != 0) || (units1 && !units2) || (!units1 && units2)) {
666 if (first && !compareCommon) {
667 fprintf(stderr, "The units of the following %ss do not match in the two files:\n", def);
668 fprintf(stderr, "%20s\t%20s\t%20s\n", "Name", file1, file2);
669 first = 0;
670 }
671 if (!compareCommon) {
672 if (units1 && units2)
673 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], units1, units2);
674 else if (units1)
675 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], units1, " ");
676 else if (units2)
677 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], " ", units2);
678 returnValue++;
679 }
680 sames--;
681 same[i] = 0;
682 }
683 free(units1);
684 free(units2);
685 units1 = units2 = NULL;
686 if (returnValue && !compareCommon)
687 break;
688 }
689 if (!compareCommon && returnValue) {
690 sames = 0;
691 }
692 }
693 if (sames) {
694 if (!(*names)) {
695 for (i = 0; i < same_items; i++) {
696 if (same[i]) {
697 *name = (char **)SDDS_Realloc(*name, sizeof(**name) * (*names + 1));
698 *dataType = (int32_t *)SDDS_Realloc(*dataType, sizeof(**dataType) * (*names + 1));
699 SDDS_CopyString(*name + *names, same_name[i]);
700 (*dataType)[*names] = datatype[i];
701 (*names)++;
702 }
703 }
704 free(datatype);
705 } else
706 *dataType = datatype;
707 }
708
709 for (i = 0; i < names2; i++)
710 free(name2[i]);
711 free(name2);
712 for (i = 0; i < names1; i++)
713 free(name1[i]);
714 free(name1);
715 if (same)
716 free(same);
717 if (free_same_name)
718 free(same_name);
719 free(def);
720 return compareCommon ? 0 : returnValue;
721}
char * SDDS_type_name[SDDS_NUM_TYPES]
Array of supported data type names.
Definition SDDS_data.c:43
int32_t SDDS_GetArrayInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified array in the SDDS dataset.
Definition SDDS_info.c:192
int32_t SDDS_GetParameterInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified parameter in the SDDS dataset.
Definition SDDS_info.c:117
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
Definition SDDS_info.c:41
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
int32_t SDDS_GetParameterType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a parameter in the SDDS dataset by its index.
int32_t SDDS_GetArrayIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named array in the SDDS dataset.
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters in the SDDS dataset.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
int32_t SDDS_GetArrayType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of an array in the SDDS dataset by its index.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
char ** SDDS_GetArrayNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all arrays in the SDDS dataset.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.

◆ main()

int main ( int argc,
char ** argv )

Definition at line 115 of file sddsdiff.c.

115 {
116 SCANNED_ARG *s_arg;
117 SDDS_DATASET table1, table2;
118 char *file1, *file2;
119 long different = 0, i, pages1, pages2, pagediff = 0, i_arg, absolute = 0;
120 int32_t *columnDataType, *parDataType, *arrayDataType;
121 int32_t columns, parameters, arrays, columnMatches, parameterMatches, arrayMatches;
122 int64_t rows1, rows2;
123 char **columnName, **parameterName, **arrayName, **columnMatch, **parameterMatch, **arrayMatch;
124 long column_provided, parameter_provided, array_provided, precision, labelFromSecondFile = 0, rowLabelType = 0, rowLabelIndex = -1, notCompareRowLabel = 0;
125 long double tolerance = 0.0L, precisionTolerance = 0.0L;
126 unsigned long compareCommonFlags = 0, dummyFlags = 0;
127 char *floatFormat, *doubleFormat, *ldoubleFormat, *stringFormat, *rowLabelColumn;
128 void *rowLabel;
129 short ignoreUnits = 0;
130
131 rowLabelColumn = NULL;
132 rowLabel = NULL;
133 floatFormat = doubleFormat = ldoubleFormat = stringFormat = NULL;
134 precision = 0;
135 columnDataType = parDataType = arrayDataType = NULL;
136 columnName = parameterName = arrayName = NULL;
137 columnMatch = parameterMatch = arrayMatch = NULL;
138 columnMatches = parameterMatches = arrayMatches = 0;
139 columns = parameters = arrays = 0;
140 file1 = file2 = NULL;
141 pages1 = pages2 = 0;
142 column_provided = parameter_provided = array_provided = 0;
144 argc = scanargs(&s_arg, argc, argv);
145 if (argc < 3) {
146 fprintf(stderr, "%s%s", USAGE1, USAGE2);
147 exit(EXIT_FAILURE);
148 }
149 for (i_arg = 1; i_arg < argc; i_arg++) {
150 if (s_arg[i_arg].arg_type == OPTION) {
151 delete_chars(s_arg[i_arg].list[0], "_");
152 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
153 case CLO_ROWLABEL:
154 if (s_arg[i_arg].n_items < 2)
155 SDDS_Bomb("Invalid -rowlabel syntax");
156 rowLabelColumn = s_arg[i_arg].list[1];
157 if (s_arg[i_arg].n_items > 2 &&
158 strncmp_case_insensitive("nocomparison", s_arg[i_arg].list[2], strlen(s_arg[i_arg].list[2])) == 0)
159 notCompareRowLabel = 1;
160 break;
161 case CLO_EXACT:
162 tolerance = -1.0L;
163 break;
164 case CLO_ABSOLUTE:
165 absolute = 1;
166 break;
167 case CLO_TOLERANCE:
168 if (s_arg[i_arg].n_items != 2)
169 SDDS_Bomb("Invalid -tolerance syntax");
170 if (!get_longdouble(&tolerance, s_arg[i_arg].list[1]))
171 SDDS_Bomb("Invalid -tolerance syntax (not a number given)");
172 break;
173 case CLO_PRECISION:
174 if (s_arg[i_arg].n_items != 2)
175 SDDS_Bomb("Invalid -precision syntax");
176 if (!get_long(&precision, s_arg[i_arg].list[1]))
177 SDDS_Bomb("Invalid -precision syntax (not a number given)");
178 if (precision < 0)
179 precision = 0;
180 break;
181 case CLO_FORMAT:
182 if (s_arg[i_arg].n_items < 2)
183 SDDS_Bomb("Invalid -format syntax.");
184 s_arg[i_arg].n_items--;
185 if (!scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
186 "float", SDDS_STRING, &floatFormat, 1, 0,
187 "double", SDDS_STRING, &doubleFormat, 1, 0,
188 "longdouble", SDDS_STRING, &ldoubleFormat, 1, 0,
189 "string", SDDS_STRING, &stringFormat, 1, 0, NULL))
190 SDDS_Bomb("Invalid -format syntax");
191 s_arg[i_arg].n_items++;
192 if (floatFormat && !SDDS_VerifyPrintfFormat(floatFormat, SDDS_FLOAT)) {
193 fprintf(stderr, "Error: Given print format (\"%s\") for float data is invalid.\n", floatFormat);
194 exit(EXIT_FAILURE);
195 }
196 if (doubleFormat && !SDDS_VerifyPrintfFormat(doubleFormat, SDDS_DOUBLE)) {
197 fprintf(stderr, "Error: Given print format (\"%s\") for double data is invalid.\n", doubleFormat);
198 exit(EXIT_FAILURE);
199 }
200 if (ldoubleFormat && !SDDS_VerifyPrintfFormat(ldoubleFormat, SDDS_LONGDOUBLE)) {
201 fprintf(stderr, "Error: Given print format (\"%s\") for long double data is invalid.\n", ldoubleFormat);
202 exit(EXIT_FAILURE);
203 }
204 if (stringFormat && !SDDS_VerifyPrintfFormat(stringFormat, SDDS_STRING)) {
205 fprintf(stderr, "Error: Given print format (\"%s\") for string data is invalid.\n", stringFormat);
206 exit(EXIT_FAILURE);
207 }
208 break;
209 case CLO_COMPARECOMMON:
210 if (s_arg[i_arg].n_items == 1)
211 compareCommonFlags |= COMPARE_COMMON_COLUMN | COMPARE_COMMON_PARAMETER | COMPARE_COMMON_ARRAY;
212 else {
213 s_arg[i_arg].n_items--;
214 if (!scanItemList(&compareCommonFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
215 "column", -1, NULL, 0, COMPARE_COMMON_COLUMN,
216 "parameter", -1, NULL, 0, COMPARE_COMMON_PARAMETER,
217 "array", -1, NULL, 0, COMPARE_COMMON_ARRAY, NULL))
218 SDDS_Bomb("Invalid -compareCommon syntax");
219 s_arg[i_arg].n_items++;
220 }
221 break;
222 case CLO_COLUMNS:
223 if (s_arg[i_arg].n_items < 2)
224 SDDS_Bomb("Invalid -columns syntax");
225 columnMatch = tmalloc(sizeof(*columnMatch) * (columnMatches = s_arg[i_arg].n_items - 1));
226 for (i = 0; i < columnMatches; i++)
227 columnMatch[i] = s_arg[i_arg].list[i + 1];
228 column_provided = 1;
229 break;
230 case CLO_PARAMETERS:
231 if (s_arg[i_arg].n_items < 2)
232 SDDS_Bomb("Invalid -parameters syntax");
233 parameterMatch = tmalloc(sizeof(*parameterMatch) * (parameterMatches = s_arg[i_arg].n_items - 1));
234 for (i = 0; i < parameterMatches; i++)
235 parameterMatch[i] = s_arg[i_arg].list[i + 1];
236 parameter_provided = 1;
237 break;
238 case CLO_ARRAYS:
239 if (s_arg[i_arg].n_items < 2)
240 SDDS_Bomb("Invalid -arrays syntax");
241 arrayMatch = tmalloc(sizeof(*arrayMatch) * (arrayMatches = s_arg[i_arg].n_items - 1));
242 for (i = 0; i < arrayMatches; i++)
243 arrayMatch[i] = s_arg[i_arg].list[i + 1];
244 array_provided = 1;
245 break;
246 case CLO_IGNORE_UNITS:
247 ignoreUnits = 1;
248 break;
249 default:
250 fprintf(stderr, "Unknown option given (sddsdiff): %s\n", s_arg[i_arg].list[0]);
251 exit(EXIT_FAILURE);
252 break;
253 }
254 } else {
255 if (!file1)
256 file1 = s_arg[i_arg].list[0];
257 else if (!file2)
258 file2 = s_arg[i_arg].list[0];
259 else
260 SDDS_Bomb("Too many files given.");
261 }
262 }
263 if (!floatFormat)
264 SDDS_CopyString(&floatFormat, "%25.8e");
265 if (!doubleFormat)
266 SDDS_CopyString(&doubleFormat, "%25.16e");
267 if (!ldoubleFormat)
268 SDDS_CopyString(&ldoubleFormat, "%26.18Le");
269 if (!stringFormat)
270 SDDS_CopyString(&stringFormat, "%25s");
271
272 if (tolerance && precision > 0) {
273 SDDS_Bomb("Tolerance and precision options are not compatible. Only one of tolerance, precision, or exact may be given.");
274 }
275 if (!file1 || !file2) {
276 fprintf(stderr, "Error: Two files must be provided for comparison.\n");
277 exit(EXIT_FAILURE);
278 }
279 if (strcmp(file1, file2) == 0) {
280 printf("\"%s\" and \"%s\" are identical.\n", file1, file2);
281 return EXIT_SUCCESS;
282 }
283 if (!SDDS_InitializeInput(&table1, file1)) {
284 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
285 exit(EXIT_FAILURE);
286 }
287 if (!SDDS_InitializeInput(&table2, file2)) {
288 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
289 exit(EXIT_FAILURE);
290 }
291 if (rowLabelColumn) {
292 if ((rowLabelIndex = SDDS_GetColumnIndex(&table1, rowLabelColumn)) < 0) {
293 if ((rowLabelIndex = SDDS_GetColumnIndex(&table2, rowLabelColumn)) < 0) {
294 fprintf(stdout, "Warning: Row label column \"%s\" does not exist in the input files. The number of rows will be labeled instead.\n", rowLabelColumn);
295 rowLabelColumn = NULL;
296 } else {
297 labelFromSecondFile = 1;
298 notCompareRowLabel = 1;
299 }
300 } else {
301 if (SDDS_GetColumnIndex(&table2, rowLabelColumn) < 0)
302 notCompareRowLabel = 1;
303 }
304
305 if (rowLabelColumn) {
306 if (labelFromSecondFile)
307 rowLabelType = SDDS_GetColumnType(&table2, rowLabelIndex);
308 else
309 rowLabelType = SDDS_GetColumnType(&table1, rowLabelIndex);
310 }
311 }
312 if (!precision) {
313 precisionTolerance = powl(10L, -1L * fabsl(log10l(LDBL_EPSILON)));
314 } else {
315 precisionTolerance = powl(10L, -1L * precision);
316 }
317 if (column_provided) {
318 columnName = getMatchingSDDSNames(&table1, columnMatch, columnMatches, &columns, SDDS_MATCH_COLUMN);
319 if (CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits))
320 different = 1;
321 }
322 if (parameter_provided) {
323 parameterName = getMatchingSDDSNames(&table1, parameterMatch, parameterMatches, &parameters, SDDS_MATCH_PARAMETER);
324
325 if (CompareDefinitions(&table1, &table2, file1, file2, &parameters, &parameterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits))
326 different = 1;
327 }
328 if (array_provided) {
329 arrayName = getMatchingSDDSNames(&table1, arrayMatch, arrayMatches, &arrays, SDDS_MATCH_ARRAY);
330 if (CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits))
331 different = 1;
332 }
333 if (!columns && !parameters && !arrays) {
334 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_COLUMN)
335 different += CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits);
336 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_PARAMETER)
337 different += CompareDefinitions(&table1, &table2, file1, file2, &parameters, &parameterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits);
338 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_ARRAY)
339 different += CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits);
340 }
341 if (!different) {
342 if (!columns && !parameters && !arrays) {
343 fprintf(stderr, "There are no common columns, parameters, or arrays in the two files.\n");
344 different = 1;
345 } else {
346 /* Definitions are the same, now compare the data */
347 while (1) {
348 pagediff = 0;
349 pages1 = SDDS_ReadPage(&table1);
350 pages2 = SDDS_ReadPage(&table2);
351 if (pages1 > 0 && pages2 > 0) {
352 /* Compare data */
353 rows1 = SDDS_CountRowsOfInterest(&table1);
354 rows2 = SDDS_CountRowsOfInterest(&table2);
355 if (rows1 != rows2) {
356 pagediff = 1;
357 different = 1;
358 fprintf(stderr, "The two files have different numbers of rows on page %ld: \"%s\" has %" PRId64 " rows, while \"%s\" has %" PRId64 " rows.\n",
359 pages1, file1, rows1, file2, rows2);
360 break;
361 } else {
362 if (parameters)
363 pagediff += CompareData(&table1, &table2, file1, file2, parameters, parameterName, parDataType, SDDS_PARAMETER_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
364 if (columns && rows1) {
365 if (rowLabelColumn) {
366 if (labelFromSecondFile) {
367 if (!(rowLabel = SDDS_GetColumn(&table2, rowLabelColumn)))
368 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
369 } else {
370 if (!(rowLabel = SDDS_GetColumn(&table1, rowLabelColumn)))
371 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
372 }
373 }
374 pagediff += CompareData(&table1, &table2, file1, file2, columns, columnName, columnDataType, SDDS_COLUMN_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, rowLabel, rowLabelType, rowLabelColumn);
375 if (rowLabelColumn) {
376 if (rowLabelType == SDDS_STRING)
377 SDDS_FreeStringArray((char **)rowLabel, rows1);
378 else
379 free(rowLabel);
380 rowLabel = NULL;
381 }
382 }
383 if (arrays)
384 pagediff += CompareData(&table1, &table2, file1, file2, arrays, arrayName, arrayDataType, SDDS_ARRAY_TYPE, pages1, tolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
385 different += pagediff;
386 }
387 } else if (pages1 > 0 && pages2 <= 0) {
388 fprintf(stderr, "\"%s\" has fewer pages than \"%s\".\n", file2, file1);
389 different = 1;
390 break;
391 } else if (pages1 < 0 && pages2 > 0) {
392 different = 1;
393 fprintf(stderr, "\"%s\" has fewer pages than \"%s\".\n", file1, file2);
394 break;
395 } else {
396 break;
397 }
398 }
399 }
400 } else {
401 different = 1;
402 }
403 if (!different)
404 printf("\"%s\" and \"%s\" are identical.\n", file1, file2);
405 else
406 fprintf(stderr, "\"%s\" and \"%s\" are different.\n", file1, file2);
407
408 if (columns) {
409 for (i = 0; i < columns; i++)
410 free(columnName[i]);
411 free(columnName);
412 free(columnDataType);
413 free(columnMatch);
414 }
415 if (parameters) {
416 for (i = 0; i < parameters; i++)
417 free(parameterName[i]);
418 free(parameterName);
419 free(parDataType);
420 free(parameterMatch);
421 }
422 if (arrays) {
423 for (i = 0; i < arrays; i++)
424 free(arrayName[i]);
425 free(arrayName);
426 free(arrayDataType);
427 free(arrayMatch);
428 }
429 free_scanargs(&s_arg, argc);
430 free(stringFormat);
431 free(floatFormat);
432 free(doubleFormat);
433 free(ldoubleFormat);
434
435 if (!SDDS_Terminate(&table1) || !SDDS_Terminate(&table2)) {
436 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
437 exit(EXIT_FAILURE);
438 }
439 return EXIT_SUCCESS;
440}
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
int32_t SDDS_VerifyPrintfFormat(const char *string, int32_t type)
Verifies that a printf format string is compatible with a specified data type.
Definition SDDS_utils.c:750
char ** getMatchingSDDSNames(SDDS_DATASET *dataset, char **matchName, int32_t matches, int32_t *names, short type)
Retrieves an array of matching SDDS entity names based on specified criteria.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
int get_longdouble(long double *dptr, char *s)
Parses a long double value from the given string.
Definition data_scan.c:88
int get_long(long *iptr, char *s)
Parses a long integer value from the given string.
Definition data_scan.c:255
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
int strncmp_case_insensitive(char *s1, char *s2, long n)
Compares up to a specified number of characters of two strings in a case-insensitive manner.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.

◆ printTitle()

void printTitle ( long flags,
char * name,
long page,
long absolute,
char * labelName )

Definition at line 872 of file sddsdiff.c.

872 {
873 char *type = NULL;
874 char *element = NULL;
875
876 switch (flags) {
877 case SDDS_COLUMN_TYPE:
878 SDDS_CopyString(&type, "column");
879 if (labelName)
880 SDDS_CopyString(&element, labelName);
881 else
882 SDDS_CopyString(&element, "row");
883 break;
884 case SDDS_PARAMETER_TYPE:
885 SDDS_CopyString(&type, "parameter");
886 SDDS_CopyString(&element, "page number");
887 break;
888 case SDDS_ARRAY_TYPE:
889 SDDS_CopyString(&type, "array");
890 SDDS_CopyString(&element, "element number");
891 break;
892 }
893 if (type) {
894 fprintf(stdout, "\nDifferences found in %s \"%s\" on page %ld:\n", type, name, page);
895 if (absolute)
896 fprintf(stdout, "%20s%25s%25s%25s\n", element, "Value in file1", "Value in file2", "Difference (abs)");
897 else
898 fprintf(stdout, "%20s%25s%25s%25s\n", element, "Value in file1", "Value in file2", "Difference (file1 - file2)");
899 free(type);
900 free(element);
901 }
902}

Variable Documentation

◆ option

char* option[N_OPTIONS]
Initial value:
= {
"compareCommon",
"columns",
"parameters",
"arrays",
"tolerance",
"precision",
"format",
"exact",
"absolute",
"rowlabel",
"ignoreUnits"}

Definition at line 60 of file sddsdiff.c.

60 {
61 "compareCommon",
62 "columns",
63 "parameters",
64 "arrays",
65 "tolerance",
66 "precision",
67 "format",
68 "exact",
69 "absolute",
70 "rowlabel",
71 "ignoreUnits"};

◆ USAGE1

char* USAGE1
Initial value:
= "Usage: sddsdiff <file1> <file2> [options]\n\
Options:\n\
-compareCommon[=column|parameter|array] Compare only the common items.\n\
-columns=<col1>[,<col2>...] Specify columns to compare.\n\
-parameters=<par1>[,<par2>...] Specify parameters to compare.\n\
-arrays=<array1>[,<array2>...] Specify arrays to compare.\n\
-tolerance=<value> Set tolerance for numerical comparisons.\n\
-precision=<integer> Set precision for floating-point comparisons.\n\
-format=float=<string> Set print format for float data.\n\
-format=double=<string> Set print format for double data.\n\
-format=longdouble=<string> Set print format for long double data.\n\
-format=string=<string> Set print format for string data.\n\
-exact Compare values exactly.\n\
-absolute Compare absolute values, ignoring signs.\n\
-rowlabel=<column-name>[,nocomparison] Use a column to label rows.\n\
-ignoreUnits Do not compare units of items.\n"

Definition at line 73 of file sddsdiff.c.

◆ USAGE2

char* USAGE2
Initial value:
= "\n\
Description:\n\
sddsdiff compares two SDDS files by checking their definitions and data. It reports differences in columns,\n\
parameters, and arrays based on the specified options.\n\
\n\
Example:\n\
sddsdiff data1.sdds data2.sdds -compareCommon=column -tolerance=1e-5 -absolute\n\
\n\
Program by Hairong Shang. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n"

Definition at line 90 of file sddsdiff.c.