SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
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 break;
367 columnData[i].units = malloc(strlen(t) + 1);
368 sprintf(columnData[i].units, "%s", t);
369 }
370 unitlabels = 0;
371 continue;
372 }
373 if (uselabels) {
374 char *tmpPtr;
375 char t[10240];
376 double tD;
377 t[0] = 0;
378 tmpPtr = ptr;
379 for (i = 0; i < columns; i++) {
380 tmpPtr = getToken(tmpPtr, separator, startDelim, endDelim, t);
381 if (strlen(t) == 0)
382 break;
383 if (sscanf(t, "%lf", &tD) == 1)
384 columnData[i].type = SDDS_DOUBLE;
385 }
386 SetUpOutputFile(&SDDSout, input, output, columnData, columns, asciiOutput, columnMajorOrder);
387 if (!SDDS_StartPage(&SDDSout, maxRows))
388 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
389 uselabels = 0;
390 }
391 if (!skipLines || (lines > skipLines)) {
392 writeOneRowToOutputFile(&SDDSout, ptr, separator, startDelim, endDelim, spanLines, columnData, columns, rows, fillInZero);
393 rows++;
394 }
395 if (rows >= maxRows - 1) {
396 if (!SDDS_LengthenTable(&SDDSout, 1000)) {
397 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
398 }
399 maxRows += 1000;
400 }
401 }
402
403 fclose(fpi);
404 if (!SDDS_WritePage(&SDDSout) || !SDDS_Terminate(&SDDSout))
405 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
406
407 free_scanargs(&scanned, argc);
408
409 return EXIT_SUCCESS;
410}
411
412long ParseSchFile(char *file, COLUMN_DATA **columnData, char *separator, char *startDelim, char *endDelim) {
413 FILE *fp;
414 char s[10240], *ptr, *ptr0;
415 long l, fieldIndex, lastFieldIndex, columns;
416
417 if (!(fp = fopen(file, "r"))) {
418 SDDS_Bomb("Unable to open SCH file");
419 }
420
421 lastFieldIndex = 0;
422 columns = 0;
423 while (fgets(s, sizeof(s), fp)) {
424 while ((l = strlen(s)) && s[l - 1] < 27)
425 s[l - 1] = 0;
426 if (strlen(s) == 0)
427 continue;
428 if (!(ptr = strchr(s, '=')))
429 continue;
430 *ptr++ = 0;
431 if (strcmp(s, "Filetype") == 0) {
432 if (strcmp(ptr, "Delimited"))
433 SDDS_Bomb("Require Filetype = Delimited in SCH file.");
434 } else if (strcmp(s, "Separator") == 0) {
435 if (!(*separator = *ptr))
436 SDDS_Bomb("Null separator in SCH file.");
437 } else if (strcmp(s, "Delimiter") == 0) {
438 if (!(*endDelim = *startDelim = *ptr))
439 SDDS_Bomb("Null delimiter in SCH file.");
440 } else if (strcmp(s, "CharSet") == 0) {
441 if (strcmp(ptr, "ascii"))
442 SDDS_Bomb("Require CharSet = ascii in SCH file.");
443 } else if (strncmp(s, "Field", strlen("Field")) == 0) {
444 if (!sscanf(s, "Field%ld", &fieldIndex))
445 SDDS_Bomb("Error scanning field index in SCH file.");
446 if (fieldIndex - lastFieldIndex != 1)
447 SDDS_Bomb("Gap or nonmonotonicity in field index values.");
448 lastFieldIndex = fieldIndex;
449 *columnData = SDDS_Realloc(*columnData, sizeof(**columnData) * (columns + 1));
450 delete_chars(ptr, " ");
451 ptr0 = ptr;
452 if (!(ptr = strchr(ptr0, ',')))
453 SDDS_Bomb("Field name not found.");
454 *ptr = 0;
455 SDDS_CopyString(&((*columnData)[columns].name), ptr0);
456 (*columnData)[columns].units = NULL;
457 ptr0 = ptr + 1;
458 if (!(ptr = strchr(ptr0, ',')))
459 SDDS_Bomb("Field type not found.");
460 *ptr = 0;
461
462 lowerstring(ptr0);
463 if (strcmp(ptr0, "string") == 0)
464 (*columnData)[columns].type = SDDS_STRING;
465 else if (strcmp(ptr0, "char") == 0)
466 (*columnData)[columns].type = SDDS_STRING;
467 else if (strcmp(ptr0, "float") == 0)
468 (*columnData)[columns].type = SDDS_FLOAT;
469 else if (strcmp(ptr0, "double") == 0)
470 (*columnData)[columns].type = SDDS_DOUBLE;
471 else {
472 fprintf(stderr, "Unknown type '%s' given to '%s'\n", ptr0, (*columnData)[columns].name);
473 exit(EXIT_FAILURE);
474 }
475 columns++;
476 } else {
477 fprintf(stderr, "Warning: unknown tag value in SCH file: %s\n", s);
478 }
479 }
480 fclose(fp);
481 return columns;
482}
483
484void SetUpOutputFile(SDDS_DATASET *SDDSout, char *input, char *output, COLUMN_DATA *columnData, long columns, long asciiOutput, short columnMajorOrder) {
485 char s[10240];
486 long i;
487
488 sprintf(s, "csv2sdds conversion of %s", input ? input : "stdin");
489
490 if (!SDDS_InitializeOutput(SDDSout, asciiOutput ? SDDS_ASCII : SDDS_BINARY, 1, NULL, s, output))
491 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
492 SDDSout->layout.data_mode.column_major = columnMajorOrder;
493 for (i = 0; i < columns; i++) {
494 if ((columnData[i].index = SDDS_DefineColumn(SDDSout, columnData[i].name, NULL, columnData[i].units, NULL, NULL, columnData[i].type, 0)) < 0) {
495 sprintf(s, "Problem defining column %s.", columnData[i].name);
496 SDDS_SetError(s);
497 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
498 }
499 }
500 if (!SDDS_WriteLayout(SDDSout))
501 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
502}
503
504char *getToken(char *s, /* the string to be scanned */
505 char separator, /* typically , */
506 char startDelim, /* typically " */
507 char endDelim, /* typically " */
508 char *buffer /* place to put the result */
509 ) {
510 char *ptr;
511 if (*s == 0) {
512 buffer[0] = 0;
513 return s;
514 }
515
516 if (*s == separator) {
517 /* zero-length token */
518 buffer[0] = 0;
519 /* advance to next position */
520 return s + 1;
521 }
522
523 /* Check for quotes. If found, return quote-bounded data. */
524 if (*s == startDelim) {
525 s++;
526 ptr = s;
527 while (*ptr) {
528 if (*ptr == endDelim && *(ptr - 1) != '\\') {
529 ptr++;
530 break;
531 }
532 ptr++;
533 }
534 strncpy(buffer, s, ptr - s - 1);
535 buffer[ptr - s - 1] = 0;
537 if (*ptr && *ptr == separator)
538 return ptr + 1;
539 return ptr;
540 }
541
542 /* advance until the next separator is found */
543 ptr = s;
544 while (*ptr && *ptr != separator)
545 ptr++;
546 if (*ptr == separator) {
547 strncpy(buffer, s, ptr - s);
548 buffer[ptr - s] = 0;
549 return ptr + 1;
550 }
551 strcpy(buffer, s);
552 buffer[ptr - s] = 0;
553 return ptr;
554}
555
556void writeOneRowToOutputFile(SDDS_DATASET *SDDSout, char *ptr, char separator, char startDelim, char endDelim, long spanLines, COLUMN_DATA *columnData, long columns, int64_t rows, short fillInZero) {
557 int column = 0;
558 char t[10240];
559 double doubleValue;
560 float floatValue;
561 short shortValue;
562 unsigned short ushortValue;
563 long nullData = 0;
564 int32_t longValue;
565 uint32_t ulongValue;
566 int64_t long64Value;
567 uint64_t ulong64Value;
568 char charValue;
569 t[0] = 0;
570
571 for (column = 0; column < columns; column++) {
572 ptr = getToken(ptr, separator, startDelim, endDelim, t);
573#if defined(DEBUG)
574 fprintf(stderr, "token: >%s<\n", t);
575#endif
576 nullData = 0;
577 if (strlen(trim_spaces(t)) == 0)
578 nullData = 1;
579 if (nullData && spanLines) {
580 break;
581 }
582 switch (columnData[column].type) {
583 case SDDS_SHORT:
584 if (nullData || sscanf(t, "%hd", &shortValue) != 1) {
585 if (fillInZero) {
586 shortValue = 0;
587 } else {
588 if (rows == 0)
589 shortValue = 0;
590 else
591 shortValue = ((short *)SDDSout->data[columnData[column].index])[rows - 1];
592 }
593 }
594 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, shortValue, -1))
595 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
596 break;
597 case SDDS_USHORT:
598 if (nullData || sscanf(t, "%hu", &ushortValue) != 1) {
599 if (fillInZero) {
600 ushortValue = 0;
601 } else {
602 if (rows == 0)
603 ushortValue = 0;
604 else
605 ushortValue = ((unsigned short *)SDDSout->data[columnData[column].index])[rows - 1];
606 }
607 }
608 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, ushortValue, -1))
609 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
610 break;
611 case SDDS_LONG:
612 if (nullData || sscanf(t, "%" SCNd32, &longValue) != 1) {
613 if (fillInZero) {
614 longValue = 0;
615 } else {
616 if (rows == 0)
617 longValue = 0;
618 else
619 longValue = ((int32_t *)SDDSout->data[columnData[column].index])[rows - 1];
620 }
621 }
622 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, longValue, -1))
623 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
624 break;
625 case SDDS_ULONG:
626 if (nullData || sscanf(t, "%" SCNu32, &ulongValue) != 1) {
627 if (fillInZero) {
628 ulongValue = 0;
629 } else {
630 if (rows == 0)
631 ulongValue = 0;
632 else
633 ulongValue = ((uint32_t *)SDDSout->data[columnData[column].index])[rows - 1];
634 }
635 }
636 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, ulongValue, -1))
637 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
638 break;
639 case SDDS_LONG64:
640 if (nullData || sscanf(t, "%" SCNd64, &long64Value) != 1) {
641 if (fillInZero) {
642 long64Value = 0;
643 } else {
644 if (rows == 0)
645 long64Value = 0;
646 else
647 long64Value = ((int64_t *)SDDSout->data[columnData[column].index])[rows - 1];
648 }
649 }
650 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, long64Value, -1))
651 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
652 break;
653 case SDDS_ULONG64:
654 if (nullData || sscanf(t, "%" SCNu64, &ulong64Value) != 1) {
655 if (fillInZero) {
656 ulong64Value = 0;
657 } else {
658 if (rows == 0)
659 ulong64Value = 0;
660 else
661 ulong64Value = ((uint64_t *)SDDSout->data[columnData[column].index])[rows - 1];
662 }
663 }
664 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, ulong64Value, -1))
665 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
666 break;
667 case SDDS_FLOAT:
668 if (nullData || sscanf(t, "%f", &floatValue) != 1) {
669 if (fillInZero) {
670 floatValue = 0.0f;
671 } else {
672 if (rows == 0)
673 floatValue = 0.0f;
674 else
675 floatValue = ((float *)SDDSout->data[columnData[column].index])[rows - 1];
676 }
677 }
678 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, floatValue, -1))
679 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
680 break;
681 case SDDS_DOUBLE:
682 if (nullData || sscanf(t, "%lf", &doubleValue) != 1) {
683 if (fillInZero) {
684 doubleValue = 0.0;
685 } else {
686 if (rows == 0)
687 doubleValue = 0.0;
688 else
689 doubleValue = ((double *)SDDSout->data[columnData[column].index])[rows - 1];
690 }
691 }
692 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, doubleValue, -1))
693 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
694 break;
695 case SDDS_CHARACTER:
696 if (nullData || sscanf(t, "%c", &charValue) != 1) {
697 if (fillInZero) {
698 charValue = 0;
699 } else {
700 if (rows == 0)
701 charValue = 0;
702 else
703 charValue = ((char *)SDDSout->data[columnData[column].index])[rows - 1];
704 }
705 }
706 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, charValue, -1))
707 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
708 break;
709 case SDDS_STRING:
711 if (!SDDS_SetRowValues(SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, rows, columnData[column].index, t, -1))
712 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
713 break;
714 default:
715 SDDS_Bomb("Unknown or unsupported data type encountered.");
716 }
717 }
718}
719
720void lowerstring(char *ptr) {
721 int size, i;
722 size = strlen(ptr);
723 for (i = 0; i < size; i++)
724 ptr[i] = tolower((unsigned char)ptr[i]);
725}
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:379
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_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: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
#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:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
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