SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
sddsdiff.c File Reference

Detailed Description

Compare two SDDS files for differences in definitions and data.

The program sddsdiff compares two SDDS (Self Describing Data Sets) files by analyzing their definitions (columns, parameters, arrays) and data, supporting various comparison criteria such as exact matches, numerical tolerances, and absolute differences. It provides detailed reports on discrepancies in definitions or data values.

Usage

sddsdiff <file1> <file2>
[-compareCommon[=column|parameter|array]]
[-columns=<col1>[,<col2>...]]
[-parameters=<par1>[,<par2>...]]
[-arrays=<array1>[,<array2>...]]
[-tolerance=<value>]
[-relativeTolerance=<value>]
[-precision=<integer>]
[-format=float=<string>|double=<string>|longdouble=<string>|string=<string>]
[-exact]
[-absolute]
[-rowlabel=<column-name>[,nocomparison]]
[-ignoreUnits]

Options

Option Description
-compareCommon Compare only common columns, parameters, or arrays.
-columns Specify columns to compare.
-parameters Specify parameters to compare.
-arrays Specify arrays to compare.
-tolerance Set absolute numerical comparison tolerance.
-relativeTolerance Set relative tolerance using min(abs(value1), abs(value2)) * value.
-precision Set the precision for numerical comparison.
-format Specify the format for printing float, double, long double, or string data.
-exact Compare values exactly (mutually exclusive with tolerance and precision).
-absolute Compare absolute values.
-rowlabel Use a column to label rows for comparison.
-ignoreUnits Ignore units during the comparison.

Incompatibilities

  • -exact is incompatible with:
    • -tolerance
    • -precision
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.

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

Go to the source code of this file.

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 relativeTolerance, 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 relativeTolerance, 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)
 

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 relativeTolerance,
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 953 of file sddsdiff.c.

