SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddscollect.c File Reference

Detailed Description

Collects data from multiple columns into new grouped columns based on specified criteria.

This file processes SDDS (Self Describing Data Sets) files, enabling users to organize data by collecting columns with matching suffixes, prefixes, or patterns into grouped columns. It supports pipelined input/output, warning control, and row/column-major order selection. Additionally, it enforces strict syntax rules for mutually exclusive options and specific requirements for certain parameters.

Usage

sddscollect [<input>] [<output>]
[-pipe=[input][,output]]
-collect={suffix=<string>|prefix=<string>|match=<string>}[,column=<newName>][,editCommand=<string>][,exclude=<wildcard>]
[-nowarnings]
[-majorOrder=row|column]

Options

Required Description
-collect Collects columns based on specified suffix, prefix, or matching pattern.
Option Description
-pipe Enables standard SDDS toolkit pipe option for input and output.
-nowarnings Suppresses warning messages.
-majorOrder Specifies major order of the output file (row-major or column-major).

Incompatibilities

  • -collect:
    • Options suffix, prefix, and match are mutually exclusive.
    • When match is used, editCommand and column must also be provided.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, R. Soliday, L. Emery

Definition in file sddscollect.c.

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

Go to the source code of this file.

Functions

long InitializeOutput (SDDS_DATASET *SDDSout, char *output, SDDS_DATASET *SDDSin, COLLECTION *collection, long collections, NEW_PARAMETER **newParameter, int *newParameters, char ***rootname, char ***units, long warnings)
 
void CollectAndWriteData (SDDS_DATASET *SDDSout, COLLECTION *collection, long collections, NEW_PARAMETER *newParameter, int newParameters, char **rootname, char **units, long rootnames, int64_t inputRow, long origPage)
 
void GetAndOrganizeData (SDDS_DATASET *SDDSin, COLLECTION *collection, long collections, NEW_PARAMETER *newParameter, int newParameters)
 
char ** ConfirmMatchingColumns (COLLECTION *collection, long collections, SDDS_DATASET *SDDSin, SDDS_DATASET *SDDSout, long *rootnames, char ***units, long warnings)
 
int main (int argc, char **argv)
 

Function Documentation

◆ CollectAndWriteData()

void CollectAndWriteData ( SDDS_DATASET * SDDSout,
COLLECTION * collection,
long collections,
NEW_PARAMETER * newParameter,
int newParameters,
char ** rootname,
char ** units,
long rootnames,
int64_t inputRow,
long origPage )

Definition at line 259 of file sddscollect.c.

261 {
262 long ic, ip, ir;
263 if (rootnames) {
264 if (!SDDS_SetColumn(SDDSout, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, rootname, rootnames, "Rootname")) {
265 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
266 }
267 if (!SDDS_SetColumn(SDDSout, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, units, rootnames, "Units")) {
268 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
269 }
270 for (ic = 0; ic < collections; ic++) {
271 for (ir = 0; ir < rootnames; ir++) {
272 if (!SDDS_SetRowValues(SDDSout, SDDS_PASS_BY_REFERENCE | SDDS_SET_BY_INDEX,
273 ir, collection[ic].targetIndex,
274 ((char *)(collection[ic].data[ir])) + inputRow * collection[ic].size, -1)) {
275 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
276 }
277 }
278 }
279 }
280
281 for (ip = 0; ip < newParameters; ip++) {
282 if (!SDDS_SetParameters(SDDSout, SDDS_PASS_BY_REFERENCE | SDDS_SET_BY_NAME,
283 newParameter[ip].name,
284 ((char *)(newParameter[ip].data) + inputRow * newParameter[ip].size), NULL)) {
285 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
286 }
287 }
288 if (!SDDS_SetParameters(SDDSout, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME,
289 "OriginalPage", origPage, NULL) ||
290 !SDDS_WritePage(SDDSout)) {
291 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
292 }
293}
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432

◆ ConfirmMatchingColumns()

char ** ConfirmMatchingColumns ( COLLECTION * collection,
long collections,
SDDS_DATASET * SDDSin,
SDDS_DATASET * SDDSout,
long * rootnames,
char *** units,
long warnings )

