SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
csv2sdds.c
Go to the documentation of this file.
1/**
2 * @file csv2sdds.c
3 * @brief Converts Comma Separated Values (CSV) data to SDDS format.
4 *
5 * @details
6 * This program reads CSV data from an input file or standard input and converts it into the
7 * SDDS (Self Describing Data Sets) format, writing the output to a specified file or standard output.
8 * It provides various options to customize the conversion process, including handling delimiters,
9 * specifying column data types, and more. The tool also validates combinations of options and applies
10 * specific requirements to ensure proper operation.
11 *
12 * @section Usage
13 * ```
14 * csv2sdds [<inputFile>] [<outputFile>]
15 * [-pipe[=in][,out]]
16 * [-asciiOutput]
17 * [-spanLines]
18 * [-maxRows=<number>]
19 * [-schfile=<filename>]
20 * [-skiplines=<number>]
21 * [-delimiters=start=<start>,end=<char>]
22 * [-separator=<char>]
23 * [-columnData=name=<name>,type=<type>,units=<units>...]
24 * [-uselabels[=units]]
25 * [-majorOrder=row|column]
26 * [-fillIn=<zero|last>]
27 * ```
28 *
29 * @section Options
30 * | Option | Description |
31 * |---------------------------------------|--------------------------------------------------------------------------------------|
32 * | `-pipe` | SDDS toolkit pipe option. |
33 * | `-asciiOutput` | Requests SDDS ASCII output. Default is binary. |
34 * | `-spanLines` | Ignore line breaks in parsing the input data. |
35 * | `-maxRows` | Maximum number of rows to expect in input. |
36 * | `-schfile` | Specifies the SCH file that describes the columns. |
37 * | `-skiplines` | Skip the first `<number>` lines of the input file. |
38 * | `-delimiters` | Specifies the delimiter characters that bracket fields. Default is `"`. |
39 * | `-separator` | Specifies the separator character between fields. Default is `,`. |
40 * | `-columnData` | Specifies column data details corresponding to the input file columns. |
41 * | `-uselabels` | Defines column names and optionally units from the file headers. |
42 * | `-majorOrder` | Specifies the output file major order: row-major or column-major. |
43 * | `-fillIn` | Use `0` or the last value for empty cells. Default is `0`. |
44 *
45 * @subsection Incompatibilities
46 * - Only one of the following may be specified:
47 * - `-columnData`
48 * - `-schfile`
49 * - `-uselabels`
50 * - For `-separator`:
51 * - Must be a single character.
52 *
53 * @copyright
54 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
55 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
56 *
57 * @license
58 * This file is distributed under the terms of the Software License Agreement
59 * found in the file LICENSE included with this distribution.
60 *
61 * @authors
62 * M. Borland, R. Soliday, D. Blachowicz, H. Shang, L. Emery
63 */
64
65#include "mdb.h"
66#include "SDDS.h"
67#include "scan.h"
68#include <ctype.h>
69
70/* Enumeration for option types */
71enum option_type {
72 SET_ASCIIOUTPUT,
73 SET_DELIMITERS,
74 SET_SEPARATOR,
75 SET_COLUMNDATA,
76 SET_SCHFILE,
77 SET_PIPE,
78 SET_SPANLINES,
79 SET_MAXROWS,
80 SET_SKIPLINES,
81 SET_USELABELS,
82 SET_MAJOR_ORDER,
83 SET_FILL_IN,
84 N_OPTIONS
85};
86
87char *option[N_OPTIONS] = {
88 "asciioutput",
89 "delimiters",
90 "separator",
91 "columndata",
92 "schfile",
93 "pipe",
94 "spanlines",
95 "maxrows",
96 "skiplines",
97 "uselabels",
98 "majorOrder",
99 "fillIn",
100};
101
102char *USAGE =
103 "\n"
104 " csv2sdds [<inputFile>] [<outputFile>]\n"
105 " [-pipe[=in][,out]]\n"
106 " [-asciiOutput] \n"
107 " [-spanLines] \n"
108 " [-maxRows=<number>]\n"
109 " [-schfile=<filename>] \n"
110 " [-skiplines=<number>]\n"
111 " [-delimiters=start=<start>,end=<char>] \n"
112 " [-separator=<char>]\n"
113 " [-columnData=name=<name>,type=<type>,units=<units>...]\n"
114 " [-uselabels[=units]] \n"
115 " [-majorOrder=row|column]\n"
116 " [-fillIn=<zero|last>]\n"
117 "Options:\n"
118 " -pipe[=in][,out] SDDS toolkit pipe option.\n"
119 " -asciiOutput Requests SDDS ASCII output. Default is binary.\n"
120 " -spanLines Ignore line breaks in parsing the input data.\n"
121 " -maxRows=<number> Maximum number of rows to expect in input.\n"
122 " -schfile=<filename> Specifies the SCH file that describes the columns.\n"
123 " -skiplines=<number> Skip the first <number> lines of the input file.\n"
124 " -delimiters=start=<char>,end=<char> Specifies the delimiter characters that bracket fields.\n"
125 " The default is '\"' for both start and end delimiters.\n"
126 " -separator=<char> Specifies the separator character between fields. The default is ','.\n"
127 " -columnData=name=<name>,type=<type>,units=<units>...\n"
128 " Specifies column data details. Must be provided in the order\n"
129 " corresponding to the data columns in the input file.\n"
130 " -uselabels[=units] Defines column names and optionally units from the file headers.\n"
131 " -majorOrder=row|column Specifies the output file major order. Choose between row-major or column-major.\n"
132 " -fillIn=<zero|last> Use '0' or the last value for empty cells. The default is '0'.\n\n"
133 "Description:\n"
134 " Converts Comma Separated Values (CSV) data to the SDDS format.\n"
135 " Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
136
137typedef struct
138{
139 char *name, *units;
140 long type, index;
142
143long ParseSchFile(char *file, COLUMN_DATA **columnData, char *separator, char *startDelim, char *endDelim);
144void SetUpOutputFile(SDDS_DATASET *SDDSout, char *input, char *output, COLUMN_DATA *columnData, long columns,
145 long asciiOutput, short columnMajorOrder);
146char *getToken(char *s, char separator, char startDelim, char endDelim, char *buffer);
147void writeOneRowToOutputFile(SDDS_DATASET *SDDSout, char *ptr, char separator, char startDelim, char endDelim,
148 long spanLines, COLUMN_DATA *columnData, long columns, int64_t rows, short fillInZero);
149void lowerstring(char *ptr);
150
151int main(int argc, char **argv) {
152 FILE *fpi;
153 char *input, *output, *schFile;
154 SDDS_DATASET SDDSout;
155 SCANNED_ARG *scanned;
156 long i, iArg;
157 int64_t rows, maxRows;
158 long asciiOutput, columns, spanLines, skipLines = 0, lines;
159 short columnlabels = 0, unitlabels = 0, uselabels = 0;
160 COLUMN_DATA *columnData;
161 char separator, startDelim, endDelim;
162 char s[10240], *ptr, *typeName, *unitsName;
163 unsigned long dummyFlags, pipeFlags, majorOrderFlag, fillInFlag;
164 short columnMajorOrder = 0, fillInZero = 1;
165
167 argc = scanargs(&scanned, argc, argv);
168 if (argc < 3) {
169 bomb(NULL, USAGE);
170 }
171 input = output = schFile = NULL;
172 asciiOutput = spanLines = columns = 0;
173 pipeFlags = 0;
174 columnData = NULL;
175 separator = ',';
176 startDelim = '\"';
177 endDelim = '\"';
178 maxRows = 10000;
179
180 for (iArg = 1; iArg < argc; iArg++) {
181 if (scanned[iArg].arg_type == OPTION) {
182 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
183 case SET_MAJOR_ORDER:
184 majorOrderFlag = 0;
185 scanned[iArg].n_items--;
186 if (scanned[iArg].n_items > 0 &&
187 (!scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
188 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
189 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
190 SDDS_Bomb("invalid -majorOrder syntax/values");
191 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
192 columnMajorOrder = 1;
193 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
194 columnMajorOrder = 0;
195 break;
196 case SET_ASCIIOUTPUT:
197 asciiOutput = 1;
198 break;
199 case SET_FILL_IN:
200 fillInFlag = 0;
201 scanned[iArg].n_items--;
202 if (scanned[iArg].n_items > 0 &&
203 (!scanItemList(&fillInFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
204 "zero", -1, NULL, 0, 0x0001UL,
205 "last", -1, NULL, 0, 0x0002UL, NULL)))
206 SDDS_Bomb("invalid -fillIn syntax/values");
207 if (fillInFlag & 0x0001UL)
208 fillInZero = 1;
209 else if (fillInFlag & 0x0002UL)
210 fillInZero = 0;
211 break;
212 case SET_DELIMITERS:
213 if (!(scanned[iArg].n_items -= 1) ||
214 !scanItemList(&dummyFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
215 "start", SDDS_CHARACTER, &startDelim, 1, 0,
216 "end", SDDS_CHARACTER, &endDelim, 1, 0, NULL)) {
217 SDDS_Bomb("invalid -delimiters syntax");
218 }
219 scanned[iArg].n_items++;
220 break;
221 case SET_SEPARATOR:
222 if (scanned[iArg].n_items != 2 || strlen(scanned[iArg].list[1]) < 1)
223 SDDS_Bomb("invalid -separator syntax");
224 interpret_escapes(scanned[iArg].list[1]);
225 separator = scanned[iArg].list[1][0];
226 break;
227 case SET_COLUMNDATA:
228 columnData = SDDS_Realloc(columnData, sizeof(*columnData) * (columns + 1));
229 columnData[columns].name = NULL;
230 columnData[columns].units = NULL;
231 unitsName = NULL;
232 typeName = "string";
233 if (!(scanned[iArg].n_items -= 1) ||
234 !scanItemList(&dummyFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
235 "name", SDDS_STRING, &(columnData[columns].name), 1, 0,
236 "units", SDDS_STRING, &unitsName, 1, 0,
237 "type", SDDS_STRING, &typeName, 1, 0, NULL) ||
238 !columnData[columns].name ||
239 !strlen(columnData[columns].name) ||
240 !typeName ||
241 !(columnData[columns].type = SDDS_IdentifyType(typeName)))
242 SDDS_Bomb("invalid -columnData syntax");
243 scanned[iArg].n_items++;
244 columnData[columns].units = unitsName;
245 columns++;
246 break;
247 case SET_SCHFILE:
248 if (scanned[iArg].n_items != 2)
249 SDDS_Bomb("invalid -schFile syntax");
250 schFile = scanned[iArg].list[1];
251 if (!fexists(schFile)) {
252 fprintf(stderr, "File not found: %s (csv2sdds)\n", schFile);
253 exit(EXIT_FAILURE);
254 }
255 break;
256 case SET_PIPE:
257 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
258 SDDS_Bomb("invalid -pipe syntax");
259 break;
260 case SET_SPANLINES:
261 spanLines = 1;
262 break;
263 case SET_MAXROWS:
264 if (scanned[iArg].n_items != 2 ||
265 strlen(scanned[iArg].list[1]) < 1 ||
266 sscanf(scanned[iArg].list[1], "%" SCNd64, &maxRows) != 1 ||
267 maxRows < 1)
268 SDDS_Bomb("invalid -maxRows syntax");
269 break;
270 case SET_SKIPLINES:
271 if (scanned[iArg].n_items != 2 ||
272 strlen(scanned[iArg].list[1]) < 1 ||
273 sscanf(scanned[iArg].list[1], "%ld", &skipLines) != 1 ||
274 skipLines < 1)
275 SDDS_Bomb("invalid -skiplines syntax");
276 break;
277 case SET_USELABELS:
278 if (scanned[iArg].n_items > 2)
279 SDDS_Bomb("invalid -uselabels syntax");
280 uselabels = 1;
281 columnlabels = 1;
282 if (scanned[iArg].n_items == 2)
283 unitlabels = 1;
284 break;
285 default:
286 bomb("Invalid option encountered.", USAGE);
287 break;
288 }
289 } else {
290 if (!input)
291 input = scanned[iArg].list[0];
292 else if (!output)
293 output = scanned[iArg].list[0];
294 else {
295 bomb("Too many filenames provided.", USAGE);
296 }
297 }
298 }
299
300 if (!columns && !schFile && !columnlabels)
301 SDDS_Bomb("Specify at least one of -columnData, -schFile, or -uselabels options.");
302 if (columns && schFile)
303 SDDS_Bomb("Specify either -columnData options or -schFile option, not both.");
304 if (columns && columnlabels)
305 SDDS_Bomb("Specify either -columnData options or -uselabels option, not both.");
306 if (schFile && columnlabels)
307 SDDS_Bomb("Specify either -schFile option or -uselabels option, not both.");
308
309 processFilenames("csv2sdds", &input, &output, pipeFlags, 0, NULL);
310 if (input) {
311 if (!fexists(input))
312 SDDS_Bomb("Input file not found.");
313 if (!(fpi = fopen(input, "r")))
314 SDDS_Bomb("Problem opening input file.");
315 } else {
316 fpi = stdin;
317 }
318
319 if (!columnlabels) {
320 if (!columns && !(columns = ParseSchFile(schFile, &columnData, &separator, &startDelim, &endDelim)))
321 SDDS_Bomb("Problem reading or parsing SCH file.");
322
323 SetUpOutputFile(&SDDSout, input, output, columnData, columns, asciiOutput, columnMajorOrder);
324
325 if (!SDDS_StartPage(&SDDSout, maxRows))
326 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
327 }
328 rows = 0; /* the row index we are storing in */
329 lines = 0;
330
331 while (fgets(s, sizeof(s), fpi)) {
332 lines++;
333 /* Convert unprintable characters to null */
334 while ((i = strlen(s)) && s[i - 1] < 27)
335 s[i - 1] = 0;
336 /* Ignore empty lines after skipping specified number of lines */
337 if (strlen(s) == 0 && (skipLines && (lines > skipLines)))
338 break;
339 ptr = s;
340#if defined(DEBUG)
341 fprintf(stderr, "line: >%s<\n", ptr);
342#endif
343 if (columnlabels && (!skipLines || (lines > skipLines))) {
344 char t[10240];
345 t[0] = 0;
346 while (1) {
347 ptr = getToken(ptr, separator, startDelim, endDelim, t);
348 if (strlen(t) == 0)
349 break;
350 columnData = SDDS_Realloc(columnData, sizeof(*columnData) * (columns + 1));
351 columnData[columns].name = malloc(strlen(t) + 1);
352 replace_chars(t, (char *)" ", (char *)"_");
353 sprintf(columnData[columns].name, "%s", t);
354 columnData[columns].units = NULL;
355 columnData[columns].type = SDDS_STRING;
356 columns++;
357 }
358 columnlabels = 0;
359 continue;
360 } else if (unitlabels && (!skipLines || (lines > skipLines))) {
361 char t[10240];
362 t[0] = 0;
363 for (i = 0; i < columns; i++) {
364 ptr = getToken(ptr, separator, startDelim, endDelim, t);
365 if (strlen(t) > 0) {
366 columnData[i].units = malloc(strlen(t) + 1);
367 sprintf(columnData[i].units, "%s", t);
368 } else {
369 columnData[i].units = NULL;
370 }
371 }
372 unitlabels = 0;
373 continue;
374 }
375 if (uselabels) {
376 char *tmpPtr;
377 char t[10240];
378 double tD;
379 t[0] = 0;
380 tmpPtr = ptr;
381 for (i = 0; i < columns; i++) {
382 tmpPtr = getToken(tmpPtr, separator, startDelim, endDelim, t);
383 if (strlen(t) == 0)
384 break;
385 if (sscanf(t, "%lf", &tD) == 1)
386 columnData[i].type = SDDS_DOUBLE;
387 }
388 SetUpOutputFile(&SDDSout, input, output, columnData, columns, asciiOutput, columnMajorOrder);
389 if (!SDDS_StartPage(&SDDSout, maxRows))
390 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
391 uselabels = 0;
392 }
393 if (!skipLines || (lines > skipLines)) {
394 writeOneRowToOutputFile(&SDDSout, ptr, separator, startDelim, endDelim, spanLines, columnData, columns, rows, fillInZero);
395 rows++;
396 }
397 if (rows >= maxRows - 1) {
398 if (!SDDS_LengthenTable(&SDDSout, 1000)) {
399 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
400 }
401 maxRows += 1000;
402 }
403 }
404
405 fclose(fpi);
406 if (!SDDS_WritePage(&SDDSout) || !SDDS_Terminate(&SDDSout))
407 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
408
409 free_scanargs(&scanned, argc);
410
411 return EXIT_SUCCESS;
412}
413
414long ParseSchFile(char *file, COLUMN_DATA **columnData, char *separator, char *startDelim, char *endDelim) {
415 FILE *fp;
416 char s[10240], *ptr, *ptr0;
417 long l, fieldIndex, lastFieldIndex, columns;
418
419 if (!(fp = fopen(file, "r"))) {
420 SDDS_Bomb("Unable to open SCH file");
421 }
422
423 lastFieldIndex = 0;
424 columns = 0;
425 while (fgets(s, sizeof(s), fp)) {
426 while ((l = strlen(s)) && s[l - 1] < 27)
427 s[l - 1] = 0;
428 if (strlen(s) == 0)
429 continue;
430 if (!(ptr = strchr(s, '=')))
431 continue;
432 *ptr++ = 0;
433 if (strcmp(s, "Filetype") == 0) {
434 if (strcmp(ptr, "Delimited"))
435 SDDS_Bomb("Require Filetype = Delimited in SCH file.");
436 } else if (strcmp(s, "Separator") == 0) {
437 if (!(*separator = *ptr))
438 SDDS_Bomb("Null separator in SCH file.");
439 } else if (strcmp(s, "Delimiter") == 0) {
440 if (!(*endDelim = *startDelim = *ptr))
441 SDDS_Bomb("Null delimiter in SCH file.");
442 } else if (strcmp(s, "CharSet") == 0) {
443 if (strcmp(ptr, "ascii"))
444 SDDS_Bomb("Require CharSet = ascii in SCH file.");
445 } else if (strncmp(s, "Field", strlen("Field")) == 0) {
446 if (!sscanf(s, "Field%ld", &fieldIndex))
447 SDDS_Bomb("Error scanning field index in SCH file.");
448 if (fieldIndex - lastFieldIndex != 1)
449 SDDS_Bomb("Gap or nonmonotonicity in field index values.");
450 lastFieldIndex = fieldIndex;
451 *columnData = SDDS_Realloc(*columnData, sizeof(**columnData) * (columns + 1));
452 delete_chars(ptr, " ");
453 ptr0 = ptr;
454 if (!(ptr = strchr(ptr0, ',')))
455 SDDS_Bomb("Field name not found.");
456 *ptr = 0;
457 SDDS_CopyString(&((*columnData)[columns].name), ptr0);
458 (*columnData)[columns].units = NULL;
459 ptr0 = ptr + 1;
460 if (!(ptr = strchr(ptr0, ',')))
461 SDDS_Bomb("Field type not found.");
462 *ptr = 0;
463
464 lowerstring(ptr0);
465 if (strcmp(ptr0, "string") == 0)
466 (*columnData)[columns].type = SDDS_STRING;
467 else if (strcmp(ptr0, "char") == 0)
468 (*columnData)[columns].type = SDDS_STRING;
469 else if (strcmp(ptr0, "float") == 0)
470 (*columnData)[columns].type = SDDS_FLOAT;
471 else if (strcmp(ptr0, "double") == 0)
472 (*columnData)[columns].type = SDDS_DOUBLE;
473 else {
474 fprintf(stderr, "Unknown type '%s' given to '%s'\n", ptr0, (*columnData)[columns].name);
475 exit(EXIT_FAILURE);
476 }
477 columns++;
478 } else {
479 fprintf(stderr, "Warning: unknown tag value in SCH file: %s\n", s);
480 }
481 }
482 fclose(fp);
483 return columns;
484}
485
486void SetUpOutputFile(SDDS_DATASET *SDDSout, char *input, char *output, COLUMN_DATA *columnData, long columns, long asciiOutput, short columnMajorOrder) {
487 char s[10240];
488 long i;
489
490 sprintf(s, "csv2sdds conversion of %s", input ? input : "stdin");
491
492 if (!SDDS_InitializeOutput(SDDSout, asciiOutput ? SDDS_ASCII : SDDS_BINARY, 1, NULL, s, output))
493 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
494 SDDSout->layout.data_mode.column_major = columnMajorOrder;
495 for (i = 0; i < columns; i++) {
496 if ((columnData[i].index = SDDS_DefineColumn(SDDSout, columnData[i].name, NULL, columnData[i].units, NULL, NULL, columnData[i].type, 0)) < 0) {
497 sprintf(s, "Problem defining column %s.", columnData[i].name);
498 SDDS_SetError(s);
499 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
500 }
501 }
502 if (!SDDS_WriteLayout(SDDSout))
503 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
504}
505
506char *getToken(char *s, /* the string to be scanned */
507 char separator, /* typically , */
508 char startDelim, /* typically " */
509 char endDelim, /* typically " */
510 char *buffer /* place to put the result */
511 ) {
512 char *ptr;
513 if (*s == 0) {
514 buffer[0] = 0;
515 return s;
516 }
517
518 if (*s == separator) {
519 /* zero-length token */
520 buffer[0] = 0;
521 /* advance to next position */
522 return s + 1;
523 }
524
525 /* Check for quotes. If found, return quote-bounded data. */
526 if (*s == startDelim) {
527 s++;
528 ptr = s;
529 while (*ptr) {
530 if (*ptr == endDelim && *(ptr - 1) != '\\') {
531 ptr++;
532 break;
533 }
534 ptr++;
535 }
536 strncpy(buffer, s, ptr - s - 1);
537 buffer[ptr - s - 1] = 0;
539 if (*ptr && *ptr == separator)
540 return ptr + 1;
541 return ptr;
542 }
543
544 /* advance until the next separator is found */
545 ptr = s;
546 while (*ptr && *ptr != separator)
547 ptr++;
548 if (*ptr == separator) {
549 strncpy(buffer, s, ptr - s);
550 buffer[ptr - s] = 0;
551 return ptr + 1;
552 }
553 strcpy(buffer, s);
554 buffer[ptr - s] = 0;
555 return ptr;
556}
557
558void writeOneRowToOutputFile(SDDS_DATASET *SDDSout, char *ptr, char separator, char startDelim, char endDelim, long spanLines, COLUMN_DATA *columnData, long columns, int64_t rows, short fillInZero) {
559 int column = 0;
560 char t[10240];
561 double doubleValue;
562 float floatValue;
563 short shortValue;
564 unsigned short ushortValue;
565 long nullData = 0;
566 int32_t longValue;
567 uint32_t ulongValue;
568 int64_t long64Value;
569 uint64_t ulong64Value;
570 char charValue;
571 t[0] = 0;
572
573 for (column = 0; column < columns; column++) {
574 ptr = getToken(ptr, separator, startDelim, endDelim, t);
575#if defined(DEBUG)
576 fprintf(stderr, "token: >%s<\n", t);
577#endif
578 nullData = 0;
579 if (strlen(trim_spaces(t)) == 0)
580 nullData = 1;
581 if (nullData && spanLines) {
582 break;
583 }
584 switch (columnData[column].type) {
585 case SDDS_SHORT:
586 if (nullData || sscanf(t, "%hd", &shortValue) != 1) {
587 if (fillInZero) {
588 shortValue = 0;
589 } else {
590 if (rows == 0)
591 shortValue = 0;
592 else
593 shortValue = ((short *)SDDSout->data[columnData[column].index])[rows - 1];
594 }
595 }
596 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, shortValue, -1))
597 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
598 break;
599 case SDDS_USHORT:
600 if (nullData || sscanf(t, "%hu", &ushortValue) != 1) {
601 if (fillInZero) {
602 ushortValue = 0;
603 } else {
604 if (rows == 0)
605 ushortValue = 0;
606 else
607 ushortValue = ((unsigned short *)SDDSout->data[columnData[column].index])[rows - 1];
608 }
609 }
610 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, ushortValue, -1))
611 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
612 break;
613 case SDDS_LONG:
614 if (nullData || sscanf(t, "%" SCNd32, &longValue) != 1) {
615 if (fillInZero) {
616 longValue = 0;
617 } else {
618 if (rows == 0)
619 longValue = 0;
620 else
621 longValue = ((int32_t *)SDDSout->data[columnData[column].index])[rows - 1];
622 }
623 }
624 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, longValue, -1))
625 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
626 break;
627 case SDDS_ULONG:
628 if (nullData || sscanf(t, "%" SCNu32, &ulongValue) != 1) {
629 if (fillInZero) {
630 ulongValue = 0;
631 } else {
632 if (rows == 0)
633 ulongValue = 0;
634 else
635 ulongValue = ((uint32_t *)SDDSout->data[columnData[column].index])[rows - 1];
636 }
637 }
638 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, ulongValue, -1))
639 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
640 break;
641 case SDDS_LONG64:
642 if (nullData || sscanf(t, "%" SCNd64, &long64Value) != 1) {
643 if (fillInZero) {
644 long64Value = 0;
645 } else {
646 if (rows == 0)
647 long64Value = 0;
648 else
649 long64Value = ((int64_t *)SDDSout->data[columnData[column].index])[rows - 1];
650 }
651 }
652 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, long64Value, -1))
653 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
654 break;
655 case SDDS_ULONG64:
656 if (nullData || sscanf(t, "%" SCNu64, &ulong64Value) != 1) {
657 if (fillInZero) {
658 ulong64Value = 0;
659 } else {
660 if (rows == 0)
661 ulong64Value = 0;
662 else
663 ulong64Value = ((uint64_t *)SDDSout->data[columnData[column].index])[rows - 1];
664 }
665 }
666 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, ulong64Value, -1))
667 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
668 break;
669 case SDDS_FLOAT:
670 if (nullData || sscanf(t, "%f", &floatValue) != 1) {
671 if (fillInZero) {
672 floatValue = 0.0f;
673 } else {
674 if (rows == 0)
675 floatValue = 0.0f;
676 else
677 floatValue = ((float *)SDDSout->data[columnData[column].index])[rows - 1];
678 }
679 }
680 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, floatValue, -1))
681 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
682 break;
683 case SDDS_DOUBLE:
684 if (nullData || sscanf(t, "%lf", &doubleValue) != 1) {
685 if (fillInZero) {
686 doubleValue = 0.0;
687 } else {
688 if (rows == 0)
689 doubleValue = 0.0;
690 else
691 doubleValue = ((double *)SDDSout->data[columnData[column].index])[rows - 1];
692 }
693 }
694 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, doubleValue, -1))
695 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
696 break;
697 case SDDS_CHARACTER:
698 if (nullData || sscanf(t, "%c", &charValue) != 1) {
699 if (fillInZero) {
700 charValue = 0;
701 } else {
702 if (rows == 0)
703 charValue = 0;
704 else
705 charValue = ((char *)SDDSout->data[columnData[column].index])[rows - 1];
706 }
707 }
708 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, charValue, -1))
709 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
710 break;
711 case SDDS_STRING:
713 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, t, -1))
714 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
715 break;
716 default:
717 SDDS_Bomb("Unknown or unsupported data type encountered.");
718 }
719 }
720}
721
722void lowerstring(char *ptr) {
723 int size, i;
724 size = strlen(ptr);
725 for (i = 0; i < size; i++)
726 ptr[i] = tolower((unsigned char)ptr[i]);
727}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_LengthenTable(SDDS_DATASET *SDDS_dataset, int64_t n_additional_rows)
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_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_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.
void SDDS_InterpretEscapes(char *s)
Interprets and converts escape sequences in a string.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:421
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:474
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:318
int32_t SDDS_IdentifyType(char *typeName)
Identifies the SDDS data type based on its string name.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:380
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:922
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:743
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
Definition SDDStypes.h:67
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
char * delete_chars(char *s, char *t)
Removes all occurrences of characters found in string t from string s.
long fexists(const char *filename)
Checks if a file exists.
Definition fexists.c:27
void interpret_escaped_quotes(char *s)
Processes a string to interpret and replace escaped quotation marks.
void interpret_escapes(char *s)
Interpret C escape sequences in a string.
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.
char * replace_chars(char *s, char *from, char *to)
Maps one set of characters to another in a given string.
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:357
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:391
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:588
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.
char * trim_spaces(char *s)
Trims leading and trailing spaces from a string.
Definition trim_spaces.c:28