959 {
960 char *str1, *str2;
961 long double ldval1, ldval2, ldenominator, ldabs1, ldabs2, lddiff;
962 double dval1, dval2, denominator, dabs1, dabs2, ddiff;
963 float fval1, fval2, fabs1, fabs2, fdenominator, fdiff;
964 int32_t lval1, lval2, labs1, labs2, ldiff, uldiff;
965 uint32_t ulval1, ulval2;
966 int64_t llval1, llval2, llabs1, llabs2, lldiff, ulldiff;
967 uint64_t ullval1, ullval2;
968 short sval1, sval2, sabs1, sabs2, sdiff, usdiff;
969 unsigned short usval1, usval2;
970 char cval1, cval2;
971 long returnValue = 0, printIndex;
972 long double tol, scale;
973
974 printIndex = index + 1;
975 if (parameter)
976 printIndex = page;
977
978 if (tolerance < 0)
979 tol = 0L;
980 else
981 tol = tolerance;
982
983 switch (datatype) {
984 case SDDS_STRING:
985 str1 = *((char **)data1 + index);
986 str2 = *((char **)data2 + index);
987 returnValue = strcmp(trim_spaces(str1), trim_spaces(str2));
988 if (returnValue != 0) {
989 if (first)
990 printTitle(flags, name, page, absolute, labelName);
991 if (labelName) {
992 fprintf(stdout, stringFormat, str1, str2, returnValue);
993 } else
994 fprintf(stdout, stringFormat, printIndex, str1, str2, returnValue);
995 }
996 break;
997 case SDDS_LONGDOUBLE:
998 ldval1 = *((long double *)data1 + index);
999 ldval2 = *((long double *)data2 + index);
1000 if (absolute) {
1001 ldabs1 = fabsl(ldval1);
1002 ldabs2 = fabsl(ldval2);
1003 } else {
1004 ldabs1 = ldval1;
1005 ldabs2 = ldval2;
1006 }
1007 lddiff = ldabs1 - ldabs2;
1008 if ((isnan(ldval1) && !isnan(ldval2)) || (isinf(ldval1) && !isinf(ldval2)))
1009 returnValue = 1;
1010 else if (ldabs1 != ldabs2) {
1011 if (relativeTolerance) {
1012 scale = MIN(fabsl(ldval1), fabsl(ldval2));
1013 if (fabsl(lddiff) > scale * relativeTolerance)
1014 returnValue = 1;
1015 } else if (tolerance) {
1016 if (fabsl(lddiff) > tol)
1017 returnValue = 1;
1018 } else {
1019 if (ldabs1 == 0L || ldabs2 == 0L) {
1020 if (fabsl(ldabs1 - ldabs2) > precisionTolerance)
1021 returnValue = 1;
1022 } else {
1023 ldabs1 = fabsl(ldval1);
1024 ldabs2 = fabsl(ldval2);
1025 ldenominator = (ldabs1 < ldabs2) ? ldabs1 : ldabs2;
1026 if (fabsl(ldval1 - ldval2) / ldenominator > precisionTolerance)
1027 returnValue = 1;
1028 }
1029 }
1030 }
1031 if (returnValue) {
1032 if (first)
1033 printTitle(flags, name, page, absolute, labelName);
1034 if (labelName)
1035 fprintf(stdout, ldoubleFormat, ldval1, ldval2, lddiff);
1036 else
1037 fprintf(stdout, ldoubleFormat, printIndex, ldval1, ldval2, lddiff);
1038 }
1039 break;
1040 case SDDS_DOUBLE:
1041 dval1 = *((double *)data1 + index);
1042 dval2 = *((double *)data2 + index);
1043 if (absolute) {
1044 dabs1 = fabs(dval1);
1045 dabs2 = fabs(dval2);
1046 } else {
1047 dabs1 = dval1;
1048 dabs2 = dval2;
1049 }
1050 ddiff = dabs1 - dabs2;
1051 if ((isnan(dval1) && !isnan(dval2)) || (isinf(dval1) && !isinf(dval2)))
1052 returnValue = 1;
1053 else if (dabs1 != dabs2) {
1054 if (relativeTolerance) {
1055 scale = MIN(fabs(dval1), fabs(dval2));
1056 if (fabs(ddiff) > scale * relativeTolerance)
1057 returnValue = 1;
1058 } else if (tolerance) {
1059 if (fabs(ddiff) > tol)
1060 returnValue = 1;
1061 } else {
1062 if (dabs1 == 0 || dabs2 == 0) {
1063 if (fabs(dabs1 - dabs2) > precisionTolerance)
1064 returnValue = 1;
1065 } else {
1066 dabs1 = fabs(dval1);
1067 dabs2 = fabs(dval2);
1068 denominator = (dabs1 < dabs2) ? dabs1 : dabs2;
1069 if (fabs(dval1 - dval2) / denominator > precisionTolerance)
1070 returnValue = 1;
1071 }
1072 }
1073 }
1074 if (returnValue) {
1075 if (first)
1076 printTitle(flags, name, page, absolute, labelName);
1077 if (labelName)
1078 fprintf(stdout, doubleFormat, dval1, dval2, ddiff);
1079 else
1080 fprintf(stdout, doubleFormat, printIndex, dval1, dval2, ddiff);
1081 }
1082 break;
1083 case SDDS_FLOAT:
1084 fval1 = *((float *)data1 + index);
1085 fval2 = *((float *)data2 + index);
1086 if (absolute) {
1087 fabs1 = fabs(fval1);
1088 fabs2 = fabs(fval2);
1089 } else {
1090 fabs1 = fval1;
1091 fabs2 = fval2;
1092 }
1093 fdiff = fabs1 - fabs2;
1094 if ((isnan(fval1) && !isnan(fval2)) || (isinf(fval1) && !isinf(fval2)))
1095 returnValue = 1;
1096 else if (fabs1 != fabs2) {
1097 if (relativeTolerance) {
1098 scale = MIN(fabs(fval1), fabs(fval2));
1099 if (fabs(fdiff) > scale * relativeTolerance)
1100 returnValue = 1;
1101 } else if (tolerance) {
1102 if (fabs(fdiff) > tol)
1103 returnValue = 1;
1104 } else {
1105 if (fabs1 == 0 || fabs2 == 0) {
1106 if (fabs(fabs1 - fabs2) > precisionTolerance)
1107 returnValue = 1;
1108 } else {
1109 fabs1 = fabs(fval1);
1110 fabs2 = fabs(fval2);
1111 fdenominator = (fabs1 < fabs2) ? fabs1 : fabs2;
1112 if (fabs(fval1 - fval2) / fdenominator > precisionTolerance)
1113 returnValue = 1;
1114 }
1115 }
1116 }
1117 if (returnValue) {
1118 if (first)
1119 printTitle(flags, name, page, absolute, labelName);
1120 if (labelName)
1121 fprintf(stdout, floatFormat, fval1, fval2, fdiff);
1122 else
1123 fprintf(stdout, floatFormat, printIndex, fval1, fval2, fdiff);
1124 }
1125 break;
1126 case SDDS_ULONG64:
1127 ullval1 = *((uint64_t *)data1 + index);
1128 ullval2 = *((uint64_t *)data2 + index);
1129 ulldiff = ullval1 - ullval2;
1130 if (labs(ulldiff) > tol)
1131 returnValue = 1;
1132 if (returnValue) {
1133 if (first)
1134 printTitle(flags, name, page, absolute, labelName);
1135 if (labelName)
1136 fprintf(stdout, ulongFormat, ullval1, ullval2, ulldiff);
1137 else
1138 fprintf(stdout, ulongFormat, printIndex, ullval1, ullval2, ulldiff);
1139 }
1140 break;
1141 case SDDS_LONG64:
1142 llval1 = *((int64_t *)data1 + index);
1143 llval2 = *((int64_t *)data2 + index);
1144 if (absolute) {
1145 llabs1 = labs(llval1);
1146 llabs2 = labs(llval2);
1147 } else {
1148 llabs1 = llval1;
1149 llabs2 = llval2;
1150 }
1151 lldiff = llabs1 - llabs2;
1152 if (llabs(lldiff) > tol)
1153 returnValue = 1;
1154 if (returnValue) {
1155 if (first)
1156 printTitle(flags, name, page, absolute, labelName);
1157 if (labelName)
1158 fprintf(stdout, longFormat, llval1, llval2, lldiff);
1159 else
1160 fprintf(stdout, longFormat, printIndex, llval1, llval2, lldiff);
1161 }
1162 break;
1163 case SDDS_ULONG:
1164 ulval1 = *((uint32_t *)data1 + index);
1165 ulval2 = *((uint32_t *)data2 + index);
1166 uldiff = ulval1 - ulval2;
1167 if (labs(uldiff) > tol)
1168 returnValue = 1;
1169 if (returnValue) {
1170 if (first)
1171 printTitle(flags, name, page, absolute, labelName);
1172 if (labelName)
1173 fprintf(stdout, ulongFormat, ulval1, ulval2, uldiff);
1174 else
1175 fprintf(stdout, ulongFormat, printIndex, ulval1, ulval2, uldiff);
1176 }
1177 break;
1178 case SDDS_LONG:
1179 lval1 = *((int32_t *)data1 + index);
1180 lval2 = *((int32_t *)data2 + index);
1181 if (absolute) {
1182 labs1 = abs(lval1);
1183 labs2 = abs(lval2);
1184 } else {
1185 labs1 = lval1;
1186 labs2 = lval2;
1187 }
1188 ldiff = labs1 - labs2;
1189 if (labs(ldiff) > tol)
1190 returnValue = 1;
1191 if (returnValue) {
1192 if (first)
1193 printTitle(flags, name, page, absolute, labelName);
1194 if (labelName)
1195 fprintf(stdout, longFormat, lval1, lval2, ldiff);
1196 else
1197 fprintf(stdout, longFormat, printIndex, lval1, lval2, ldiff);
1198 }
1199 break;
1200 case SDDS_SHORT:
1201 sval1 = *((short *)data1 + index);
1202 sval2 = *((short *)data2 + index);
1203 if (absolute) {
1204 sabs1 = abs(sval1);
1205 sabs2 = abs(sval2);
1206 } else {
1207 sabs1 = sval1;
1208 sabs2 = sval2;
1209 }
1210 sdiff = sabs1 - sabs2;
1211 if (abs(sdiff) > tol)
1212 returnValue = 1;
1213 if (returnValue) {
1214 if (first)
1215 printTitle(flags, name, page, absolute, labelName);
1216 if (labelName)
1217 fprintf(stdout, shortFormat, sval1, sval2, sdiff);
1218 else
1219 fprintf(stdout, shortFormat, printIndex, sval1, sval2, sdiff);
1220 }
1221 break;
1222 case SDDS_USHORT:
1223 usval1 = *((unsigned short *)data1 + index);
1224 usval2 = *((unsigned short *)data2 + index);
1225 usdiff = usval1 - usval2;
1226 if (abs(usdiff) > tol)
1227 returnValue = 1;
1228 if (returnValue) {
1229 if (first)
1230 printTitle(flags, name, page, absolute, labelName);
1231 if (labelName)
1232 fprintf(stdout, ushortFormat, usval1, usval2, usdiff);
1233 else
1234 fprintf(stdout, ushortFormat, printIndex, usval1, usval2, usdiff);
1235 }
1236 break;
1237 case SDDS_CHARACTER:
1238 cval1 = *((char *)data1 + index);
1239 cval2 = *((char *)data2 + index);
1240 if (cval1 != cval2) {
1241 returnValue = 1;
1242 if (first)
1243 printTitle(flags, name, page, absolute, labelName);
1244 if (labelName)
1245 fprintf(stdout, charFormat, cval1, cval2, cval1 - cval2);
1246 else
1247 fprintf(stdout, charFormat, printIndex, cval1, cval2, cval1 - cval2);
1248 }
1249 break;
1250 default:
1251 fprintf(stderr, "Unknown data type %ld.\n", datatype);
1252 exit(EXIT_FAILURE);
1253 }
1254 return returnValue;
1255}
#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 relativeTolerance,
long double precisionTolerance,
char * floatFormat,
char * doubleFormat,
char * ldoubleFormat,
char * stringFormat,
long absolute,
void * rowLabel,
long rowLabelType,
char * labelName )