Definition at line 440 of file sddscollect.c.

441 {
442 long ic, ip, ii, partLength;
443 char **rootname, editBuffer[1024];
444 char saveChar;
445
446 partLength = 0;
447 rootname = NULL;
448 *units = NULL;
449 *rootnames = 0;
450 if (!collections)
451 return NULL;
452 for (ic = 0; ic < collections; ic++) {
453 if (!collection[ic].oldColumns)
454 continue;
455 if (collection[ic].part)
456 partLength = strlen(collection[ic].part);
457 if (collection[ic].part && collection[ic].flags & COLLECTION_SUFFIX) {
458 /* sort collection according to truncated string */
459 saveChar = collection[ic].part[0];
460 for (ip = 0; ip < collection[ic].oldColumns; ip++)
461 collection[ic].oldColumn[ip][strlen(collection[ic].oldColumn[ip]) - partLength] = 0;
462 qsort(collection[ic].oldColumn, collection[ic].oldColumns, sizeof(*collection[ic].oldColumn), string_cmpasc);
463 /* now restore the strings (column names) to original form */
464 for (ip = 0; ip < collection[ic].oldColumns; ip++)
465 collection[ic].oldColumn[ip][strlen(collection[ic].oldColumn[ip])] = saveChar;
466 } else {
467 qsort(collection[ic].oldColumn, collection[ic].oldColumns, sizeof(*collection[ic].oldColumn), string_cmpasc);
468 }
469 if (rootname)
470 continue;
471 *rootnames = collection[ic].oldColumns;
472 if (!(rootname = (char **)malloc(sizeof(*rootname) * (*rootnames)))) {
473 SDDS_Bomb("Memory allocation failure");
474 }
475 if (!(*units = (char **)malloc(sizeof(**units) * (*rootnames)))) {
476 SDDS_Bomb("Memory allocation failure");
477 }
478 for (ip = 0; ip < (*rootnames); ip++) {
479 if (SDDS_GetColumnInformation(SDDSin, "units", *units + ip, SDDS_GET_BY_NAME, collection[ic].oldColumn[ip]) != SDDS_STRING) {
480 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
481 }
482 if (collection[ic].flags & COLLECTION_EDIT) {
483 strcpy(editBuffer, collection[ic].oldColumn[ip]);
484 if (!edit_string(editBuffer, collection[ic].editCommand)) {
485 SDDS_Bomb("Problem editing column name.");
486 }
487 SDDS_CopyString(rootname + ip, editBuffer);
488 } else if (collection[ic].flags & COLLECTION_PREFIX) {
489 SDDS_CopyString(rootname + ip, collection[ic].oldColumn[ip] + partLength);
490 } else {
491 SDDS_CopyString(rootname + ip, collection[ic].oldColumn[ip]);
492 rootname[ip][strlen(rootname[ip]) - partLength] = 0;
493 }
494 }
495 }
496 if (!(*rootnames))
497 return NULL;
498
499 for (ic = 0; ic < collections; ic++) {
500 if (!collection[ic].oldColumns)
501 continue;
502 if (collection[ic].oldColumns != (*rootnames)) {
503 fprintf(stderr, "Error (sddscollect): Groups have different numbers of members\n");
504 for (ip = 0; ip < collections; ip++) {
505 fprintf(stderr, "%ld in %s\n", collection[ip].oldColumns,
506 collection[ip].part ? collection[ip].part : collection[ip].match);
507 }
508 exit(EXIT_FAILURE);
509 }
510 if (collection[ic].flags & COLLECTION_MATCH)
511 continue;
512 for (ip = 0; ip < collection[ic].oldColumns; ip++)
513 if (strstr(collection[ic].oldColumn[ip], rootname[ip]) == NULL) {
514 fprintf(stderr, "Error (sddscollect): Mismatch with rootname %s for column %s in group %s\n",
515 rootname[ip], collection[ic].oldColumn[ip],
516 collection[ic].part ? collection[ic].part : collection[ic].match);
517 /* about to bomb here, so it's okay to reuse these indices */
518 for (ic = 0; ic < collections; ic++) {
519 fprintf(stderr, "Group %s (%ld):\n",
520 collection[ic].part ? collection[ic].part : collection[ic].match, ic);
521 for (ip = 0; ip < collection[ic].oldColumns; ip++)
522 fprintf(stderr, " old column[%ld] = %s\n", ip, collection[ic].oldColumn[ip]);
523 }
524 exit(EXIT_FAILURE);
525 }
526 }
527
528 for (ic = 0; ic < collections; ic++) {
529 char *units;
530 int32_t type = 0;
531 long unitsMismatch;
532 if (!collection[ic].oldColumns)
533 continue;
534 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, collection[ic].oldColumn[0], collection[ic].newColumn) ||
535 (collection[ic].targetIndex = SDDS_GetColumnIndex(SDDSout, collection[ic].newColumn)) < 0 ||
536 SDDS_GetColumnInformation(SDDSout, "units", &units, SDDS_GET_BY_NAME, collection[ic].newColumn) != SDDS_STRING ||
537 SDDS_GetColumnInformation(SDDSout, "type", &type, SDDS_GET_BY_NAME, collection[ic].newColumn) != SDDS_LONG) {
538 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
539 }
540 collection[ic].size = SDDS_GetTypeSize(type);
541 unitsMismatch = 0;
542 for (ii = 1; ii < collection[ic].oldColumns; ii++) {
543 if (SDDS_CheckColumn(SDDSin, collection[ic].oldColumn[ii], NULL, type, stderr) == SDDS_CHECK_WRONGTYPE) {
544 fprintf(stderr, "Error (sddscollect): Inconsistent data types for suffix/prefix/match %s\n",
545 collection[ic].part ? collection[ic].part : collection[ic].match);
546 exit(EXIT_FAILURE);
547 }
548 if (SDDS_CheckColumn(SDDSin, collection[ic].oldColumn[ii], units, type, NULL) == SDDS_CHECK_WRONGUNITS)
549 unitsMismatch = 1;
550 }
551 if (unitsMismatch) {
552 if (warnings)
553 fprintf(stderr, "Warning (sddscollect): Inconsistent units for suffix/prefix %s\n", collection[ic].part);
554 if (!SDDS_ChangeColumnInformation(SDDSout, "units", "?", SDDS_BY_NAME, collection[ic].newColumn)) {
555 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
556 }
557 }
558 }
559
560 return rootname;
561}
int32_t SDDS_ChangeColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Modifies a specific field in a column definition within the SDDS dataset.
Definition SDDS_info.c:364
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
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
int32_t SDDS_GetTypeSize(int32_t type)
Retrieves the size in bytes of a specified SDDS data type.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
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
long edit_string(char *text, char *edit)
Edits the provided text based on the specified edit commands.
Definition edit_string.c:75
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
int string_cmpasc(const void *a, const void *b)
Compare two strings in ascending order.

