SDDSlib
Loading...
Searching...
No Matches
sddstranspose.c
Go to the documentation of this file.
1/**
2 * @file sddstranspose.c
3 * @brief Transposes numerical columns in an SDDS file.
4 *
5 * This program reads an SDDS file with one or more pages, identifies all numerical columns,
6 * and transposes them as though they were a matrix. If the file contains multiple pages,
7 * additional pages are transposed only if they have the same number of rows as the first page.
8 * String columns are converted to string parameters, and string parameters listed in the
9 * "OldStringColumnNames" parameter become string columns in the output. If any string
10 * columns exist, the data in the first string column is used as the names of the columns
11 * in the output file. If no string columns exist, column names are generated from command
12 * line options. The names of the input file columns are saved as a string column in the
13 * output file with a name specified via the command line or the default "OldColumnName".
14 *
15 * ## Usage
16 * ```
17 * sddstranspose <inputfile> <outputfile> [OPTIONS]
18 * ```
19 *
20 * ## Options
21 * -pipe=[input][,output]
22 * -oldColumnNames=<string>
23 * -root=<string>
24 * -digits=<integer>
25 * -newColumnNames=<column>
26 * -symbol=<string>
27 * -ascii
28 * -matchColumn=<string>[,<string>,...]
29 * -indexColumn
30 * -noOldColumnNames
31 * -majorOrder=row|column
32 * -verbose
33 *
34 * @copyright
35 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
36 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
37 *
38 * @license
39 * This file is distributed under the terms of the Software License Agreement
40 * found in the file LICENSE included with this distribution.
41 *
42 * @author M. Borland, C. Saunders, L. Emery, R. Soliday, H. Shang
43 */
44
45#include "mdb.h"
46#include "scan.h"
47#include "match_string.h"
48#include "matlib.h"
49#include "SDDS.h"
50#include "SDDSutils.h"
51
52/* Enumeration for option types */
53enum option_type {
54 CLO_VERBOSE,
55 CLO_COLUMNROOT,
56 CLO_SYMBOL,
57 CLO_ASCII,
58 CLO_PIPE,
59 CLO_OLDCOLUMNNAMES,
60 CLO_NEWCOLUMNNAMES,
61 CLO_DIGITS,
62 CLO_MATCH_COLUMN,
63 CLO_INDEX_COLUMN,
64 CLO_NO_OLDCOLUMNNAMES,
65 CLO_MAJOR_ORDER,
66 N_OPTIONS
67};
68
69char *commandline_option[N_OPTIONS] = {
70 "verbose",
71 "root",
72 "symbol",
73 "ascii",
74 "pipe",
75 "oldColumnNames",
76 "newColumnNames",
77 "digits",
78 "matchColumn",
79 "indexColumn",
80 "noOldColumnNames",
81 "majorOrder",
82};
83
84static char *OLD_STRING_COLUMN_NAMES = "OldStringColumnNames";
85
86static char *USAGE =
87 "Usage: sddstranspose <inputfile> <outputfile> [OPTIONS]\n\n"
88 "Options:\n"
89 " -pipe=[input][,output] Reads input from and/or writes output to a pipe.\n"
90 " -oldColumnNames=<string> Specifies the name for the output file string column created for the input file column names.\n"
91 " -root=<string> Uses the specified string to generate column names of the output file.\n"
92 " Default column names are the first string column in <inputfile>.\n"
93 " If no string column exists, column names are formed with the root \"Column\".\n"
94 " -digits=<integer> Sets the minimum number of digits appended to the root part of the column names.\n"
95 " Default is 3.\n"
96 " -newColumnNames=<column> Uses the specified column as the source for new column names.\n"
97 " -symbol=<string> Uses the specified string for the symbol field in all column definitions.\n"
98 " -ascii Outputs the file in ASCII format. Default is binary.\n"
99 " -matchColumn=<string>[,<string>,...] Only transposes the columns that match the specified names.\n"
100 " -indexColumn Adds an index column to the output file.\n"
101 " -noOldColumnNames Does not create a new column for old column names.\n"
102 " -majorOrder=row|column Specifies the output file's major order (row-major or column-major).\n"
103 " -verbose Prints incidental information to stderr.\n\n"
104 "Link date: " __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION "\n";
105
106char **TokenizeString(char *source, long n_items);
107char *JoinStrings(char **source, long n_items, long buflen_increment);
108
109int main(int argc, char **argv) {
110 SCANNED_ARG *s_arg;
111 SDDS_DATASET inputPage, outputPage;
112
113 char *inputfile, *outputfile;
114 char **inputColumnName, **inputStringColumnName, **inputDoubleColumnName;
115 char **outputStringColumnName, **outputDoubleColumnName, **matchColumn = NULL;
116 long inputDoubleColumns, inputStringColumns, indexColumn = 0, noOldColumnNamesColumn = 0;
117 int64_t inputRows;
118 int32_t matchColumns = 0;
119 long outputRows, outputDoubleColumns, outputStringColumns;
120 char **inputParameterName;
121 int32_t inputParameters;
122 int32_t inputColumns;
123 char *inputDescription, *inputContents;
124 char *outputDescription;
125 long i, i_arg, col;
126 char *buffer;
127 char **columnOfStrings;
128 long buffer_size;
129#define BUFFER_SIZE_INCREMENT 16384
130 MATRIX *R, *RInv;
131 long OldStringColumnsDefined;
132 char *inputStringRows, *outputStringRows;
133 char **stringArray, *stringParameter;
134 long token_length;
135 long verbose;
136 char format[32];
137 long digits;
138 char *Symbol, *Root;
139 void *parameterPointer;
140 long ascii;
141 unsigned long pipeFlags, majorOrderFlag;
142 long tmpfile_used, noWarnings;
143 long ipage = 0, columnType;
144 char *oldColumnNames, *newColumnNamesColumn;
145 short columnMajorOrder = -1;
146
147 inputColumnName = outputStringColumnName = outputDoubleColumnName = inputParameterName = NULL;
148 outputRows = outputDoubleColumns = outputStringColumns = OldStringColumnsDefined = 0;
149
151
152 argc = scanargs(&s_arg, argc, argv);
153 if (argc == 1)
154 bomb(NULL, USAGE);
155
156 inputfile = outputfile = NULL;
157 verbose = 0;
158 Symbol = Root = NULL;
159 ascii = 0;
160 digits = 3;
161 pipeFlags = 0;
162 tmpfile_used = 0;
163 noWarnings = 0;
164 oldColumnNames = NULL;
165 newColumnNamesColumn = NULL;
166
167 for (i_arg = 1; i_arg < argc; i_arg++) {
168 if (s_arg[i_arg].arg_type == OPTION) {
169 switch (match_string(s_arg[i_arg].list[0], commandline_option, N_OPTIONS, UNIQUE_MATCH)) {
170 case CLO_MAJOR_ORDER:
171 majorOrderFlag = 0;
172 s_arg[i_arg].n_items--;
173 if (s_arg[i_arg].n_items > 0 &&
174 (!scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
175 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
176 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
177 SDDS_Bomb("invalid -majorOrder syntax/values");
178 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
179 columnMajorOrder = 1;
180 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
181 columnMajorOrder = 0;
182 break;
183 case CLO_MATCH_COLUMN:
184 matchColumns = s_arg[i_arg].n_items - 1;
185 matchColumn = s_arg[i_arg].list + 1;
186 break;
187 case CLO_INDEX_COLUMN:
188 indexColumn = 1;
189 break;
190 case CLO_NO_OLDCOLUMNNAMES:
191 noOldColumnNamesColumn = 1;
192 break;
193 case CLO_VERBOSE:
194 verbose = 1;
195 break;
196 case CLO_ASCII:
197 ascii = 1;
198 break;
199 case CLO_DIGITS:
200 if (!(get_long(&digits, s_arg[i_arg].list[1])))
201 bomb("No integer provided for option -digits", USAGE);
202 break;
203 case CLO_COLUMNROOT:
204 if (!(Root = s_arg[i_arg].list[1]))
205 SDDS_Bomb("No root string provided with -root option");
206 break;
207 case CLO_SYMBOL:
208 if (!(Symbol = s_arg[i_arg].list[1]))
209 SDDS_Bomb("No symbol string provided with -symbol option");
210 break;
211 case CLO_PIPE:
212 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
213 SDDS_Bomb("Invalid -pipe syntax");
214 break;
215 case CLO_OLDCOLUMNNAMES:
216 if (!(oldColumnNames = s_arg[i_arg].list[1]))
217 SDDS_Bomb("No string provided for -oldColumnNames option");
218 break;
219 case CLO_NEWCOLUMNNAMES:
220 if (s_arg[i_arg].n_items != 2 || SDDS_StringIsBlank(newColumnNamesColumn = s_arg[i_arg].list[1]))
221 SDDS_Bomb("Invalid syntax or value for -newColumnNames option");
222 break;
223 default:
224 bomb("Unrecognized option provided", USAGE);
225 }
226 } else {
227 if (!inputfile)
228 inputfile = s_arg[i_arg].list[0];
229 else if (!outputfile)
230 outputfile = s_arg[i_arg].list[0];
231 else
232 bomb("Too many filenames provided", USAGE);
233 }
234 }
235
236 processFilenames("sddstranspose", &inputfile, &outputfile, pipeFlags, noWarnings, &tmpfile_used);
237 if (newColumnNamesColumn && Root)
238 SDDS_Bomb("-root and -newColumnNames options are incompatible");
239
240 if (!SDDS_InitializeInput(&inputPage, inputfile) ||
241 !(inputParameterName = (char **)SDDS_GetParameterNames(&inputPage, &inputParameters)) ||
242 !SDDS_GetDescription(&inputPage, &inputDescription, &inputContents))
243 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
244
245 if (matchColumns)
246 inputColumnName = getMatchingSDDSNames(&inputPage, matchColumn, matchColumns, &inputColumns, SDDS_MATCH_COLUMN);
247 else {
248 if (!(inputColumnName = (char **)SDDS_GetColumnNames(&inputPage, &inputColumns)))
249 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
250 }
251
252 inputDoubleColumns = 0;
253 inputStringColumns = 0;
254 inputDoubleColumnName = (char **)malloc(inputColumns * sizeof(char *));
255 inputStringColumnName = (char **)malloc(inputColumns * sizeof(char *));
256 inputRows = 0;
257
258 /***********
259 * Read data
260 ***********/
261 while (0 < SDDS_ReadTable(&inputPage)) {
262 ipage++;
263#if defined(DEBUG)
264 fprintf(stderr, "Working on page %ld\n", ipage);
265#endif
266 if (ipage == 1) {
267 if (!SDDS_SetColumnFlags(&inputPage, 0))
268 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
269
270 /* Count the string and numerical columns in the input file */
271 for (i = 0; i < inputColumns; i++) {
272 if (SDDS_NUMERIC_TYPE(columnType = SDDS_GetColumnType(&inputPage, i))) {
273 inputDoubleColumnName[inputDoubleColumns] = inputColumnName[i];
274 inputDoubleColumns++;
275 }
276 }
277 for (i = 0; i < inputPage.layout.n_columns; i++) {
278 if (inputPage.layout.column_definition[i].type == SDDS_STRING) {
279 inputStringColumnName[inputStringColumns] = inputPage.layout.column_definition[i].name;
280 inputStringColumns++;
281 }
282 }
283 if (!(inputRows = SDDS_CountRowsOfInterest(&inputPage)))
284 SDDS_Bomb("No rows in dataset.");
285 } else {
286 /* These statements are executed on subsequent pages */
287 if (inputRows != SDDS_CountRowsOfInterest(&inputPage)) {
288 SDDS_Bomb("Datasets have differing number of rows. Processing stopped before reaching end of input file.");
289 }
290 }
291
292 if (inputRows > INT32_MAX) {
293 SDDS_Bomb("Too many rows in dataset.");
294 }
295
296#if defined(DEBUG)
297 fprintf(stderr, "Row flags set\n");
298#endif
299 if (inputDoubleColumns == 0)
300 SDDS_Bomb("No numerical columns in file.");
301
302 if ((ipage == 1) && verbose) {
303 fprintf(stderr, "Number of numerical columns: %ld.\n", inputDoubleColumns);
304 fprintf(stderr, "Number of string columns: %ld.\n", inputStringColumns);
305 fprintf(stderr, "Number of rows: %" PRId64 ".\n", inputRows);
306 }
307
308 /****************
309 * Transpose data
310 ****************/
311 if (inputDoubleColumns) {
312 if (ipage == 1) {
313 m_alloc(&RInv, inputRows, inputDoubleColumns);
314 m_alloc(&R, inputDoubleColumns, inputRows);
315 }
316 for (col = 0; col < inputDoubleColumns; col++) {
317 if (!(R->a[col] = (double *)SDDS_GetColumnInDoubles(&inputPage, inputDoubleColumnName[col]))) {
318 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
319 }
320 }
321 if (verbose) {
322 m_show(R, "%9.6le ", "Transpose of input matrix:\n", stdout);
323 }
324 m_trans(RInv, R);
325 }
326
327 /***************************
328 * Determine existence of
329 * transposed string columns
330 ***************************/
331 if (ipage == 1) {
332 OldStringColumnsDefined = 0;
333 switch (SDDS_CheckParameter(&inputPage, OLD_STRING_COLUMN_NAMES, NULL, SDDS_STRING, NULL)) {
334 case SDDS_CHECK_OKAY:
335 OldStringColumnsDefined = 1;
336 break;
337 case SDDS_CHECK_NONEXISTENT:
338 break;
339 case SDDS_CHECK_WRONGTYPE:
340 case SDDS_CHECK_WRONGUNITS:
341 fprintf(stderr, "Error: Parameter OldStringColumns has incorrect type or units.\n");
342 exit(EXIT_FAILURE);
343 break;
344 }
345
346 if (OldStringColumnsDefined) {
347 /* Decompose OldStringColumns into names of string columns for the output file */
348 if (!SDDS_GetParameter(&inputPage, OLD_STRING_COLUMN_NAMES, &inputStringRows))
349 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
350
351 if (verbose) {
352 fprintf(stderr, "Parameter OldStringColumns: %s.\n", inputStringRows);
353 }
354
355 outputStringColumnName = (char **)malloc(sizeof(char *));
356 outputStringColumns = 0;
357 buffer_size = BUFFER_SIZE_INCREMENT;
358 buffer = (char *)malloc(sizeof(char) * buffer_size);
359 while (0 <= (token_length = SDDS_GetToken(inputStringRows, buffer, BUFFER_SIZE_INCREMENT))) {
360 if (!token_length)
361 SDDS_Bomb("A null string was detected in parameter OldStringColumns.");
362
363 if (!SDDS_CopyString(&outputStringColumnName[outputStringColumns], buffer))
364 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
365
366 if (verbose) {
367 fprintf(stderr, "Output string column: %s\n", outputStringColumnName[outputStringColumns]);
368 }
369 outputStringColumns++;
370 }
371 }
372 }
373
374 /*********************
375 * Define output page
376 *********************/
377 if (ipage == 1) {
378 outputRows = inputDoubleColumns;
379 outputDoubleColumns = inputRows;
380
381 if (inputDescription) {
382 outputDescription = (char *)malloc(sizeof(char) * (strlen("Transpose of ") + strlen(inputDescription) + 1));
383 strcpy(outputDescription, "Transpose of ");
384 strcat(outputDescription, inputDescription);
385 if (!SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, outputDescription, inputContents, outputfile))
386 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
387 free(outputDescription);
388 } else {
389 if (!SDDS_InitializeOutput(&outputPage, ascii ? SDDS_ASCII : SDDS_BINARY, 1, NULL, NULL, outputfile))
390 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
391 }
392
393 SDDS_DeferSavingLayout(&outputPage, 1);
394
395 if (columnMajorOrder != -1)
396 outputPage.layout.data_mode.column_major = columnMajorOrder;
397 else
398 outputPage.layout.data_mode.column_major = inputPage.layout.data_mode.column_major;
399
400 /***********************************
401 * Define names for numerical columns
402 ***********************************/
403 if (!Root && inputStringColumns) {
404 /* Use specified string column, or first string column encountered */
405 if (!newColumnNamesColumn)
406 /* First string column encountered */
407 outputDoubleColumnName = (char **)SDDS_GetColumn(&inputPage, inputStringColumnName[0]);
408 else {
409 /* Use specified string column */
410 if (SDDS_CheckColumn(&inputPage, newColumnNamesColumn, NULL, SDDS_STRING, stderr) != SDDS_CHECK_OKAY)
411 SDDS_Bomb("Column specified with -newColumnNames does not exist in input file.");
412 outputDoubleColumnName = (char **)SDDS_GetColumn(&inputPage, newColumnNamesColumn);
413 }
414
415 for (i = 1; i < inputRows; i++) {
416 if (match_string(outputDoubleColumnName[i - 1], outputDoubleColumnName + i, inputRows - i, EXACT_MATCH) >= 0) {
417 fprintf(stderr, "Error: Duplicate column name '%s' found in input file string column '%s'. Cannot be used as output column names.\n",
418 outputDoubleColumnName[i - 1], newColumnNamesColumn ? newColumnNamesColumn : inputStringColumnName[0]);
419 exit(EXIT_FAILURE);
420 }
421 }
422 } else {
423 /* Use command line options to generate column names in the output file */
424 outputDoubleColumnName = (char **)malloc(outputDoubleColumns * sizeof(char *));
425 digits = MAX(digits, (long)(log10(inputRows) + 1));
426 if (!Root) {
427 Root = (char *)malloc(sizeof(char) * (strlen("Column") + 1));
428 strcpy(Root, "Column");
429 }
430 if (outputDoubleColumns != 1) {
431 for (i = 0; i < outputDoubleColumns; i++) {
432 outputDoubleColumnName[i] = (char *)malloc(sizeof(char) * (strlen(Root) + digits + 1));
433 sprintf(format, "%s%%0%ldld", Root, digits);
434 sprintf(outputDoubleColumnName[i], format, i);
435 }
436 } else { /* Only one row to transpose */
437 outputDoubleColumnName[0] = (char *)malloc(sizeof(char) * (strlen(Root) + 1));
438 strcpy(outputDoubleColumnName[0], Root);
439 }
440 }
441
442 /*************************
443 * Define string columns
444 *************************/
445 if (OldStringColumnsDefined) {
446 if (!SDDS_DefineSimpleColumns(&outputPage, outputStringColumns, outputStringColumnName, NULL, SDDS_STRING))
447 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
448 } else {
449 /* By default, at least one string column should exist for old column names */
450 if (!noOldColumnNamesColumn) {
451 outputStringColumns = 1;
452 outputStringColumnName = (char **)malloc(sizeof(char *));
453 if (oldColumnNames) {
454 /* Command line option specification */
455 outputStringColumnName[0] = oldColumnNames;
456 } else {
457 outputStringColumnName[0] = (char *)malloc(sizeof(char) * (strlen("OldColumnNames") + 1));
458 strcpy(outputStringColumnName[0], "OldColumnNames");
459 }
460 if (0 > SDDS_DefineColumn(&outputPage, outputStringColumnName[0], NULL, NULL, NULL, NULL, SDDS_STRING, 0))
461 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
462 }
463 }
464
465 if (indexColumn && !SDDS_DefineSimpleColumn(&outputPage, "Index", NULL, SDDS_LONG))
466 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
467
468 /*************************
469 * Define numerical columns
470 *************************/
471 for (i = 0; i < outputDoubleColumns; i++) {
472 if (Symbol) {
473 if (0 > SDDS_DefineColumn(&outputPage, outputDoubleColumnName[i], Symbol, NULL, NULL, NULL, SDDS_DOUBLE, 0))
474 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
475 } else {
476 if (0 > SDDS_DefineColumn(&outputPage, outputDoubleColumnName[i], NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0))
477 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
478 }
479 }
480
481 /********************************
482 * Define string parameters
483 * i.e., transposed string columns
484 ********************************/
485 if (inputStringColumns > 1) {
486 if (0 > SDDS_DefineParameter(&outputPage, OLD_STRING_COLUMN_NAMES, NULL, NULL, "Transposed string columns", NULL, SDDS_STRING, NULL))
487 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
488 for (i = 0; i < inputStringColumns; i++) {
489 if (0 > SDDS_DefineParameter(&outputPage, inputStringColumnName[i], NULL, NULL, "Transposed string column data", NULL, SDDS_STRING, NULL))
490 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
491 }
492 }
493
494 /*************************
495 * Transfer other parameters
496 *************************/
497 if (inputParameters) {
498 for (i = 0; i < inputParameters; i++) {
499 if ((0 > match_string(inputParameterName[i], outputStringColumnName, outputStringColumns, 0) &&
500 strcasecmp(inputParameterName[i], OLD_STRING_COLUMN_NAMES))) {
501 if (0 > SDDS_TransferParameterDefinition(&outputPage, &inputPage, inputParameterName[i], NULL))
502 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
503 }
504 }
505 }
506
507 /***************
508 * Write layout
509 ***************/
510 SDDS_DeferSavingLayout(&outputPage, 0);
511
512 /* If InputFile is not already transferred to the output file, then create it */
513 switch (SDDS_CheckParameter(&outputPage, "InputFile", NULL, SDDS_STRING, NULL)) {
514 case SDDS_CHECK_NONEXISTENT:
515 if (0 > SDDS_DefineParameter(&outputPage, "InputFile", NULL, NULL, "Original matrix file", NULL, SDDS_STRING, NULL))
516 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
517 break;
518 default:
519 break;
520 }
521
522 if (!SDDS_WriteLayout(&outputPage))
523 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
524 }
525
526#if defined(DEBUG)
527 fprintf(stderr, "Table layout defined\n");
528#endif
529
530 if (!SDDS_StartTable(&outputPage, outputRows))
531 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
532 if (ipage == 1) {
533 if (!SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, "InputFile", inputfile ? inputfile : "pipe", NULL))
534 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
535 }
536
537 /***************************************
538 * Assign string columns from input
539 * to string parameters in output
540 ***************************************/
541 if (inputStringColumns > 1) {
542 for (i = 0; i < inputStringColumns; i++) {
543 columnOfStrings = (char **)SDDS_GetColumn(&inputPage, inputStringColumnName[i]);
544 stringParameter = JoinStrings(columnOfStrings, inputRows, BUFFER_SIZE_INCREMENT);
545 if (!SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, inputStringColumnName[i], stringParameter, NULL))
546 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
547 free(columnOfStrings);
548 free(stringParameter);
549 }
550 outputStringRows = JoinStrings(inputStringColumnName, inputStringColumns, BUFFER_SIZE_INCREMENT);
551 if (!SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, OLD_STRING_COLUMN_NAMES, outputStringRows, NULL))
552 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
553 }
554
555#if defined(DEBUG)
556 fprintf(stderr, "String parameters assigned\n");
557#endif
558
559 if (inputParameters) {
560 for (i = 0; i < inputParameters; i++) {
561 if ((0 > match_string(inputParameterName[i], outputStringColumnName, outputStringColumns, 0) &&
562 strcasecmp(inputParameterName[i], OLD_STRING_COLUMN_NAMES))) {
563 parameterPointer = (void *)SDDS_GetParameter(&inputPage, inputParameterName[i], NULL);
564 if (!SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, inputParameterName[i], parameterPointer, NULL))
565 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
566 free(parameterPointer);
567 }
568 }
569 }
570
571#if defined(DEBUG)
572 fprintf(stderr, "Input parameters assigned\n");
573#endif
574
575 /**********************************
576 * Assign data to output table part
577 * of data set
578 **********************************/
579 if (outputRows) {
580 /***************************
581 * Assign string column data
582 ***************************/
583 if (OldStringColumnsDefined) {
584 for (i = 0; i < outputStringColumns; i++) {
585 if (!SDDS_GetParameter(&inputPage, outputStringColumnName[i], &stringParameter))
586 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
587 stringArray = TokenizeString(stringParameter, outputRows);
588 if (!SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, stringArray, outputRows, outputStringColumnName[i]))
589 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
590 free(stringArray);
591 }
592 } else {
593 if (!noOldColumnNamesColumn &&
594 !SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, inputDoubleColumnName, outputRows, outputStringColumnName[0]))
595 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
596 }
597
598#if defined(DEBUG)
599 fprintf(stderr, "String data columns assigned\n");
600#endif
601
602 /***************************
603 * Assign numerical column data
604 ***************************/
605 for (i = 0; i < outputDoubleColumns; i++) /* i is the row index */
606 if (!SDDS_SetColumn(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE, RInv->a[i], outputRows, outputDoubleColumnName[i]))
607 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
608
609 if (indexColumn) {
610 for (i = 0; i < outputRows; i++)
611 if (!SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, i, "Index", i, NULL))
612 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
613 }
614
615#if defined(DEBUG)
616 fprintf(stderr, "Numerical data columns assigned\n");
617#endif
618 }
619
620#if defined(DEBUG)
621 fprintf(stderr, "Data assigned\n");
622#endif
623
624 if (!SDDS_WriteTable(&outputPage))
625 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
626
627#if defined(DEBUG)
628 fprintf(stderr, "Data written out\n");
629#endif
630 }
631
632 if (inputDoubleColumns) {
633 m_free(&RInv);
634 m_free(&R);
635 }
636 if (inputColumnName) {
637 SDDS_FreeStringArray(inputColumnName, inputColumns);
638 free(inputColumnName);
639 }
640 if (inputStringColumns)
641 free(inputStringColumnName);
642 if (inputDescription)
643 free(inputDescription);
644 if (inputParameterName) {
645 SDDS_FreeStringArray(inputParameterName, inputParameters);
646 free(inputParameterName);
647 }
648 if (outputDoubleColumns) {
649 SDDS_FreeStringArray(outputDoubleColumnName, outputDoubleColumns);
650 free(outputDoubleColumnName);
651 }
652
653 if (!SDDS_Terminate(&inputPage))
654 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
655 if (ipage > 0) {
656 if (!SDDS_Terminate(&outputPage))
657 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
658 }
659 if (tmpfile_used && !replaceFileAndBackUp(inputfile, outputfile))
660 exit(EXIT_FAILURE);
661
662 return EXIT_SUCCESS;
663}
664
665char **TokenizeString(char *source, long n_items) {
666 char *buffer;
667 long buflen;
668 char *ptr;
669 char **string_array;
670 long i;
671
672 if (!source)
673 return NULL;
674 ptr = source;
675 string_array = (char **)malloc(sizeof(char *) * n_items);
676 buflen = strlen(source) + 1;
677 buffer = (char *)malloc(sizeof(char) * buflen);
678 for (i = 0; i < n_items; i++) {
679 if (SDDS_GetToken(ptr, buffer, buflen) != -1)
680 SDDS_CopyString(&string_array[i], buffer);
681 else
682 SDDS_CopyString(&string_array[i], "");
683 }
684 free(buffer);
685 return string_array;
686}
687
688char *JoinStrings(char **source, long n_items, long buflen_increment) {
689 char *buffer;
690 char *ptr;
691 long buffer_size, bufferLeft, bufferUsed;
692 long i, slen;
693 char *sptr;
694
695 buffer_size = buflen_increment;
696 buffer = (char *)malloc(sizeof(char) * buffer_size);
697 buffer[0] = '\0';
698 ptr = buffer;
699 bufferLeft = buffer_size - 2;
700 bufferUsed = 0;
701 for (i = 0; i < n_items; i++) {
702 sptr = source[i];
703 slen = strlen(sptr);
704 while ((slen + 5) > bufferLeft) {
705 buffer = trealloc(buffer, sizeof(char) * (buffer_size += buflen_increment));
706 bufferLeft += buflen_increment;
707 ptr = buffer + bufferUsed;
708 }
709 if (i) {
710 slen++;
711 *ptr++ = ' ';
712 }
713 *ptr++ = '"';
714 while (*sptr)
715 *ptr++ = *sptr++;
716 *ptr++ = '"';
717 *ptr = '\0';
718 bufferLeft -= slen + 2;
719 bufferUsed += slen + 2;
720 }
721
722 return buffer;
723}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
void SDDS_DeferSavingLayout(SDDS_DATASET *SDDS_dataset, int32_t mode)
Definition SDDS_copy.c:603
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.
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_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.
int32_t SDDS_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value)
Sets the acceptance flags for all columns in the current data table of a data set.
int32_t SDDS_GetDescription(SDDS_DATASET *SDDS_dataset, char **text, char **contents)
Retrieves the text and contents descriptions from an SDDS dataset.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
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_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_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_DefineSimpleColumns(SDDS_DATASET *SDDS_dataset, int32_t number, char **name, char **unit, int32_t type)
Defines multiple simple data columns of the same data type within the SDDS 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_TransferParameterDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a parameter definition from a source dataset to a target dataset.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
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.
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters 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_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
int32_t SDDS_GetToken(char *s, char *buffer, int32_t buflen)
Extracts the next token from a string, handling quoted substrings and escape characters.
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.
Definition SDDS_utils.c:342
int32_t SDDS_CheckParameter(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a parameter exists in the SDDS dataset with the specified name, units, and type.
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
#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
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
void * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
int get_long(long *iptr, char *s)
Parses a long integer value from the given string.
Definition data_scan.c:255
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.
Definition replacefile.c:75
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.