Definition at line 772 of file sddsdiff.c.

775 {
776 long diff = 0, i, first = 1;
777 int64_t rows, j;
778 char fFormat[2048], dFormat[2048], ldFormat[2048], strFormat[2048], lFormat[2048], ulFormat[2048], ushortFormat[2048], shortFormat[2048], cFormat[2048], labelFormat[1024];
779 SDDS_ARRAY *array1, *array2;
780 void *data1, *data2;
781
782 array1 = array2 = NULL;
783 data1 = data2 = NULL;
784
785 if (!rowLabel) {
786 snprintf(fFormat, sizeof(fFormat), "%%20ld%s%s%s\n", floatFormat, floatFormat, floatFormat);
787 snprintf(dFormat, sizeof(dFormat), "%%20ld%s%s%s\n", doubleFormat, doubleFormat, doubleFormat);
788 snprintf(ldFormat, sizeof(ldFormat), "%%20ld%s%s%s\n", ldoubleFormat, ldoubleFormat, ldoubleFormat);
789 snprintf(strFormat, sizeof(strFormat), "%%20ld%s%s%%25ld\n", stringFormat, stringFormat);
790 snprintf(lFormat, sizeof(lFormat), "%s", "%20ld%25ld%25ld\n");
791 snprintf(ulFormat, sizeof(ulFormat), "%s", "%20ld%25lu%25lu%25ld\n");
792 snprintf(shortFormat, sizeof(shortFormat), "%s", "%20ld%25hd%25hd%25hd\n");
793 snprintf(ushortFormat, sizeof(ushortFormat), "%s", "%20ld%25hu%25hu%25hd\n");
794 snprintf(cFormat, sizeof(cFormat), "%s", "%20ld%25c%25c%25d\n");
795 }
796 switch (type) {
797 case SDDS_COLUMN_TYPE:
798 rows = SDDS_CountRowsOfInterest(dataset1);
799 if (!rows)
800 break;
801 for (i = 0; i < names; i++) {
802 first = 1;
803 if (!(data1 = SDDS_GetColumn(dataset1, name[i])) || !(data2 = SDDS_GetColumn(dataset2, name[i]))) {
804 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
805 exit(EXIT_FAILURE);
806 }
807 for (j = 0; j < rows; j++) {
808 if (rowLabel) {
809 switch (rowLabelType) {
810 case SDDS_STRING:
811 snprintf(labelFormat, sizeof(labelFormat), "%20s", ((char **)rowLabel)[j]);
812 break;
813 case SDDS_LONGDOUBLE:
814 snprintf(labelFormat, sizeof(labelFormat), "%20.15Le", ((long double *)rowLabel)[j]);
815 break;
816 case SDDS_DOUBLE:
817 snprintf(labelFormat, sizeof(labelFormat), "%20.10e", ((double *)rowLabel)[j]);
818 break;
819 case SDDS_FLOAT:
820 snprintf(labelFormat, sizeof(labelFormat), "%20.5e", ((float *)rowLabel)[j]);
821 break;
822 case SDDS_ULONG64:
823 snprintf(labelFormat, sizeof(labelFormat), "%20" PRIu64, ((uint64_t *)rowLabel)[j]);
824 break;
825 case SDDS_LONG64:
826 snprintf(labelFormat, sizeof(labelFormat), "%20" PRId64, ((int64_t *)rowLabel)[j]);
827 break;
828 case SDDS_ULONG:
829 snprintf(labelFormat, sizeof(labelFormat), "%20" PRIu32, ((uint32_t *)rowLabel)[j]);
830 break;
831 case SDDS_LONG:
832 snprintf(labelFormat, sizeof(labelFormat), "%20" PRId32, ((int32_t *)rowLabel)[j]);
833 break;
834 case SDDS_USHORT:
835 snprintf(labelFormat, sizeof(labelFormat), "%20hu", ((unsigned short *)rowLabel)[j]);
836 break;
837 case SDDS_SHORT:
838 snprintf(labelFormat, sizeof(labelFormat), "%20hd", ((short *)rowLabel)[j]);
839 break;
840 case SDDS_CHARACTER:
841 snprintf(labelFormat, sizeof(labelFormat), "%20c", ((char *)rowLabel)[j]);
842 break;
843 default:
844 fprintf(stderr, "Unknown data type for rowlabel.\n");
845 exit(EXIT_FAILURE);
846 }
847 snprintf(fFormat, sizeof(fFormat), "%s%s%s%s\n", labelFormat, floatFormat, floatFormat, floatFormat);
848 snprintf(dFormat, sizeof(dFormat), "%s%s%s%s\n", labelFormat, doubleFormat, doubleFormat, doubleFormat);
849 snprintf(ldFormat, sizeof(ldFormat), "%s%s%s%s\n", labelFormat, ldoubleFormat, ldoubleFormat, ldoubleFormat);
850 snprintf(strFormat, sizeof(strFormat), "%s%s%s%%25ld\n", labelFormat, stringFormat, stringFormat);
851 snprintf(lFormat, sizeof(lFormat), "%s%%25ld%%25ld%%25ld\n", labelFormat);
852 snprintf(ulFormat, sizeof(ulFormat), "%s%%25lu%%25lu%%25ld\n", labelFormat);
853 snprintf(shortFormat, sizeof(shortFormat), "%s%%25hd%%25hd%%25hd\n", labelFormat);
854 snprintf(ushortFormat, sizeof(ushortFormat), "%s%%25hu%%25hu%%25hd\n", labelFormat);
855 snprintf(cFormat, sizeof(cFormat), "%s%%25c%%25c%%25d\n", labelFormat);
856 }
857 if (compare_two_data(data1, data2, j, dataType[i], first, SDDS_COLUMN_TYPE, name[i], page, tolerance, relativeTolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 0, rowLabelColumn) != 0) {
858 diff++;
859 if (first)
860 first = 0;
861 }
862 if (dataType[i] == SDDS_STRING) {
863 free((char *)((char **)data1)[j]);
864 free((char *)((char **)data2)[j]);
865 }
866 }
867 free((char **)data1);
868 free((char **)data2);
869 data1 = data2 = NULL;
870 }
871 break;
872 case SDDS_PARAMETER_TYPE:
873 for (i = 0; i < names; i++) {
874 first = 1;
875 if (!(data1 = SDDS_GetParameter(dataset1, name[i], NULL)) || !(data2 = SDDS_GetParameter(dataset2, name[i], NULL))) {
876 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
877 exit(EXIT_FAILURE);
878 }
879 if (compare_two_data(data1, data2, 0, dataType[i], first, SDDS_PARAMETER_TYPE, name[i], page, tolerance, relativeTolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 1, NULL) != 0) {
880 diff++;
881 if (first)
882 first = 0;
883 }
884 if (dataType[i] == SDDS_STRING) {
885 free(*((char **)data1));
886 free(*((char **)data2));
887 }
888 free(data1);
889 free(data2);
890 data1 = data2 = NULL;
891 }
892 break;
893 case SDDS_ARRAY_TYPE:
894 for (i = 0; i < names; i++) {
895 first = 1;
896 if (!(array1 = SDDS_GetArray(dataset1, name[i], NULL)) || !(array2 = SDDS_GetArray(dataset2, name[i], NULL))) {
897 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
898 exit(EXIT_FAILURE);
899 }
900 if (array1->elements != array2->elements) {
901 fprintf(stderr, "Array \"%s\" has %" PRId32 " elements in \"%s\", but %" PRId32 " elements in \"%s\".\n", name[i], array1->elements, file1, array2->elements, file2);
902 diff++;
903 } else {
904 for (j = 0; j < array1->elements; j++) {
905 if (compare_two_data(array1->data, array2->data, j, dataType[i], first, SDDS_ARRAY_TYPE, name[i], page, tolerance, relativeTolerance, precisionTolerance, fFormat, dFormat, ldFormat, strFormat, lFormat, ulFormat, shortFormat, ushortFormat, cFormat, absolute, 0, NULL) != 0) {
906 diff++;
907 if (first)
908 first = 0;
909 }
910 }
911 }
912 SDDS_FreeArray(array1);
913 SDDS_FreeArray(array2);
914 array1 = array2 = NULL;
915 }
916 break;
917 }
918 return diff;
919}
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:474