◆ GetAndOrganizeData()

void GetAndOrganizeData ( SDDS_DATASET * SDDSin,
COLLECTION * collection,
long collections,
NEW_PARAMETER * newParameter,
int newParameters )

Definition at line 295 of file sddscollect.c.

296 {
297 long ic, ip, ii;
298 for (ic = 0; ic < collections; ic++) {
299 for (ii = 0; ii < collection[ic].oldColumns; ii++) {
300 if (!(collection[ic].data[ii] = SDDS_GetInternalColumn(SDDSin, collection[ic].oldColumn[ii]))) {
301 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
302 }
303 }
304 }
305 for (ip = 0; ip < newParameters; ip++) {
306 if (!(newParameter[ip].data = SDDS_GetColumn(SDDSin, newParameter[ip].name))) {
307 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
308 }
309 }
310}
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".
void * SDDS_GetInternalColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves an internal pointer to the data of a specified column, including all rows.

◆ InitializeOutput()

long InitializeOutput ( SDDS_DATASET * SDDSout,
char * output,
SDDS_DATASET * SDDSin,
COLLECTION * collection,
long collections,
NEW_PARAMETER ** newParameter,
int * newParameters,
char *** rootname,
char *** units,
long warnings )

Definition at line 312 of file sddscollect.c.

