SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
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>]
[-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 numerical comparison tolerance.
-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 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)
 

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

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

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

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

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

904 {
905 char *type = NULL;
906 char *element = NULL;
907
908 switch (flags) {
909 case SDDS_COLUMN_TYPE:
910 SDDS_CopyString(&type, "column");
911 if (labelName)
912 SDDS_CopyString(&element, labelName);
913 else
914 SDDS_CopyString(&element, "row");
915 break;
916 case SDDS_PARAMETER_TYPE:
917 SDDS_CopyString(&type, "parameter");
918 SDDS_CopyString(&element, "page number");
919 break;
920 case SDDS_ARRAY_TYPE:
921 SDDS_CopyString(&type, "array");
922 SDDS_CopyString(&element, "element number");
923 break;
924 }
925 if (type) {
926 fprintf(stdout, "\nDifferences found in %s \"%s\" on page %ld:\n", type, name, page);
927 if (absolute)
928 fprintf(stdout, "%20s%25s%25s%25s\n", element, "Value in file1", "Value in file2", "Difference (abs)");
929 else
930 fprintf(stdout, "%20s%25s%25s%25s\n", element, "Value in file1", "Value in file2", "Difference (file1 - file2)");
931 free(type);
932 free(element);
933 }
934}