◆ 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 491 of file sddsdiff.c.

491 {
492 size_t same_items;
493 long sames, free_same_name = 0;
494 int32_t *same, *datatype;
495 int32_t names1, names2;
496 char **name1, **name2, *def, **same_name;
497 long type1, type2, i, returnValue = 0, first = 1;
498 int32_t index1, index2;
499 char *units1, *units2;
500 units1 = units2 = NULL;
501 name1 = name2 = same_name = NULL;
502 names1 = names2 = 0;
503 def = NULL;
504 same_items = 0;
505 same = datatype = NULL;
506
507 type1 = type2 = -1;
508
509 switch (type) {
510 case SDDS_COLUMN_TYPE:
511 name1 = SDDS_GetColumnNames(dataset1, &names1);
512 name2 = SDDS_GetColumnNames(dataset2, &names2);
513 SDDS_CopyString(&def, "column");
514 break;
515 case SDDS_PARAMETER_TYPE:
516 name1 = SDDS_GetParameterNames(dataset1, &names1);
517 name2 = SDDS_GetParameterNames(dataset2, &names2);
518 SDDS_CopyString(&def, "parameter");
519 break;
520 case SDDS_ARRAY_TYPE:
521 name1 = SDDS_GetArrayNames(dataset1, &names1);
522 name2 = SDDS_GetArrayNames(dataset2, &names2);
523 SDDS_CopyString(&def, "array");
524 break;
525 default:
526 fprintf(stderr, "Unknown type given for CompareDefinitions().\n");
527 return 1;
528 }
529 if (names1 == 0 && names2 == 0)
530 return 0;
531 if (*names) {
532 if (!names1 || !names2) {
533 fprintf(stderr, "Error: One of the files does not have any %s.\n", def);
534 returnValue = 1;
535 }
536 if (!returnValue) {
537 for (i = 0; i < *names; i++) {
538 if (rowLabelColumn && notCompareRowLabel && strcmp((*name)[i], rowLabelColumn) == 0)
539 continue;
540 if (-1 == match_string((*name)[i], name1, names1, EXACT_MATCH)) {
541 fprintf(stderr, "Error: File \"%s\" does not have %s \"%s\".\n", file1, def, (*name)[i]);
542 returnValue = 1;
543 break;
544 }
545 if (-1 == match_string((*name)[i], name2, names2, EXACT_MATCH)) {
546 fprintf(stderr, "Error: File \"%s\" does not have %s \"%s\".\n", file2, def, (*name)[i]);
547 returnValue = 1;
548 break;
549 }
550 }
551 }
552 if (returnValue) {
553 for (i = 0; i < names1; i++)
554 free(name1[i]);
555 free(name1);
556 for (i = 0; i < names2; i++)
557 free(name2[i]);
558 free(name2);
559 free(def);
560 return returnValue;
561 }
562 same_items = *names;
563 same_name = *name;
564 compareCommon = 0;
565 } else {
566 if (!names1 && !names2) {
567 free(def);
568 return 0;
569 }
570 if (compareCommon && (!names1 || !names2)) {
571 if (names1) {
572 for (i = 0; i < names1; i++)
573 free(name1[i]);
574 free(name1);
575 }
576 if (names2) {
577 for (i = 0; i < names2; i++)
578 free(name2[i]);
579 free(name2);
580 }
581 *names = 0;
582 return 0;
583 }
584 if (names1 != names2 && !compareCommon && !notCompareRowLabel)
585 returnValue = 1;
586 if (returnValue) {
587 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);
588 for (i = 0; i < names2; i++)
589 free(name2[i]);
590 free(name2);
591 for (i = 0; i < names1; i++)
592 free(name1[i]);
593 free(name1);
594 free(def);
595 return returnValue;
596 }
597 same_items = 0;
598 for (i = 0; i < names1; i++) {
599 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name1[i]) == 0)
600 continue;
601 if (-1 == match_string(name1[i], name2, names2, EXACT_MATCH)) {
602 if (!compareCommon) {
603 if (first) {
604 fprintf(stderr, " Following %ss of \"%s\" are not in \"%s\":\n", def, file1, file2);
605 first = 0;
606 }
607 fprintf(stderr, " %s\n", name1[i]);
608 returnValue++;
609 }
610 } else {
611 same_name = (char **)SDDS_Realloc(same_name, sizeof(*same_name) * (same_items + 1));
612 same_name[same_items] = name1[i];
613 same_items++;
614 }
615 }
616 if (!compareCommon) {
617 if (!first)
618 fprintf(stderr, "\n");
619 first = 1;
620 for (i = 0; i < names2; i++) {
621 if (rowLabelColumn && notCompareRowLabel && strcmp(rowLabelColumn, name2[i]) == 0)
622 continue;
623 if (-1 == match_string(name2[i], name1, names1, EXACT_MATCH)) {
624 if (first) {
625 fprintf(stderr, " Following %ss of \"%s\" are not in \"%s\":\n", def, file2, file1);
626 first = 0;
627 }
628 fprintf(stderr, " %s\n", name2[i]);
629 returnValue++;
630 }
631 }
632 if (!first)
633 fprintf(stderr, "\n");
634 }
635 if (same_items)
636 free_same_name = 1;
637 }
638 sames = same_items;
639 if (same_items) {
640 datatype = (int32_t *)malloc(sizeof(*datatype) * same_items);
641 same = (int32_t *)malloc(sizeof(*same) * same_items);
642 /* Check the units and type */
643 for (i = 0; i < same_items; i++) {
644 same[i] = 1;
645 switch (type) {
646 case SDDS_COLUMN_TYPE:
647 index1 = SDDS_GetColumnIndex(dataset1, same_name[i]);
648 index2 = SDDS_GetColumnIndex(dataset2, same_name[i]);
649 type1 = SDDS_GetColumnType(dataset1, index1);
650 type2 = SDDS_GetColumnType(dataset2, index2);
651 if (!ignoreUnits) {
652 if (SDDS_GetColumnInformation(dataset1, "units", &units1, SDDS_GET_BY_INDEX, index1) != SDDS_STRING) {
653 SDDS_SetError("Units field of column has wrong data type!");
654 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
655 exit(EXIT_FAILURE);
656 }
657 if (SDDS_GetColumnInformation(dataset2, "units", &units2, SDDS_GET_BY_INDEX, index2) != SDDS_STRING) {
658 SDDS_SetError("Units field of column has wrong data type!");
659 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
660 exit(EXIT_FAILURE);
661 }
662 }
663 break;
664 case SDDS_PARAMETER_TYPE:
665 index1 = SDDS_GetParameterIndex(dataset1, same_name[i]);
666 index2 = SDDS_GetParameterIndex(dataset2, same_name[i]);
667 type1 = SDDS_GetParameterType(dataset1, index1);
668 type2 = SDDS_GetParameterType(dataset2, index2);
669 if (!ignoreUnits) {
670 if (SDDS_GetParameterInformation(dataset1, "units", &units1, SDDS_GET_BY_INDEX, index1) != SDDS_STRING) {
671 SDDS_SetError("Units field of parameter has wrong data type!");
672 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
673 exit(EXIT_FAILURE);
674 }
675 if (SDDS_GetParameterInformation(dataset2, "units", &units2, SDDS_GET_BY_INDEX, index2) != SDDS_STRING) {
676 SDDS_SetError("Units field of parameter has wrong data type!");
677 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
678 exit(EXIT_FAILURE);
679 }
680 }
681 break;
682 case SDDS_ARRAY_TYPE:
683 index1 = SDDS_GetArrayIndex(dataset1, same_name[i]);
684 index2 = SDDS_GetArrayIndex(dataset2, same_name[i]);
685 type1 = SDDS_GetArrayType(dataset1, index1);
686 type2 = SDDS_GetArrayType(dataset2, index2);
687 if (!ignoreUnits) {
688 if (SDDS_GetArrayInformation(dataset1, "units", &units1, SDDS_GET_BY_INDEX, index1) != SDDS_STRING) {
689 SDDS_SetError("Units field of array has wrong data type!");
690 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
691 exit(EXIT_FAILURE);
692 }
693 if (SDDS_GetArrayInformation(dataset2, "units", &units2, SDDS_GET_BY_INDEX, index2) != SDDS_STRING) {
694 SDDS_SetError("Units field of array has wrong data type!");
695 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
696 exit(EXIT_FAILURE);
697 }
698 }
699 break;
700 }
701 datatype[i] = type1;
702 if (type1 != type2) {
703 if (first && !compareCommon) {
704 fprintf(stderr, "The type of the following %ss do not match in the two files:\n", def);
705 fprintf(stderr, "%20s\t%20s\t%20s\n", "Name", file1, file2);
706 first = 0;
707 }
708 if (!compareCommon) {
709 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], SDDS_type_name[type1 - 1], SDDS_type_name[type2 - 1]);
710 returnValue++;
711 }
712 sames--;
713 same[i] = 0;
714 } else if ((units1 && units2 && strcasecmp(units1, units2) != 0) || (units1 && !units2) || (!units1 && units2)) {
715 if (first && !compareCommon) {
716 fprintf(stderr, "The units of the following %ss do not match in the two files:\n", def);
717 fprintf(stderr, "%20s\t%20s\t%20s\n", "Name", file1, file2);
718 first = 0;
719 }
720 if (!compareCommon) {
721 if (units1 && units2)
722 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], units1, units2);
723 else if (units1)
724 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], units1, " ");
725 else if (units2)
726 fprintf(stderr, "%20s\t%20s\t%20s\n", same_name[i], " ", units2);
727 returnValue++;
728 }
729 sames--;
730 same[i] = 0;
731 }
732 free(units1);
733 free(units2);
734 units1 = units2 = NULL;
735 if (returnValue && !compareCommon)
736 break;
737 }
738 if (!compareCommon && returnValue) {
739 sames = 0;
740 }
741 }
742 if (sames) {
743 if (!(*names)) {
744 for (i = 0; i < same_items; i++) {
745 if (same[i]) {
746 *name = (char **)SDDS_Realloc(*name, sizeof(**name) * (*names + 1));
747 *dataType = (int32_t *)SDDS_Realloc(*dataType, sizeof(**dataType) * (*names + 1));
748 SDDS_CopyString(*name + *names, same_name[i]);
749 (*dataType)[*names] = datatype[i];
750 (*names)++;
751 }
752 }
753 free(datatype);
754 } else
755 *dataType = datatype;
756 }
757
758 for (i = 0; i < names2; i++)
759 free(name2[i]);
760 free(name2);
761 for (i = 0; i < names1; i++)
762 free(name1[i]);
763 free(name1);
764 if (same)
765 free(same);
766 if (free_same_name)
767 free(same_name);
768 free(def);
769 return compareCommon ? 0 : returnValue;
770}
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:421
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:922
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:743
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 154 of file sddsdiff.c.