314 {
315 char **inputColumn, *partString;
316 long partLength, *inputLength;
317 int32_t inputColumns;
318 short *inputUsed;
319 long ic, ii, ip, inputsUsed, rootnames;
320 char *matchString, *excludeString;
321
322 partLength = 0;
323 inputLength = NULL;
324
325 if (!SDDS_InitializeOutput(SDDSout, SDDS_BINARY, 0, NULL, "sddscollect output", output) ||
326 !SDDS_TransferAllParameterDefinitions(SDDSout, SDDSin, 0) ||
327 !SDDS_TransferAllArrayDefinitions(SDDSout, SDDSin, 0)) {
328 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
329 }
330
331 if (!(inputColumn = SDDS_GetColumnNames(SDDSin, &inputColumns)) || inputColumns == 0) {
332 SDDS_Bomb("No columns in input file");
333 }
334 if (!(inputUsed = (short *)calloc(inputColumns, sizeof(*inputUsed))) ||
335 !(inputLength = (long *)calloc(inputColumns, sizeof(*inputLength)))) {
336 SDDS_Bomb("Memory allocation failure");
337 }
338 for (ii = 0; ii < inputColumns; ii++)
339 inputLength[ii] = strlen(inputColumn[ii]);
340
341 inputsUsed = 0;
342 matchString = NULL;
343 excludeString = NULL;
344 for (ic = 0; ic < collections; ic++) {
345 if (!collection[ic].newColumn)
346 SDDS_CopyString(&collection[ic].newColumn, collection[ic].part);
347 if ((partString = collection[ic].part))
348 partLength = strlen(partString);
349 if (collection[ic].match) {
350 matchString = collection[ic].match;
351 partLength = -1;
352 }
353 if (collection[ic].exclude) {
354 excludeString = collection[ic].exclude;
355 }
356 collection[ic].oldColumn = NULL;
357 collection[ic].oldColumns = 0;
358 for (ii = 0; ii < inputColumns; ii++) {
359 if (inputUsed[ii])
360 continue;
361 if (partLength >= inputLength[ii])
362 continue;
363 if (matchString) {
364 if (wild_match(inputColumn[ii], matchString)) {
365 if ((excludeString == NULL) || (!wild_match(inputColumn[ii], excludeString))) {
366 if (!(collection[ic].oldColumn = SDDS_Realloc(collection[ic].oldColumn,
367 sizeof(*collection[ic].oldColumn) * (collection[ic].oldColumns + 1)))) {
368 SDDS_Bomb("Memory allocation failure");
369 }
370 collection[ic].oldColumn[collection[ic].oldColumns] = inputColumn[ii];
371 inputUsed[ii] = 1;
372 inputsUsed++;
373 collection[ic].oldColumns++;
374 }
375 }
376 } else if (collection[ic].flags & COLLECTION_PREFIX) {
377 if (strncmp(partString, inputColumn[ii], partLength) == 0) {
378 if (!(collection[ic].oldColumn = SDDS_Realloc(collection[ic].oldColumn,
379 sizeof(*collection[ic].oldColumn) * (collection[ic].oldColumns + 1)))) {
380 SDDS_Bomb("Memory allocation failure");
381 }
382 collection[ic].oldColumn[collection[ic].oldColumns] = inputColumn[ii];
383 inputUsed[ii] = 1;
384 inputsUsed++;
385 collection[ic].oldColumns++;
386 }
387 } else {
388 if (strcmp(partString, inputColumn[ii] + inputLength[ii] - partLength) == 0) {
389 if (!(collection[ic].oldColumn = SDDS_Realloc(collection[ic].oldColumn,
390 sizeof(*collection[ic].oldColumn) * (collection[ic].oldColumns + 1)))) {
391 SDDS_Bomb("Memory allocation failure");
392 }
393 collection[ic].oldColumn[collection[ic].oldColumns] = inputColumn[ii];
394 inputUsed[ii] = 1;
395 inputsUsed++;
396 collection[ic].oldColumns++;
397 }
398 }
399 }
400 if (!collection[ic].oldColumns && warnings) {
401 fprintf(stderr, "Warning (sddscollect): No columns in input for %s %s\n",
402 collection[ic].flags & COLLECTION_PREFIX ? "prefix" : "suffix", collection[ic].part);
403 }
404 if (!(collection[ic].data = (void **)calloc(collection[ic].oldColumns, sizeof(*collection[ic].data)))) {
405 SDDS_Bomb("Memory allocation failure");
406 }
407 }
408
409 if ((*newParameters = inputColumns - inputsUsed)) {
410 *newParameter = (NEW_PARAMETER *)malloc(sizeof(**newParameter) * (*newParameters));
411 for (ii = ip = 0; ii < inputColumns; ii++) {
412 if (inputUsed[ii])
413 continue;
414 if (!SDDS_CopyString(&(*newParameter)[ip].name, inputColumn[ii]) ||
415 !SDDS_DefineParameterLikeColumn(SDDSout, SDDSin, inputColumn[ii], NULL) ||
416 ((*newParameter)[ip].targetIndex = SDDS_GetParameterIndex(SDDSout, inputColumn[ii])) < 0) {
417 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
418 }
419 (*newParameter)[ip].size = SDDS_GetTypeSize(SDDS_GetParameterType(SDDSout, (*newParameter)[ip].targetIndex));
420 ip++;
421 }
422 }
423
424 *rootname = ConfirmMatchingColumns(collection, collections, SDDSin, SDDSout, &rootnames, units, warnings);
425
426 if (SDDS_DefineParameter(SDDSout, "OriginalPage", NULL, NULL, NULL, NULL, SDDS_LONG, NULL) < 0) {
427 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
428 }
429 if (rootnames &&
430 (SDDS_DefineColumn(SDDSout, "Rootname", NULL, NULL, NULL, NULL, SDDS_STRING, 0) < 0 ||
431 SDDS_DefineColumn(SDDSout, "Units", NULL, NULL, NULL, NULL, SDDS_STRING, 0) < 0)) {
432 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
433 }
434 if (!SDDS_WriteLayout(SDDSout)) {
435 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
436 }
437 return rootnames;
438}
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
int32_t SDDS_TransferAllArrayDefinitions(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, uint32_t mode)
Transfers all array definitions from a source dataset to a target dataset.
int32_t SDDS_TransferAllParameterDefinitions(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, uint32_t mode)
Transfers all parameter definitions from a source dataset to a target dataset.
int32_t SDDS_DefineParameterLikeColumn(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Defines a parameter in the target dataset based on a column definition from the source dataset.
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_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
int wild_match(char *string, char *template)
Determine whether one string is a wildcard match for another.
Definition wild_match.c:49

◆ main()

int main ( int argc,
char ** argv )

Definition at line 120 of file sddscollect.c.

120 {
121 long iArg, ic;
122 SDDS_DATASET SDDSin, SDDSout;
123 SCANNED_ARG *scanned;
124 unsigned long pipeFlags, flags, majorOrderFlag;
125 COLLECTION *collection;
126 NEW_PARAMETER *newParameter;
127 char **rootname, **units;
128 long collections, rootnames, code;
129 int newParameters = 0;
130 int64_t rows, row;
131 char *input, *output;
132 long warnings;
133 short columnMajorOrder = -1;
134
136
137 argc = scanargs(&scanned, argc, argv);
138 if (argc == 1) {
139 bomb(NULL, USAGE);
140 return EXIT_FAILURE;
141 }
142
143 input = output = NULL;
144 collection = NULL;
145 collections = 0;
146 pipeFlags = 0;
147 warnings = 1;
148
149 for (iArg = 1; iArg < argc; iArg++) {
150 if (scanned[iArg].arg_type == OPTION) {
151 /* process options here */
152 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
153 case CLO_MAJOR_ORDER:
154 majorOrderFlag = 0;
155 scanned[iArg].n_items--;
156 if (scanned[iArg].n_items > 0 &&
157 (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
158 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
159 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
160 SDDS_Bomb("Invalid -majorOrder syntax/values");
161 }
162 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
163 columnMajorOrder = 1;
164 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
165 columnMajorOrder = 0;
166 break;
167 case CLO_COLLECT:
168 if (!(collection = SDDS_Realloc(collection, sizeof(*collection) * (collections + 1)))) {
169 SDDS_Bomb("Memory allocation failure");
170 }
171 ic = collections;
172 collection[ic].newColumn = collection[ic].part = collection[ic].match = collection[ic].editCommand = NULL;
173 collection[ic].exclude = NULL;
174 if (--scanned[iArg].n_items == 0 ||
175 !scanItemList(&flags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
176 "suffix", SDDS_STRING, &collection[ic].part, 1, COLLECTION_SUFFIX,
177 "prefix", SDDS_STRING, &collection[ic].part, 1, COLLECTION_PREFIX,
178 "column", SDDS_STRING, &collection[ic].newColumn, 1, COLLECTION_COLUMN,
179 "match", SDDS_STRING, &collection[ic].match, 1, COLLECTION_MATCH,
180 "editcommand", SDDS_STRING, &collection[ic].editCommand, 1, COLLECTION_EDIT,
181 "exclude", SDDS_STRING, &collection[ic].exclude, 1, COLLECTION_EXCLUDE, NULL) ||
182 ((flags & COLLECTION_SUFFIX && flags & COLLECTION_PREFIX) ||
183 (flags & COLLECTION_SUFFIX && flags & COLLECTION_MATCH) ||
184 (flags & COLLECTION_PREFIX && flags & COLLECTION_MATCH))) {
185 SDDS_Bomb("Invalid -collect syntax");
186 }
187 if (flags & COLLECTION_MATCH &&
188 (!(flags & COLLECTION_EDIT) || !(flags & COLLECTION_COLUMN))) {
189 SDDS_Bomb("Invalid -collect syntax: must give editCommand and column with match");
190 }
191 collection[ic].flags = flags;
192 collections++;
193 break;
194 case CLO_PIPE:
195 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags)) {
196 SDDS_Bomb("Invalid -pipe syntax");
197 }
198 break;
199 case CLO_NOWARNINGS:
200 warnings = 0;
201 break;
202 default:
203 fprintf(stderr, "Invalid option seen: %s\n", scanned[iArg].list[0]);
204 exit(EXIT_FAILURE);
205 break;
206 }
207 } else {
208 if (!input)
209 input = scanned[iArg].list[0];
210 else if (!output)
211 output = scanned[iArg].list[0];
212 else
213 SDDS_Bomb("Too many filenames");
214 }
215 }
216
217 if (!collections) {
218 SDDS_Bomb("At least one -collect option must be given");
219 }
220
221 processFilenames("sddscollect", &input, &output, pipeFlags, !warnings, NULL);
222
223 if (!SDDS_InitializeInput(&SDDSin, input)) {
224 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
225 }
226
227 rootnames = InitializeOutput(&SDDSout, output, &SDDSin, collection, collections,
228 &newParameter, &newParameters, &rootname, &units, warnings);
229 if (columnMajorOrder != -1)
230 SDDSout.layout.data_mode.column_major = columnMajorOrder;
231 else
232 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
233
234 while ((code = SDDS_ReadPage(&SDDSin)) > 0) {
235 if (!SDDS_StartPage(&SDDSout, rootnames) ||
236 !SDDS_CopyParameters(&SDDSout, &SDDSin) ||
237 !SDDS_CopyArrays(&SDDSout, &SDDSin)) {
238 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
239 }
240 if ((rows = SDDS_CountRowsOfInterest(&SDDSin)) > 0) {
241 GetAndOrganizeData(&SDDSin, collection, collections, newParameter, newParameters);
242 for (row = 0; row < rows; row++) {
243 CollectAndWriteData(&SDDSout, collection, collections, newParameter, newParameters,
244 rootname, units, rootnames, row, code);
245 if (row != rows - 1 && !SDDS_StartPage(&SDDSout, rootnames)) {
246 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
247 }
248 }
249 } else if (!SDDS_WritePage(&SDDSout)) {
250 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
251 }
252 }
253 if (!code || !SDDS_Terminate(&SDDSout) || !SDDS_Terminate(&SDDSin)) {
254 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
255 }
256 return EXIT_SUCCESS;
257}
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
int32_t SDDS_CopyArrays(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:334
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
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)
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
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.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
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.