SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddscollect.c
Go to the documentation of this file.
1/**
2 * @file sddscollect.c
3 * @brief Collects data from multiple columns into new grouped columns based on specified criteria.
4 *
5 * @details
6 * This file processes SDDS (Self Describing Data Sets) files, enabling users to organize data by
7 * collecting columns with matching suffixes, prefixes, or patterns into grouped columns.
8 * It supports pipelined input/output, warning control, and row/column-major order selection.
9 * Additionally, it enforces strict syntax rules for mutually exclusive options and specific
10 * requirements for certain parameters.
11 *
12 * @section Usage
13 * ```
14 * sddscollect [<input>] [<output>]
15 * [-pipe=[input][,output]]
16 * -collect={suffix=<string>|prefix=<string>|match=<string>}[,column=<newName>][,editCommand=<string>][,exclude=<wildcard>]
17 * [-nowarnings]
18 * [-majorOrder=row|column]
19 * ```
20 *
21 * @section Options
22 * | Required | Description |
23 * |-----------|-----------------------------------------------------------------------------|
24 * | `-collect` | Collects columns based on specified suffix, prefix, or matching pattern. |
25 *
26 * | Option | Description |
27 * |--------------------------------------|---------------------------------------------------------------------------------------|
28 * | `-pipe` | Enables standard SDDS toolkit pipe option for input and output. |
29 * | `-nowarnings` | Suppresses warning messages. |
30 * | `-majorOrder` | Specifies major order of the output file (row-major or column-major). |
31 *
32 * @subsection Incompatibilities
33 * - `-collect`:
34 * - Options `suffix`, `prefix`, and `match` are mutually exclusive.
35 * - When `match` is used, `editCommand` and `column` must also be provided.
36 *
37 * @copyright
38 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
39 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
40 *
41 * @license
42 * This file is distributed under the terms of the Software License Agreement
43 * found in the file LICENSE included with this distribution.
44 *
45 * @author
46 * M. Borland, R. Soliday, L. Emery
47 */
48
49#include "mdb.h"
50#include "SDDS.h"
51#include "SDDSutils.h"
52#include "scan.h"
53#include <ctype.h>
54
55static char *USAGE =
56 "sddscollect [<input>] [<output>]\n"
57 " [-pipe=[input][,output]]\n"
58 " -collect={suffix=<string>|prefix=<string>|match=<string>}[,column=<newName>][,editCommand=<string>][,exclude=<wildcard>]\n"
59 " [-nowarnings]\n"
60 " [-majorOrder=row|column]\n"
61 "Options:\n"
62 " -pipe=[input][,output]\n"
63 " Use the standard SDDS toolkit pipe option for input and output.\n"
64 " -collect={suffix=<string>|prefix=<string>|match=<string>}\n"
65 " Collects columns based on the specified suffix, prefix, or matching pattern.\n"
66 " Additional parameters:\n"
67 " column=<newName> (Optional) Name of the new column. Defaults to suffix or prefix.\n"
68 " editCommand=<string> (Optional) Command to edit the column names.\n"
69 " exclude=<wildcard> (Optional) Exclude columns matching the wildcard pattern.\n"
70 " -nowarnings\n"
71 " Suppresses warning messages.\n"
72 " -majorOrder=row|column\n"
73 " Specifies the major order of the output file. Can be either row-major or column-major.\n"
74 "Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")";
75
76/* Enumeration for option types */
77enum option_type {
78 CLO_COLLECT,
79 CLO_PIPE,
80 CLO_NOWARNINGS,
81 CLO_MAJOR_ORDER,
82 N_OPTIONS
83};
84
85static char *option[N_OPTIONS] = {
86 "collect",
87 "pipe",
88 "nowarnings",
89 "majorOrder",
90};
91
92typedef struct
93{
94 char *part, *newColumn, *match, *editCommand, *exclude;
95 char **oldColumn;
96 void **data;
97 long oldColumns, targetIndex, size;
98 unsigned long flags;
100
101typedef struct
102{
103 char *name;
104 void *data;
105 long size, targetIndex;
107
108#define COLLECTION_SUFFIX 0x0001U
109#define COLLECTION_PREFIX 0x0002U
110#define COLLECTION_COLUMN 0x0004U
111#define COLLECTION_MATCH 0x0008U
112#define COLLECTION_EDIT 0x0010U
113#define COLLECTION_EXCLUDE 0x0020U
114
115long InitializeOutput(SDDS_DATASET *SDDSout, char *output, SDDS_DATASET *SDDSin, COLLECTION *collection, long collections, NEW_PARAMETER **newParameter, int *newParameters, char ***rootname, char ***units, long warnings);
116void CollectAndWriteData(SDDS_DATASET *SDDSout, COLLECTION *collection, long collections, NEW_PARAMETER *newParameter, int newParameters, char **rootname, char **units, long rootnames, int64_t inputRow, long origPage);
117void GetAndOrganizeData(SDDS_DATASET *SDDSin, COLLECTION *collection, long collections, NEW_PARAMETER *newParameter, int newParameters);
118char **ConfirmMatchingColumns(COLLECTION *collection, long collections, SDDS_DATASET *SDDSin, SDDS_DATASET *SDDSout, long *rootnames, char ***units, long warnings);
119
120int main(int argc, char **argv) {
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}
258
259void CollectAndWriteData(SDDS_DATASET *SDDSout, COLLECTION *collection, long collections,
260 NEW_PARAMETER *newParameter, int newParameters, char **rootname,
261 char **units, long rootnames, int64_t inputRow, long origPage) {
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}
294
295void GetAndOrganizeData(SDDS_DATASET *SDDSin, COLLECTION *collection, long collections,
296 NEW_PARAMETER *newParameter, int newParameters) {
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}
311
312long InitializeOutput(SDDS_DATASET *SDDSout, char *output, SDDS_DATASET *SDDSin,
313 COLLECTION *collection, long collections, NEW_PARAMETER **newParameter,
314 int *newParameters, char ***rootname, char ***units, long warnings) {
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}
439
440char **ConfirmMatchingColumns(COLLECTION *collection, long collections, SDDS_DATASET *SDDSin,
441 SDDS_DATASET *SDDSout, long *rootnames, char ***units, long warnings) {
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}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
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.
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.
void * SDDS_GetInternalColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves an internal pointer to the data of a specified column, including all rows.
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_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_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_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
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_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_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.
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.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
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
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
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
Utility functions for SDDS dataset manipulation and string array operations.
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.
int string_cmpasc(const void *a, const void *b)
Compare two strings in ascending order.
int wild_match(char *string, char *template)
Determine whether one string is a wildcard match for another.
Definition wild_match.c:49