154 {
155 SCANNED_ARG *s_arg;
156 SDDS_DATASET table1, table2;
157 char *file1, *file2;
158 long different = 0, i, pages1, pages2, pagediff = 0, i_arg, absolute = 0;
159 int32_t *columnDataType, *parDataType, *arrayDataType;
160 int32_t columns, parameters, arrays, columnMatches, parameterMatches, arrayMatches;
161 int64_t rows1, rows2;
162 char **columnName, **parameterName, **arrayName, **columnMatch, **parameterMatch, **arrayMatch;
163 long column_provided, parameter_provided, array_provided, precision, labelFromSecondFile = 0, rowLabelType = 0, rowLabelIndex = -1, notCompareRowLabel = 0;
164 long double tolerance = 0.0L, relativeTolerance = 0.0L, precisionTolerance = 0.0L;
165 unsigned long compareCommonFlags = 0, dummyFlags = 0;
166 char *floatFormat, *doubleFormat, *ldoubleFormat, *stringFormat, *rowLabelColumn;
167 void *rowLabel;
168 short ignoreUnits = 0;
169
170 rowLabelColumn = NULL;
171 rowLabel = NULL;
172 floatFormat = doubleFormat = ldoubleFormat = stringFormat = NULL;
173 precision = 0;
174 columnDataType = parDataType = arrayDataType = NULL;
175 columnName = parameterName = arrayName = NULL;
176 columnMatch = parameterMatch = arrayMatch = NULL;
177 columnMatches = parameterMatches = arrayMatches = 0;
178 columns = parameters = arrays = 0;
179 file1 = file2 = NULL;
180 pages1 = pages2 = 0;
181 column_provided = parameter_provided = array_provided = 0;
183 argc = scanargs(&s_arg, argc, argv);
184 if (argc < 3) {
185 fprintf(stderr, "%s%s", USAGE1, USAGE2);
186 exit(EXIT_FAILURE);
187 }
188 for (i_arg = 1; i_arg < argc; i_arg++) {
189 if (s_arg[i_arg].arg_type == OPTION) {
190 delete_chars(s_arg[i_arg].list[0], "_");
191 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
192 case CLO_ROWLABEL:
193 if (s_arg[i_arg].n_items < 2)
194 SDDS_Bomb("Invalid -rowlabel syntax");
195 rowLabelColumn = s_arg[i_arg].list[1];
196 if (s_arg[i_arg].n_items > 2 &&
197 strncmp_case_insensitive("nocomparison", s_arg[i_arg].list[2], strlen(s_arg[i_arg].list[2])) == 0)
198 notCompareRowLabel = 1;
199 break;
200 case CLO_EXACT:
201 tolerance = -1.0L;
202 break;
203 case CLO_ABSOLUTE:
204 absolute = 1;
205 break;
206 case CLO_TOLERANCE:
207 if (s_arg[i_arg].n_items != 2)
208 SDDS_Bomb("Invalid -tolerance syntax");
209 if (!get_longdouble(&tolerance, s_arg[i_arg].list[1]))
210 SDDS_Bomb("Invalid -tolerance syntax (not a number given)");
211 break;
212 case CLO_RELATIVE_TOLERANCE:
213 if (s_arg[i_arg].n_items != 2)
214 SDDS_Bomb("Invalid -relativeTolerance syntax");
215 if (!get_longdouble(&relativeTolerance, s_arg[i_arg].list[1]))
216 SDDS_Bomb("Invalid -relativeTolerance syntax (not a number given)");
217 break;
218 case CLO_PRECISION:
219 if (s_arg[i_arg].n_items != 2)
220 SDDS_Bomb("Invalid -precision syntax");
221 if (!get_long(&precision, s_arg[i_arg].list[1]))
222 SDDS_Bomb("Invalid -precision syntax (not a number given)");
223 if (precision < 0)
224 precision = 0;
225 break;
226 case CLO_FORMAT:
227 if (s_arg[i_arg].n_items < 2)
228 SDDS_Bomb("Invalid -format syntax.");
229 s_arg[i_arg].n_items--;
230 if (!scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
231 "float", SDDS_STRING, &floatFormat, 1, 0,
232 "double", SDDS_STRING, &doubleFormat, 1, 0,
233 "longdouble", SDDS_STRING, &ldoubleFormat, 1, 0,
234 "string", SDDS_STRING, &stringFormat, 1, 0, NULL))
235 SDDS_Bomb("Invalid -format syntax");
236 s_arg[i_arg].n_items++;
237 if (floatFormat && !SDDS_VerifyPrintfFormat(floatFormat, SDDS_FLOAT)) {
238 fprintf(stderr, "Error: Given print format (\"%s\") for float data is invalid.\n", floatFormat);
239 exit(EXIT_FAILURE);
240 }
241 if (doubleFormat && !SDDS_VerifyPrintfFormat(doubleFormat, SDDS_DOUBLE)) {
242 fprintf(stderr, "Error: Given print format (\"%s\") for double data is invalid.\n", doubleFormat);
243 exit(EXIT_FAILURE);
244 }
245 if (ldoubleFormat && !SDDS_VerifyPrintfFormat(ldoubleFormat, SDDS_LONGDOUBLE)) {
246 fprintf(stderr, "Error: Given print format (\"%s\") for long double data is invalid.\n", ldoubleFormat);
247 exit(EXIT_FAILURE);
248 }
249 if (stringFormat && !SDDS_VerifyPrintfFormat(stringFormat, SDDS_STRING)) {
250 fprintf(stderr, "Error: Given print format (\"%s\") for string data is invalid.\n", stringFormat);
251 exit(EXIT_FAILURE);
252 }
253 break;
254 case CLO_COMPARECOMMON:
255 if (s_arg[i_arg].n_items == 1)
256 compareCommonFlags |= COMPARE_COMMON_COLUMN | COMPARE_COMMON_PARAMETER | COMPARE_COMMON_ARRAY;
257 else {
258 s_arg[i_arg].n_items--;
259 if (!scanItemList(&compareCommonFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
260 "column", -1, NULL, 0, COMPARE_COMMON_COLUMN,
261 "parameter", -1, NULL, 0, COMPARE_COMMON_PARAMETER,
262 "array", -1, NULL, 0, COMPARE_COMMON_ARRAY, NULL))
263 SDDS_Bomb("Invalid -compareCommon syntax");
264 s_arg[i_arg].n_items++;
265 }
266 break;
267 case CLO_COLUMNS:
268 if (s_arg[i_arg].n_items < 2)
269 SDDS_Bomb("Invalid -columns syntax");
270 columnMatch = tmalloc(sizeof(*columnMatch) * (columnMatches = s_arg[i_arg].n_items - 1));
271 for (i = 0; i < columnMatches; i++)
272 columnMatch[i] = s_arg[i_arg].list[i + 1];
273 column_provided = 1;
274 break;
275 case CLO_PARAMETERS:
276 if (s_arg[i_arg].n_items < 2)
277 SDDS_Bomb("Invalid -parameters syntax");
278 parameterMatch = tmalloc(sizeof(*parameterMatch) * (parameterMatches = s_arg[i_arg].n_items - 1));
279 for (i = 0; i < parameterMatches; i++)
280 parameterMatch[i] = s_arg[i_arg].list[i + 1];
281 parameter_provided = 1;
282 break;
283 case CLO_ARRAYS:
284 if (s_arg[i_arg].n_items < 2)
285 SDDS_Bomb("Invalid -arrays syntax");
286 arrayMatch = tmalloc(sizeof(*arrayMatch) * (arrayMatches = s_arg[i_arg].n_items - 1));
287 for (i = 0; i < arrayMatches; i++)
288 arrayMatch[i] = s_arg[i_arg].list[i + 1];
289 array_provided = 1;
290 break;
291 case CLO_IGNORE_UNITS:
292 ignoreUnits = 1;
293 break;
294 default:
295 fprintf(stderr, "Unknown option given (sddsdiff): %s\n", s_arg[i_arg].list[0]);
296 exit(EXIT_FAILURE);
297 break;
298 }
299 } else {
300 if (!file1)
301 file1 = s_arg[i_arg].list[0];
302 else if (!file2)
303 file2 = s_arg[i_arg].list[0];
304 else
305 SDDS_Bomb("Too many files given.");
306 }
307 }
308 if (!floatFormat)
309 SDDS_CopyString(&floatFormat, "%25.8e");
310 if (!doubleFormat)
311 SDDS_CopyString(&doubleFormat, "%25.16e");
312 if (!ldoubleFormat)
313 SDDS_CopyString(&ldoubleFormat, "%26.18Le");
314 if (!stringFormat)
315 SDDS_CopyString(&stringFormat, "%25s");
316
317 if ((tolerance || relativeTolerance) && precision > 0) {
318 SDDS_Bomb("Tolerance, relativeTolerance, and precision options are not compatible. Only one of tolerance, relativeTolerance, precision, or exact may be given.");
319 }
320 if (tolerance && relativeTolerance) {
321 SDDS_Bomb("Tolerance and relativeTolerance options are not compatible. Only one may be given.");
322 }
323 if (!file1 || !file2) {
324 fprintf(stderr, "Error: Two files must be provided for comparison.\n");
325 exit(EXIT_FAILURE);
326 }
327 if (strcmp(file1, file2) == 0) {
328 printf("\"%s\" and \"%s\" are identical.\n", file1, file2);
329 return EXIT_SUCCESS;
330 }
331 if (!SDDS_InitializeInput(&table1, file1)) {
332 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
333 exit(EXIT_FAILURE);
334 }
335 if (!SDDS_InitializeInput(&table2, file2)) {
336 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
337 exit(EXIT_FAILURE);
338 }
339 if (rowLabelColumn) {
340 if ((rowLabelIndex = SDDS_GetColumnIndex(&table1, rowLabelColumn)) < 0) {
341 if ((rowLabelIndex = SDDS_GetColumnIndex(&table2, rowLabelColumn)) < 0) {
342 fprintf(stdout, "Warning: Row label column \"%s\" does not exist in the input files. The number of rows will be labeled instead.\n", rowLabelColumn);
343 rowLabelColumn = NULL;
344 } else {
345 labelFromSecondFile = 1;
346 notCompareRowLabel = 1;
347 }
348 } else {
349 if (SDDS_GetColumnIndex(&table2, rowLabelColumn) < 0)
350 notCompareRowLabel = 1;
351 }
352
353 if (rowLabelColumn) {
354 if (labelFromSecondFile)
355 rowLabelType = SDDS_GetColumnType(&table2, rowLabelIndex);
356 else
357 rowLabelType = SDDS_GetColumnType(&table1, rowLabelIndex);
358 }
359 }
360 if (!precision) {
361 precisionTolerance = powl(10L, -1L * fabsl(log10l(LDBL_EPSILON)));
362 } else {
363 precisionTolerance = powl(10L, -1L * precision);
364 }
365 if (column_provided) {
366 columnName = getMatchingSDDSNames(&table1, columnMatch, columnMatches, &columns, SDDS_MATCH_COLUMN);
367 if (CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits))
368 different = 1;
369 }
370 if (parameter_provided) {
371 parameterName = getMatchingSDDSNames(&table1, parameterMatch, parameterMatches, &parameters, SDDS_MATCH_PARAMETER);
372
373 if (CompareDefinitions(&table1, &table2, file1, file2, &parameters, &parameterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits))
374 different = 1;
375 }
376 if (array_provided) {
377 arrayName = getMatchingSDDSNames(&table1, arrayMatch, arrayMatches, &arrays, SDDS_MATCH_ARRAY);
378 if (CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits))
379 different = 1;
380 }
381 if (!columns && !parameters && !arrays) {
382 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_COLUMN)
383 different += CompareDefinitions(&table1, &table2, file1, file2, &columns, &columnName, &columnDataType, SDDS_COLUMN_TYPE, compareCommonFlags & COMPARE_COMMON_COLUMN, rowLabelColumn, notCompareRowLabel, ignoreUnits);
384 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_PARAMETER)
385 different += CompareDefinitions(&table1, &table2, file1, file2, &parameters, &parameterName, &parDataType, SDDS_PARAMETER_TYPE, compareCommonFlags & COMPARE_COMMON_PARAMETER, NULL, 1, ignoreUnits);
386 if (!compareCommonFlags || compareCommonFlags & COMPARE_COMMON_ARRAY)
387 different += CompareDefinitions(&table1, &table2, file1, file2, &arrays, &arrayName, &arrayDataType, SDDS_ARRAY_TYPE, compareCommonFlags & COMPARE_COMMON_ARRAY, NULL, 1, ignoreUnits);
388 }
389 if (!different) {
390 if (!columns && !parameters && !arrays) {
391 fprintf(stderr, "There are no common columns, parameters, or arrays in the two files.\n");
392 different = 1;
393 } else {
394 /* Definitions are the same, now compare the data */
395 while (1) {
396 pagediff = 0;
397 pages1 = SDDS_ReadPage(&table1);
398 pages2 = SDDS_ReadPage(&table2);
399 if (pages1 > 0 && pages2 > 0) {
400 /* Compare data */
401 rows1 = SDDS_CountRowsOfInterest(&table1);
402 rows2 = SDDS_CountRowsOfInterest(&table2);
403 if (rows1 != rows2) {
404 pagediff = 1;
405 different = 1;
406 fprintf(stderr, "The two files have different numbers of rows on page %ld: \"%s\" has %" PRId64 " rows, while \"%s\" has %" PRId64 " rows.\n",
407 pages1, file1, rows1, file2, rows2);
408 break;
409 } else {
410 if (parameters)
411 pagediff += CompareData(&table1, &table2, file1, file2, parameters, parameterName, parDataType, SDDS_PARAMETER_TYPE, pages1, tolerance, relativeTolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
412
413 if (columns && rows1) {
414 if (rowLabelColumn) {
415 if (labelFromSecondFile) {
416 if (!(rowLabel = SDDS_GetColumn(&table2, rowLabelColumn)))
417 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
418 } else {
419 if (!(rowLabel = SDDS_GetColumn(&table1, rowLabelColumn)))
420 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
421 }
422 }
423 pagediff += CompareData(&table1, &table2, file1, file2, columns, columnName, columnDataType, SDDS_COLUMN_TYPE, pages1, tolerance, relativeTolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, rowLabel, rowLabelType, rowLabelColumn);
424 if (rowLabelColumn) {
425 if (rowLabelType == SDDS_STRING)
426 SDDS_FreeStringArray((char **)rowLabel, rows1);
427 else
428 free(rowLabel);
429 rowLabel = NULL;
430 }
431 }
432 if (arrays)
433 pagediff += CompareData(&table1, &table2, file1, file2, arrays, arrayName, arrayDataType, SDDS_ARRAY_TYPE, pages1, tolerance, relativeTolerance, precisionTolerance, floatFormat, doubleFormat, ldoubleFormat, stringFormat, absolute, NULL, rowLabelType, NULL);
434 different += pagediff;
435 }
436 } else if (pages1 > 0 && pages2 <= 0) {
437 fprintf(stderr, "\"%s\" has fewer pages than \"%s\".\n", file2, file1);
438 different = 1;
439 break;
440 } else if (pages1 < 0 && pages2 > 0) {
441 different = 1;
442 fprintf(stderr, "\"%s\" has fewer pages than \"%s\".\n", file1, file2);
443 break;
444 } else {
445 break;
446 }
447 }
448 }
449 } else {
450 different = 1;
451 }
452 if (!different)
453 printf("\"%s\" and \"%s\" are identical.\n", file1, file2);
454 else
455 fprintf(stderr, "\"%s\" and \"%s\" are different.\n", file1, file2);
456
457 if (columns) {
458 for (i = 0; i < columns; i++)
459 free(columnName[i]);
460 free(columnName);
461 free(columnDataType);
462 free(columnMatch);
463 }
464 if (parameters) {
465 for (i = 0; i < parameters; i++)
466 free(parameterName[i]);
467 free(parameterName);
468 free(parDataType);
469 free(parameterMatch);
470 }
471 if (arrays) {
472 for (i = 0; i < arrays; i++)
473 free(arrayName[i]);
474 free(arrayName);
475 free(arrayDataType);
476 free(arrayMatch);
477 }
478 free_scanargs(&s_arg, argc);
479 free(stringFormat);
480 free(floatFormat);
481 free(doubleFormat);
482 free(ldoubleFormat);
483
484 if (!SDDS_Terminate(&table1) || !SDDS_Terminate(&table2)) {
485 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
486 exit(EXIT_FAILURE);
487 }
488 return EXIT_SUCCESS;
489}
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:50
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:816
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:318
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:380
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:65
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:588
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 921 of file sddsdiff.c.

921 {
922 char *type = NULL;
923 char *element = NULL;
924
925 switch (flags) {
926 case SDDS_COLUMN_TYPE:
927 SDDS_CopyString(&type, "column");
928 if (labelName)
929 SDDS_CopyString(&element, labelName);
930 else
931 SDDS_CopyString(&element, "row");
932 break;
933 case SDDS_PARAMETER_TYPE:
934 SDDS_CopyString(&type, "parameter");
935 SDDS_CopyString(&element, "page number");
936 break;
937 case SDDS_ARRAY_TYPE:
938 SDDS_CopyString(&type, "array");
939 SDDS_CopyString(&element, "element number");
940 break;
941 }
942 if (type) {
943 fprintf(stdout, "\nDifferences found in %s \"%s\" on page %ld:\n", type, name, page);
944 if (absolute)
945 fprintf(stdout, "%20s%25s%25s%25s\n", element, "Value in file1", "Value in file2", "Difference (abs)");
946 else
947 fprintf(stdout, "%20s%25s%25s%25s\n", element, "Value in file1", "Value in file2", "Difference (file1 - file2)");
948 free(type);
949 free(element);
950 }
951}