69char *option[N_OPTIONS] = {
81sddsselect [<input1>] <input2> [<output>]\n\
82 [-pipe[=input][,output]]\n\
83 [-match=<column-name>[=<column-name>]]\n\
84 [-equate=<column-name>[=<column-name>]] \n\
87 [-reuse[=rows][,page]] \n\
88 [-majorOrder=row|column]\n\
91 -pipe[=input][,output] Use pipe for input and/or output.\n\
92 -match=<column1>[=<column2>] Specify columns to match between input1 and input2.\n\
93 -equate=<column1>[=<column2>] Specify columns to equate between input1 and input2.\n\
94 -hashLookup Use a hash table for key lookups (non-wildcard match/equate).\n\
95 -invert Invert the selection to keep non-matching rows.\n\
96 -reuse[=rows][,page] Allow reusing rows or specify page reuse.\n\
97 -majorOrder=row|column Set the output file to row or column major order.\n\
98 -nowarnings Suppress warning messages.\n\
101 sddsselect -match=colA=colB input1.sdds input2.sdds output.sdds\n\
103Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
105int main(
int argc,
char **argv) {
107 long i, j, i_arg, reuse, reusePage;
108 int64_t rows1, rows2, i1, i2;
111 char **match_column, **equate_column;
112 long match_columns, equate_columns;
113 char *input1, *input2, *output;
114 long tmpfile_used, retval1, retval2;
115 long warnings, invert;
116 unsigned long pipeFlags, majorOrderFlag;
117 KEYED_EQUIVALENT **keyGroup = NULL;
119 short columnMajorOrder = -1;
120 long useHashLookup = 0;
123 argc =
scanargs(&s_arg, argc, argv);
127 input1 = input2 = output = NULL;
128 match_column = equate_column = NULL;
129 match_columns = equate_columns = reuse = reusePage = 0;
130 tmpfile_used = invert = 0;
134 for (i_arg = 1; i_arg < argc; i_arg++) {
135 if (s_arg[i_arg].arg_type == OPTION) {
137 switch (
match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
138 case SET_MAJOR_ORDER:
140 s_arg[i_arg].n_items--;
141 if (s_arg[i_arg].n_items > 0 &&
142 (!
scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
143 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
144 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
145 SDDS_Bomb(
"invalid -majorOrder syntax/values");
146 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
147 columnMajorOrder = 1;
148 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
149 columnMajorOrder = 0;
151 case SET_MATCH_COLUMN:
152 if (s_arg[i_arg].n_items != 2)
154 if (match_columns != 0)
155 SDDS_Bomb(
"only one -match option may be given");
156 match_column =
tmalloc(
sizeof(*match_column) * 2);
157 if ((ptr = strchr(s_arg[i_arg].list[1],
'=')))
160 ptr = s_arg[i_arg].list[1];
161 match_column[0] = s_arg[i_arg].list[1];
162 match_column[1] = ptr;
165 case SET_EQUATE_COLUMN:
166 if (s_arg[i_arg].n_items != 2)
168 if (equate_columns != 0)
169 SDDS_Bomb(
"only one -equate option may be given");
170 equate_column =
tmalloc(
sizeof(*equate_column) * 2);
171 if ((ptr = strchr(s_arg[i_arg].list[1],
'=')))
174 ptr = s_arg[i_arg].list[1];
175 equate_column[0] = s_arg[i_arg].list[1];
176 equate_column[1] = ptr;
180 if (s_arg[i_arg].n_items == 1)
183 char *reuseOptions[2] = {
"rows",
"page"};
184 for (i = 1; i < s_arg[i_arg].n_items; i++) {
185 switch (
match_string(s_arg[i_arg].list[i], reuseOptions, 2, 0)) {
206 if (!
processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
209 case SET_HASH_LOOKUP:
213 fprintf(stderr,
"error: unknown switch: %s\n", s_arg[i_arg].list[0]);
219 input1 = s_arg[i_arg].list[0];
220 else if (input2 == NULL)
221 input2 = s_arg[i_arg].list[0];
222 else if (output == NULL)
223 output = s_arg[i_arg].list[0];
229 if (pipeFlags & USE_STDIN && input1) {
231 SDDS_Bomb(
"too many filenames (sddsxref)");
236 processFilenames(
"sddsselect", &input1, &output, pipeFlags, !warnings, &tmpfile_used);
238 SDDS_Bomb(
"second input file not specified (sddsxref)");
240 if (equate_columns && match_columns)
241 SDDS_Bomb(
"only one of -equate or -match may be given");
242 if (!equate_columns && !match_columns)
243 SDDS_Bomb(
"one of -equate or -match must be given");
257 sprintf(s,
"error: column %s not found or not string type in file %s", match_column[0], input1 ? input1 :
"stdin");
263 sprintf(s,
"error: column %s not found or not string type in file %s", match_column[1], input2);
268 if (equate_columns) {
271 sprintf(s,
"error: column %s not found or not numeric type in file %s", equate_column[0], input1 ? input1 :
"stdin");
277 sprintf(s,
"error: column %s not found or not numeric type in file %s", equate_column[1], input2);
283 if (output && pipeFlags & USE_STDOUT)
284 SDDS_Bomb(
"too many filenames with -pipe option");
285 if (!output && !(pipeFlags & USE_STDOUT)) {
287 fprintf(stderr,
"warning: existing file %s will be replaced (sddsselect)\n", input1 ? input1 :
"stdin");
295 if (columnMajorOrder != -1)
296 SDDS_output.layout.data_mode.column_major = columnMajorOrder;
298 SDDS_output.layout.data_mode.column_major = SDDS_1.layout.data_mode.column_major;
306 fprintf(stderr,
"warning: <input2> ends before <input1>\n");
331 SDDS_SetError(
"Problem copying parameter or array data from second input file");
336 SDDS_SetError(
"Problem copying parameter or array data from first input file");
341 char **string1, **string2;
345 fprintf(stderr,
"Error: problem getting column %s from file %s\n", match_column[0], input1 ? input1 :
"stdin");
348 if (rows2 && !(string2 =
SDDS_GetColumn(&SDDS_2, match_column[1]))) {
349 fprintf(stderr,
"Error: problem getting column %s from file %s\n", match_column[1], input2);
355 strHash = SDDS_BuildStrHash(string2, rows2);
359 for (i1 = 0; i1 < rows1; i1++) {
361 sprintf(s,
"Problem copying row %" PRId64
" of first data set", i1);
368 if (SDDS_LookupStr(strHash, string1[i1], reuse) >= 0)
375 if ((!matched && !invert) || (matched && invert)) {
381 for (i = 0; i < rows1; i++)
387 for (i = 0; i < rows2; i++)
392 if (useHashLookup && strHash) {
393 SDDS_FreeStrHash(strHash);
396 for (i = 0; i < keyGroups; i++) {
398 if (keyGroup[i]->equivalent)
399 free(keyGroup[i]->equivalent);
409 }
else if (equate_columns) {
410 double *value1, *value2;
414 fprintf(stderr,
"Error: problem getting column %s from file %s\n", equate_column[0], input1 ? input1 :
"stdin");
418 fprintf(stderr,
"Error: problem getting column %s from file %s\n", equate_column[1], input2);
424 numHash = SDDS_BuildNumHash(value2, rows2);
428 for (i1 = 0; i1 < rows1; i1++) {
430 sprintf(s,
"Problem copying row %" PRId64
" of first data set", i1);
437 if (SDDS_LookupNum(numHash, value1[i1], reuse) >= 0)
444 if ((!equated && !invert) || (equated && invert)) {
455 if (useHashLookup && numHash) {
456 SDDS_FreeNumHash(numHash);
459 for (i = 0; i < keyGroups; i++) {
461 if (keyGroup[i]->equivalent)
462 free(keyGroup[i]->equivalent);
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_CopyRowDirect(SDDS_DATASET *SDDS_target, int64_t target_row, SDDS_DATASET *SDDS_source, int64_t source_row)
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_CopyArrays(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
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.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Header file for routines used by SDDS command-line applications.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_DOUBLE
Identifier for the double data type.
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
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.
long replaceFileAndBackUp(char *file, char *replacement)
Replaces a file with a replacement file and creates a backup of the original.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
void free_scanargs(SCANNED_ARG **scanned, int argc)
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.
KEYED_EQUIVALENT ** MakeSortedKeyGroups(long *keyGroups, long keyType, void *data, long points)
Create sorted key groups from data.
long FindMatchingKeyGroup(KEYED_EQUIVALENT **keyGroup, long keyGroups, long keyType, void *searchKeyData, long reuse)
Find a matching key group for a search key.
char * tmpname(char *s)
Supplies a unique temporary filename.