SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
tdms2sdds.c
Go to the documentation of this file.
1/**
2 * @file tdms2sdds.c
3 * @brief Converts National Instruments' LabVIEW TDMS files to SDDS format.
4 *
5 * @details
6 * This program reads National Instruments' LabVIEW TDMS (Technical Data Management Streaming) files
7 * and converts them into SDDS (Self Describing Data Sets) format. It supports customization of output,
8 * including ASCII or binary formats, segmentation, and other advanced features for better data management.
9 *
10 * @section Usage
11 * ```
12 * tdms2sdds <inputFile> [<outputFile>]
13 * [-pipe=out]
14 * [-ascii | -binary]
15 * [-numOfSegments]
16 * [-segment=<integer>]
17 * ```
18 *
19 * @section Options
20 * | Optional | Description |
21 * |----------------------|-------------------------------------------------------------------------|
22 * | `-pipe` | SDDS toolkit pipe option. |
23 * | `-ascii` | Requests SDDS ASCII output (default). |
24 * | `-binary` | Requests SDDS binary output. |
25 * | `-numOfSegments` | Prints the number of TDMS segments in the input file. |
26 * | `-segment` | Specifies a particular segment to convert. |
27 *
28 * @subsection Incompatibilities
29 * - Only one of the following may be specified:
30 * - `-ascii`
31 * - `-binary`
32 *
33 * @copyright
34 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
35 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
36 *
37 * @license
38 * This file is distributed under the terms of the Software License Agreement
39 * found in the file LICENSE included with this distribution.
40 *
41 * @author
42 * R. Soliday, M. Borland
43 */
44
45/* Read http://www.ni.com/white-paper/5696/en/ for definitions for the header elements */
46
47#include "mdb.h"
48#include "SDDS.h"
49#include "scan.h"
50#if defined(_WIN32)
51# include <io.h>
52# include <fcntl.h>
53typedef signed __int16 int16_t;
54typedef signed __int8 int8_t;
55typedef unsigned __int16 uint16_t;
56typedef signed __int64 int64_t;
57#endif
58
59typedef struct
60{
61 int32_t toc;
62 uint32_t version;
63 uint64_t next_segment_offset;
64 uint64_t raw_data_offset;
66
67typedef struct
68{
69 char *name;
70 int32_t datatype;
71 void *value;
73
74typedef struct
75{
76 char *path;
77 uint32_t raw_data_index;
78 int32_t raw_data_datatype;
79 uint32_t raw_data_dimensions;
80 uint64_t raw_data_count;
81 uint64_t raw_data_total_size;
82 uint32_t n_properties;
85
86typedef struct
87{
88 uint32_t n_objects;
91
92typedef struct
93{
94 uint32_t n_values;
95 double *values;
96 char *name;
97 int32_t datatype;
99
100typedef struct
101{
102 uint32_t n_channels;
103 TDMS_RAW_DATA_CHANNEL *channel;
105
106typedef struct
107{
108 char *name;
109 char *unit;
110 long double start_time;
111 long double start_offset;
112 long double increment;
113 int32_t samples;
114 char *time_pref;
115 long double range;
116} TDMS_XPART;
117
118typedef struct
119{
120 TDMS_LEAD_IN lead_in;
121 TDMS_META_DATA meta_data;
122 TDMS_RAW_DATA raw_data;
123 TDMS_XPART xpart;
125
126typedef struct
127{
128 uint32_t n_segments;
129 TDMS_SEGMENT *segment; /* segments are like SDDS pages */
130 long filesize;
131} TDMS_FILE;
132
133void TDMS_ReadLeadIn(FILE *fd, TDMS_SEGMENT *segment);
134void TDMS_ReadMetaData(FILE *fd, TDMS_SEGMENT *segment);
135void TDMS_ReadRawData(FILE *fd, TDMS_FILE *tdms, uint32_t n_segment, long filesize);
136void TDMS_GetValue(FILE *fd, void **value, int32_t datatype);
137
138/* Enumeration for TOC flags */
139#define kTocMetaData (1L << 1)
140#define kTocNewObjList (1L << 2)
141#define kTocRawData (1L << 3)
142#define kTocInterleavedData (1L << 5)
143#define kTocBigEndian (1L << 6)
144#define kTocDAQmxRawData (1L << 7)
145
146/* Enumeration for data types */
147#define tdsTypeVoid 0x00000000
148#define tdsTypeI8 0x00000001
149#define tdsTypeI16 0x00000002
150#define tdsTypeI32 0x00000003
151#define tdsTypeI64 0x00000004
152#define tdsTypeU8 0x00000005
153#define tdsTypeU16 0x00000006
154#define tdsTypeU32 0x00000007
155#define tdsTypeU64 0x00000008
156#define tdsTypeSingleFloat 0x00000009
157#define tdsTypeDoubleFloat 0x0000000A
158#define tdsTypeExtendedFloat 0x0000000B
159#define tdsTypeSingleFloatWithUnit 0x00000019
160#define tdsTypeDoubleFloatWithUnit 0x0000001A
161#define tdsTypeExtendedFloatWithUnit 0x0000001B
162#define tdsTypeString 0x00000020
163#define tdsTypeBoolean 0x00000021
164#define tdsTypeTimeStamp 0x00000044
165#define tdsTypeDAQmxRawData 0xFFFFFFFF
166
167/* Enumeration for option types */
168enum option_type {
169 SET_ASCII,
170 SET_BINARY,
171 SET_PIPE,
172 SET_SEGMENT,
173 SET_NUMOFSEGMENTS,
174 N_OPTIONS
175};
176
177char *option[N_OPTIONS] = {
178 "ascii",
179 "binary",
180 "pipe",
181 "segment",
182 "numofsegments"};
183
184/* Improved Usage Message */
185char *USAGE =
186 "Usage: tdms2sdds <inputFile> [<outputFile>]\n"
187 " [-pipe=out]\n"
188 " [-ascii | -binary] \n"
189 " [-numOfSegments] \n"
190 " [-segment=<integer>]\n"
191 "Options:\n"
192 " -pipe=out SDDS toolkit pipe option.\n"
193 " -ascii Requests SDDS ASCII output. Default is binary.\n"
194 " -binary Requests SDDS BINARY output.\n"
195 " -numOfSegments Print out the number of TDMS segments.\n"
196 " -segment=<integer> Select a specific segment to convert.\n\n"
197 "Converts National Instruments TDMS files to SDDS.\n"
198 "Program by Robert Soliday. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
199
200int main(int argc, char **argv) {
201 FILE *fd;
202 char *input = NULL, *output = NULL;
203 SDDS_DATASET SDDSout;
204 SCANNED_ARG *scanned;
205 long iArg;
206 long ascii = 0;
207 unsigned long pipeFlags = 0;
208 int i = 0, n, found, ii, jj, kk, segment = 0, querySegments = 0;
209 long double timeValue;
210 short timeDefined = 0;
211 char buffer[1024];
212
213 TDMS_FILE tdms;
214 uint64_t rows = 0, j = 0, k;
215
217 argc = scanargs(&scanned, argc, argv);
218 if (argc < 2) {
219 fprintf(stderr, "%s", USAGE);
220 return (EXIT_FAILURE);
221 }
222
223 for (iArg = 1; iArg < argc; iArg++) {
224 if (scanned[iArg].arg_type == OPTION) {
225 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
226 case SET_ASCII:
227 ascii = 1;
228 break;
229 case SET_BINARY:
230 ascii = 0;
231 break;
232 case SET_SEGMENT:
233 if (scanned[iArg].n_items < 2) {
234 fprintf(stderr, "Error (%s): invalid -segment syntax\n", argv[0]);
235 return (EXIT_FAILURE);
236 }
237 if (sscanf(scanned[iArg].list[1], "%d", &segment) != 1 || segment <= 0) {
238 fprintf(stderr, "Error (%s): invalid -segment syntax or value\n", argv[0]);
239 return (EXIT_FAILURE);
240 }
241 break;
242 case SET_NUMOFSEGMENTS:
243 querySegments = 1;
244 break;
245 case SET_PIPE:
246 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags)) {
247 fprintf(stderr, "invalid -pipe syntax\n");
248 return (EXIT_FAILURE);
249 }
250 break;
251 default:
252 fprintf(stderr, "invalid option seen\n");
253 fprintf(stderr, "%s", USAGE);
254 return (EXIT_FAILURE);
255 }
256 } else {
257 if (!input)
258 input = scanned[iArg].list[0];
259 else if (!output)
260 output = scanned[iArg].list[0];
261 else {
262 fprintf(stderr, "too many filenames\n");
263 fprintf(stderr, "%s", USAGE);
264 return (EXIT_FAILURE);
265 }
266 }
267 }
268 if (!querySegments) {
269 processFilenames("tdms2sdds", &input, &output, pipeFlags, 0, NULL);
270 }
271
272 if (input) {
273 if (!fexists(input)) {
274 fprintf(stderr, "input file not found\n");
275 return (EXIT_FAILURE);
276 }
277 if (!(fd = fopen(input, "rb"))) {
278 fprintf(stderr, "problem opening input file\n");
279 return (EXIT_FAILURE);
280 }
281 } else {
282 fprintf(stderr, "tdms2sdds cannot -pipe=in tdms files\n");
283 return (EXIT_FAILURE);
284 }
285
286 fseek(fd, 0L, SEEK_END);
287 tdms.filesize = ftell(fd);
288 fseek(fd, 0L, SEEK_SET);
289
290 tdms.n_segments = 0;
291 while (ftell(fd) < tdms.filesize) {
292 tdms.n_segments++;
293 if (tdms.n_segments == 1) {
294 tdms.segment = malloc(sizeof(TDMS_SEGMENT));
295 } else {
296 tdms.segment = realloc(tdms.segment, sizeof(TDMS_SEGMENT) * tdms.n_segments);
297 }
298 /* Read Lead In */
299 TDMS_ReadLeadIn(fd, &(tdms.segment[tdms.n_segments - 1]));
300 if (tdms.segment[tdms.n_segments - 1].lead_in.toc & kTocBigEndian) {
302 fprintf(stderr, "tdms2sdds does not yet support reading from non-native endian TDMS files.\n");
303 return (EXIT_FAILURE);
304 }
305 } else {
307 fprintf(stderr, "tdms2sdds does not yet support reading from non-native endian TDMS files.\n");
308 return (EXIT_FAILURE);
309 }
310 }
311 /* Read Meta Data */
312 if (tdms.segment[tdms.n_segments - 1].lead_in.toc & kTocMetaData) {
313 TDMS_ReadMetaData(fd, &(tdms.segment[tdms.n_segments - 1]));
314 }
315 /* Read Raw Data */
316 if (tdms.segment[tdms.n_segments - 1].lead_in.toc & kTocRawData) {
317 TDMS_ReadRawData(fd, &tdms, tdms.n_segments - 1, tdms.filesize);
318 }
319 }
320 fclose(fd);
321
322 if (querySegments) {
323 fprintf(stdout, "Number of segments: %u\n", tdms.n_segments);
324 return (EXIT_SUCCESS);
325 }
326 if (!SDDS_InitializeOutput(&SDDSout, ascii ? SDDS_ASCII : SDDS_BINARY, 1, NULL, NULL, output)) {
327 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
328 return (EXIT_FAILURE);
329 }
330 if (input) {
331 if (SDDS_DefineParameter(&SDDSout, "TDMSfile", NULL, NULL, NULL, NULL, SDDS_STRING, input) == -1) {
332 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
333 return (EXIT_FAILURE);
334 }
335 }
336 if (segment > tdms.n_segments) {
337 fprintf(stderr, "tdms2sdds: Error: segment selected does not exist\n");
338 return (EXIT_FAILURE);
339 } else {
340 segment--;
341 }
342 for (i = 0; i < tdms.n_segments; i++) {
343 if ((segment != -1) && (segment != i)) {
344 continue;
345 }
346 for (j = 0; j < tdms.segment[i].raw_data.n_channels; j++) {
347 if (j == 0) {
348 rows = tdms.segment[i].raw_data.channel[j].n_values;
349 } else {
350 if (rows != tdms.segment[i].raw_data.channel[j].n_values) {
351 fprintf(stderr, "tdms2sdds: Error: channels in the same TDMS segment have different lengths which is not allowed in SDDS\n");
352 return (EXIT_FAILURE);
353 }
354 }
355 }
356 k = 0;
357 for (j = 0; j < tdms.segment[i].meta_data.n_objects; j++) {
358 found = 0;
359 for (n = 0; n < tdms.segment[i].meta_data.object[j].n_properties; n++) {
360 if (strcmp(tdms.segment[i].meta_data.object[j].property[n].name, "NI_ChannelName") == 0) {
361 found = 1;
362 strcpy(buffer, tdms.segment[i].meta_data.object[j].property[n].value);
363 break;
364 }
365 }
366 if (!found) {
367 strcpy(buffer, tdms.segment[i].meta_data.object[j].path);
368 }
369 if (!edit_string(buffer, "1Z/%g/ /_/%ga/a_a%g/\'//%g/(/[/%g/)/]/%g/=/_eq_/")) {
370 fprintf(stderr, "tdms2sdds: Error: problem editing column label\n");
371 return (EXIT_FAILURE);
372 }
373 /* Check for channel name that starts with a number and prepend a semicolon */
374 if (!(isalpha(*buffer) || strchr(".:", *buffer))) {
375 if (!edit_string(buffer, "i/:/")) {
376 fprintf(stderr, "tdms2sdds: Error: problem editing column label\n");
377 return (EXIT_FAILURE);
378 }
379 }
380 strcpy(tdms.segment[i].meta_data.object[j].path, buffer);
381 if (tdms.segment[i].meta_data.object[j].raw_data_index != 0xFFFFFFFF) {
382 tdms.segment[i].raw_data.channel[k].name = tdms.segment[i].meta_data.object[j].path;
383 tdms.segment[i].raw_data.channel[k].datatype = tdms.segment[i].meta_data.object[j].raw_data_datatype;
384 }
385 if (((segment == -1) && (i == 0)) || (segment != -1)) {
386 if (tdms.segment[i].meta_data.object[j].raw_data_index != 0xFFFFFFFF) {
387 if (timeDefined == 0) {
388 if (tdms.segment[i].xpart.samples > 0) {
389 if (tdms.segment[i].xpart.name == NULL) {
390 tdms.segment[i].xpart.name = malloc(5);
391 sprintf(tdms.segment[i].xpart.name, "Time");
392 }
393 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].xpart.name, tdms.segment[i].xpart.unit, SDDS_DOUBLE)) {
394 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
395 return (EXIT_FAILURE);
396 }
397 timeDefined = 1;
398 }
399 }
400 if ((tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeBoolean) ||
401 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeU8) ||
402 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeU16)) {
403 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_USHORT)) {
404 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
405 return (EXIT_FAILURE);
406 }
407 } else if ((tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeI8) ||
408 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeI16)) {
409 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_SHORT)) {
410 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
411 return (EXIT_FAILURE);
412 }
413 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeI32) {
414 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_LONG)) {
415 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
416 return (EXIT_FAILURE);
417 }
418 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeU32) {
419 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_ULONG)) {
420 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
421 return (EXIT_FAILURE);
422 }
423 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeI64) {
424 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_LONG64)) {
425 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
426 return (EXIT_FAILURE);
427 }
428 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeU64) {
429 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_ULONG64)) {
430 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
431 return (EXIT_FAILURE);
432 }
433 } else if ((tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeSingleFloat) ||
434 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeSingleFloatWithUnit)) {
435 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_FLOAT)) {
436 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
437 return (EXIT_FAILURE);
438 }
439 } else if ((tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeDoubleFloat) ||
440 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeDoubleFloatWithUnit) ||
441 (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeTimeStamp)) {
442 if (!SDDS_DefineSimpleColumn(&SDDSout, tdms.segment[i].meta_data.object[j].path, NULL, SDDS_DOUBLE)) {
443 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
444 return (EXIT_FAILURE);
445 }
446 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeString) {
447 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
448 return (EXIT_FAILURE);
449 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeVoid) {
450 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
451 return (EXIT_FAILURE);
452 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeExtendedFloat) {
453 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
454 return (EXIT_FAILURE);
455 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeExtendedFloatWithUnit) {
456 fprintf(stderr, "tdms2sdds: extended float with unit type channels are not yet supported in tdms2sdds\n");
457 return (EXIT_FAILURE);
458 } else if (tdms.segment[i].meta_data.object[j].raw_data_datatype == tdsTypeDAQmxRawData) {
459 fprintf(stderr, "tdms2sdds: DAQmx raw data channels are not yet supported in tdms2sdds\n");
460 return (EXIT_FAILURE);
461 } else {
462 fprintf(stderr, "tdms2sdds: unknown data type\n");
463 return (EXIT_FAILURE);
464 }
465 }
466 for (n = 0; n < tdms.segment[i].meta_data.object[j].n_properties; n++) {
467 if (strcmp(tdms.segment[i].meta_data.object[j].property[n].name, "name") == 0) {
468 continue;
469 }
470 strcpy(buffer, tdms.segment[i].meta_data.object[j].property[n].name);
471 if (!edit_string(buffer, "%g/ /_/%g/\'//%g/(/[/%g/)/]/%g/=/_eq_/")) {
472 fprintf(stderr, "tdms2sdds: Error: problem editing column label\n");
473 return (EXIT_FAILURE);
474 }
475 /* Check for channel name that starts with a number and prepend a semicolon */
476 if (!(isalpha(*buffer) || strchr(".:", *buffer))) {
477 if (!edit_string(buffer, "i/:/")) {
478 fprintf(stderr, "tdms2sdds: Error: problem editing column label\n");
479 return (EXIT_FAILURE);
480 }
481 }
482 strcpy(tdms.segment[i].meta_data.object[j].property[n].name, buffer);
483
484 /* Check if additional channels have the same property names. Only include the first */
485 if (SDDS_GetParameterIndex(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name) != -1) {
487 continue;
488 }
489 if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeBoolean) ||
490 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU8) ||
491 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU16)) {
492 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_USHORT)) {
493 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
494 return (EXIT_FAILURE);
495 }
496 } else if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI8) ||
497 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI16)) {
498 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_SHORT)) {
499 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
500 return (EXIT_FAILURE);
501 }
502 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI32) {
503 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_LONG)) {
504 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
505 return (EXIT_FAILURE);
506 }
507 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU32) {
508 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_ULONG)) {
509 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
510 return (EXIT_FAILURE);
511 }
512 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI64) {
513 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_LONG64)) {
514 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
515 return (EXIT_FAILURE);
516 }
517 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU64) {
518 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_ULONG64)) {
519 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
520 return (EXIT_FAILURE);
521 }
522 } else if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeSingleFloat) ||
523 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeSingleFloatWithUnit)) {
524 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_FLOAT)) {
525 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
526 return (EXIT_FAILURE);
527 }
528 } else if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDoubleFloat) ||
529 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDoubleFloatWithUnit) ||
530 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeTimeStamp)) {
531 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_DOUBLE)) {
532 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
533 return (EXIT_FAILURE);
534 }
535 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeString) {
536 if (!SDDS_DefineSimpleParameter(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name, NULL, SDDS_STRING)) {
537 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
538 return (EXIT_FAILURE);
539 }
540 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeVoid) {
541 fprintf(stderr, "tdms2sdds: void type parameters are not yet supported in tdms2sdds\n");
542 return (EXIT_FAILURE);
543 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeExtendedFloat) {
544 fprintf(stderr, "tdms2sdds: extended float type parameters are not yet supported in tdms2sdds\n");
545 return (EXIT_FAILURE);
546 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeExtendedFloatWithUnit) {
547 fprintf(stderr, "tdms2sdds: extended float with unit type parameters are not yet supported in tdms2sdds\n");
548 return (EXIT_FAILURE);
549 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDAQmxRawData) {
550 fprintf(stderr, "tdms2sdds: DAQmx raw data parameters are not yet supported in tdms2sdds\n");
551 return (EXIT_FAILURE);
552 } else {
553 fprintf(stderr, "tdms2sdds: unknown data type\n");
554 return (EXIT_FAILURE);
555 }
556 }
557 }
558 if (tdms.segment[i].meta_data.object[j].raw_data_index != 0xFFFFFFFF) {
559 k++;
560 }
561 }
562 if (((segment == -1) && (i == 0)) || (segment != -1)) {
563 if (!SDDS_WriteLayout(&SDDSout)) {
564 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
565 return (EXIT_FAILURE);
566 }
567 }
568 if (!SDDS_StartTable(&SDDSout, rows)) {
569 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
570 return (EXIT_FAILURE);
571 }
572
573 if ((tdms.segment[i].xpart.name != NULL) &&
574 (tdms.segment[i].xpart.samples > 0) &&
575 (tdms.segment[i].raw_data.n_channels > 0)) {
576 timeValue = tdms.segment[i].xpart.start_time + tdms.segment[i].xpart.start_offset;
577 for (j = 0; j < rows; j++) {
578 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, j, tdms.segment[i].xpart.name, (double)timeValue, NULL)) {
579 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
580 return (EXIT_FAILURE);
581 }
582 timeValue += tdms.segment[i].xpart.increment;
583 }
584 }
585 for (j = 0; j < tdms.segment[i].raw_data.n_channels; j++) {
586 if ((tdms.segment[i].raw_data.channel[j].datatype == tdsTypeI16) ||
587 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeU16) ||
588 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeI32) ||
589 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeU32) ||
590 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeI64) ||
591 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeU64) ||
592 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeSingleFloat) ||
593 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeSingleFloatWithUnit) ||
594 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeDoubleFloat) ||
595 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeDoubleFloatWithUnit) ||
596 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeTimeStamp)) {
597 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_NAME, tdms.segment[i].raw_data.channel[j].values,
598 tdms.segment[i].raw_data.channel[j].n_values, tdms.segment[i].raw_data.channel[j].name)) {
599 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
600 return (EXIT_FAILURE);
601 }
602 } else if ((tdms.segment[i].raw_data.channel[j].datatype == tdsTypeBoolean) ||
603 (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeI8)) {
604 for (k = 0; k < rows; k++) {
605 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, k,
606 tdms.segment[i].raw_data.channel[j].name,
607 (int16_t)(((int8_t *)(tdms.segment[i].raw_data.channel[j].values))[k]), NULL)) {
608 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
609 return (EXIT_FAILURE);
610 }
611 }
612 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeU8) {
613 for (k = 0; k < rows; k++) {
614 if (!SDDS_SetRowValues(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, k,
615 tdms.segment[i].raw_data.channel[j].name,
616 (uint16_t)(((uint8_t *)(tdms.segment[i].raw_data.channel[j].values))[k]), NULL)) {
617 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
618 return (EXIT_FAILURE);
619 }
620 }
621 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeString) {
622 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
623 return (EXIT_FAILURE);
624 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeVoid) {
625 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
626 return (EXIT_FAILURE);
627 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeExtendedFloat) {
628 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
629 return (EXIT_FAILURE);
630 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeExtendedFloatWithUnit) {
631 fprintf(stderr, "tdms2sdds: extended float with unit type channels are not yet supported in tdms2sdds\n");
632 return (EXIT_FAILURE);
633 } else if (tdms.segment[i].raw_data.channel[j].datatype == tdsTypeDAQmxRawData) {
634 fprintf(stderr, "tdms2sdds: DAQmx raw data channels are not yet supported in tdms2sdds\n");
635 return (EXIT_FAILURE);
636 } else {
637 fprintf(stderr, "tdms2sdds: unknown data type\n");
638 return (EXIT_FAILURE);
639 }
640 }
641
642 for (j = 0; j < tdms.segment[i].meta_data.n_objects; j++) {
643 for (n = 0; n < tdms.segment[i].meta_data.object[j].n_properties; n++) {
644 /* Do not write parameter if it wasn't defined in the first segment */
645 if (SDDS_GetParameterIndex(&SDDSout, tdms.segment[i].meta_data.object[j].property[n].name) == -1) {
647 continue;
648 }
649 if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI16) ||
650 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU16) ||
651 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI32) ||
652 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU32) ||
653 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI64) ||
654 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU64) ||
655 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeSingleFloat) ||
656 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeSingleFloatWithUnit) ||
657 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDoubleFloat) ||
658 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDoubleFloatWithUnit) ||
659 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeTimeStamp)) {
660 if (!SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_REFERENCE,
661 tdms.segment[i].meta_data.object[j].property[n].name,
662 tdms.segment[i].meta_data.object[j].property[n].value, NULL)) {
663 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
664 return (EXIT_FAILURE);
665 }
666 } else if ((tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeBoolean) ||
667 (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeI8)) {
668 if (!SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
669 tdms.segment[i].meta_data.object[j].property[n].name,
670 (int16_t)(*(int8_t *)(tdms.segment[i].meta_data.object[j].property[n].value)), NULL)) {
671 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
672 return (EXIT_FAILURE);
673 }
674 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeU8) {
675 if (!SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
676 tdms.segment[i].meta_data.object[j].property[n].name,
677 (uint16_t)(*(uint8_t *)(tdms.segment[i].meta_data.object[j].property[n].value)), NULL)) {
678 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
679 return (EXIT_FAILURE);
680 }
681 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeString) {
682 if (!SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
683 tdms.segment[i].meta_data.object[j].property[n].name,
684 tdms.segment[i].meta_data.object[j].property[n].value, NULL)) {
685 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
686 return (EXIT_FAILURE);
687 }
688 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeVoid) {
689 fprintf(stderr, "tdms2sdds: void type parameters are not yet supported in tdms2sdds\n");
690 return (EXIT_FAILURE);
691 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeExtendedFloat) {
692 fprintf(stderr, "tdms2sdds: extended float type parameters are not yet supported in tdms2sdds\n");
693 return (EXIT_FAILURE);
694 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeExtendedFloatWithUnit) {
695 fprintf(stderr, "tdms2sdds: extended float with unit type parameters are not yet supported in tdms2sdds\n");
696 return (EXIT_FAILURE);
697 } else if (tdms.segment[i].meta_data.object[j].property[n].datatype == tdsTypeDAQmxRawData) {
698 fprintf(stderr, "tdms2sdds: DAQmx raw data parameters are not yet supported in tdms2sdds\n");
699 return (EXIT_FAILURE);
700 } else {
701 fprintf(stderr, "tdms2sdds: unknown data type\n");
702 return (EXIT_FAILURE);
703 }
704 }
705 }
706 if (!SDDS_WriteTable(&SDDSout)) {
707 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
708 return (EXIT_FAILURE);
709 }
710 }
711 if (!SDDS_Terminate(&SDDSout)) {
712 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
713 return (EXIT_FAILURE);
714 }
715
716 if (tdms.n_segments > 0) {
717 for (i = 0; i < tdms.n_segments; i++) {
718 if (tdms.segment[i].raw_data.n_channels > 0) {
719 for (j = 0; j < tdms.segment[i].raw_data.n_channels; j++) {
720 if (tdms.segment[i].raw_data.channel[j].n_values > 0) {
721 free(tdms.segment[i].raw_data.channel[j].values);
722 }
723 }
724 free(tdms.segment[i].raw_data.channel);
725 }
726 if (tdms.segment[i].meta_data.n_objects > 0) {
727 for (j = 0; j < tdms.segment[i].meta_data.n_objects; j++) {
728 if (tdms.segment[i].meta_data.object[j].path) {
729 free(tdms.segment[i].meta_data.object[j].path);
730 }
731 if (tdms.segment[i].meta_data.object[j].n_properties > 0) {
732 for (k = 0; k < tdms.segment[i].meta_data.object[j].n_properties; k++) {
733 if (tdms.segment[i].meta_data.object[j].property[k].name) {
734 for (ii = i + 1; ii < tdms.n_segments; ii++) {
735 for (jj = 0; jj < tdms.segment[ii].meta_data.n_objects; jj++) {
736 for (kk = 0; kk < tdms.segment[ii].meta_data.object[jj].n_properties; kk++) {
737 if (tdms.segment[i].meta_data.object[j].property[k].name == tdms.segment[ii].meta_data.object[jj].property[kk].name) {
738 tdms.segment[ii].meta_data.object[jj].property[kk].name = NULL;
739 tdms.segment[ii].meta_data.object[jj].property[kk].value = NULL;
740 }
741 }
742 }
743 }
744 free(tdms.segment[i].meta_data.object[j].property[k].name);
745 tdms.segment[i].meta_data.object[j].property[k].name = NULL;
746 }
747 if (tdms.segment[i].meta_data.object[j].property[k].value) {
748 free(tdms.segment[i].meta_data.object[j].property[k].value);
749 tdms.segment[i].meta_data.object[j].property[k].value = NULL;
750 }
751 }
752 free(tdms.segment[i].meta_data.object[j].property);
753 }
754 }
755 free(tdms.segment[i].meta_data.object);
756 }
757 }
758 free(tdms.segment);
759 }
760
761 free_scanargs(&scanned, argc);
762
763 return (EXIT_SUCCESS);
764}
765
766void TDMS_ReadLeadIn(FILE *fd, TDMS_SEGMENT *segment) {
767 char buffer[50];
768 size_t bytesRead;
769
770 bytesRead = fread(buffer, 1, 4, fd);
771 (void)bytesRead;
772 buffer[4] = '\0';
773 if (strcmp(buffer, "TDSm") != 0) {
774 fprintf(stderr, "tdms2sdds: Error: File does not start with TDSm\n");
775 exit(EXIT_FAILURE);
776 }
777 bytesRead = fread(&(segment->lead_in.toc), 1, 4, fd); /* TOC */
778 (void)bytesRead;
779 bytesRead = fread(&(segment->lead_in.version), 1, 4, fd); /* Version */
780 (void)bytesRead;
781 if (segment->lead_in.version == 4712) {
782 fprintf(stderr, "tdms2sdds: Error: TDMS version 1.0 files unsupported\n");
783 exit(EXIT_FAILURE);
784 }
785 if (segment->lead_in.version != 4713) {
786 fprintf(stderr, "tdms2sdds: Error: Unknown TDMS version\n");
787 exit(EXIT_FAILURE);
788 }
789 bytesRead = fread(&(segment->lead_in.next_segment_offset), 1, 8, fd); /* Next segment offset */
790 (void)bytesRead;
791 bytesRead = fread(&(segment->lead_in.raw_data_offset), 1, 8, fd); /* Raw data offset */
792 (void)bytesRead;
793}
794
795void TDMS_ReadMetaData(FILE *fd, TDMS_SEGMENT *segment) {
796 uint32_t uLong, i, j;
797 size_t bytesRead;
798
799 segment->xpart.name = NULL;
800 segment->xpart.unit = NULL;
801 segment->xpart.start_time = 0;
802 segment->xpart.start_offset = 0;
803 segment->xpart.increment = 0;
804 segment->xpart.samples = 0;
805 segment->xpart.time_pref = NULL;
806 segment->xpart.range = 0;
807
808 bytesRead = fread(&(segment->meta_data.n_objects), 1, 4, fd);
809 (void)bytesRead;
810
811 segment->meta_data.object = malloc(sizeof(TDMS_META_DATA_OBJECT) * segment->meta_data.n_objects);
812 for (i = 0; i < segment->meta_data.n_objects; i++) {
813 bytesRead = fread(&uLong, 1, 4, fd);
814 (void)bytesRead;
815 segment->meta_data.object[i].path = malloc(sizeof(char) * (uLong + 1));
816 bytesRead = fread(segment->meta_data.object[i].path, 1, uLong, fd);
817 (void)bytesRead;
818 segment->meta_data.object[i].path[uLong] = '\0';
819 bytesRead = fread(&(segment->meta_data.object[i].raw_data_index), 1, 4, fd);
820 (void)bytesRead;
821 if ((segment->meta_data.object[i].raw_data_index != 0xFFFFFFFF) && (segment->meta_data.object[i].raw_data_index != 0x00000000)) {
822 bytesRead = fread(&(segment->meta_data.object[i].raw_data_datatype), 1, 4, fd);
823 (void)bytesRead;
824 bytesRead = fread(&(segment->meta_data.object[i].raw_data_dimensions), 1, 4, fd);
825 (void)bytesRead;
826 bytesRead = fread(&(segment->meta_data.object[i].raw_data_count), 1, 8, fd);
827 (void)bytesRead;
828 if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
829 bytesRead = fread(&(segment->meta_data.object[i].raw_data_total_size), 1, 8, fd);
830 (void)bytesRead;
831 }
832 }
833 bytesRead = fread(&(segment->meta_data.object[i].n_properties), 1, 4, fd);
834 (void)bytesRead;
835 segment->meta_data.object[i].property = malloc(sizeof(TDMS_META_DATA_OBJECT_PROPERTY) * segment->meta_data.object[i].n_properties);
836 for (j = 0; j < segment->meta_data.object[i].n_properties; j++) {
837 bytesRead = fread(&uLong, 1, 4, fd);
838 (void)bytesRead;
839 segment->meta_data.object[i].property[j].name = malloc(sizeof(char) * (uLong + 1));
840 bytesRead = fread(segment->meta_data.object[i].property[j].name, 1, uLong, fd);
841 (void)bytesRead;
842 segment->meta_data.object[i].property[j].name[uLong] = '\0';
843 bytesRead = fread(&(segment->meta_data.object[i].property[j].datatype), 1, 4, fd);
844 (void)bytesRead;
845 if (segment->meta_data.object[i].property[j].datatype == tdsTypeString) {
846 bytesRead = fread(&uLong, 1, 4, fd);
847 (void)bytesRead;
848 segment->meta_data.object[i].property[j].value = malloc(sizeof(char) * (uLong + 1));
849 bytesRead = fread(segment->meta_data.object[i].property[j].value, 1, uLong, fd);
850 (void)bytesRead;
851 ((char *)(segment->meta_data.object[i].property[j].value))[uLong] = '\0';
852 } else {
853 TDMS_GetValue(fd, &(segment->meta_data.object[i].property[j].value), segment->meta_data.object[i].property[j].datatype);
854 }
855 /* check for waveform channel properties */
856 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_xname") == 0) {
857 segment->xpart.name = segment->meta_data.object[i].property[j].value;
858 }
859 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_xunit_string") == 0) {
860 segment->xpart.unit = segment->meta_data.object[i].property[j].value;
861 }
862 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_start_time") == 0) {
863 segment->xpart.start_time = *(double *)(segment->meta_data.object[i].property[j].value);
864 }
865 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_start_offset") == 0) {
866 segment->xpart.start_offset = *(double *)(segment->meta_data.object[i].property[j].value);
867 }
868 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_increment") == 0) {
869 segment->xpart.increment = *(double *)(segment->meta_data.object[i].property[j].value);
870 }
871 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_samples") == 0) {
872 segment->xpart.samples = *(int32_t *)(segment->meta_data.object[i].property[j].value);
873 }
874 if (strcmp(segment->meta_data.object[i].property[j].name, "wf_time_pref") == 0) {
875 segment->xpart.time_pref = segment->meta_data.object[i].property[j].value;
876 }
877 }
878 }
879 (void)bytesRead;
880}
881
882void TDMS_ReadRawData(FILE *fd, TDMS_FILE *tdms, uint32_t n_segment, long filesize) {
883 uint32_t i, j, k, n, p, a;
884 uint32_t channel_size;
885 uint32_t chunk_size = 0;
886 uint32_t total_chunks;
887 uint32_t n_chunks;
888 uint32_t chunk;
889 int64_t LLong;
890 uint64_t uLLong;
891 int prevFound = 0;
892 TDMS_SEGMENT *segment = &((*tdms).segment[n_segment]);
893 size_t bytesRead;
894
895 segment->raw_data.n_channels = 0;
896 for (i = 0; i < segment->meta_data.n_objects; i++) {
897 if (segment->meta_data.object[i].raw_data_index != 0xFFFFFFFF) {
898 if (segment->meta_data.object[i].raw_data_index == 0x00000000) {
899 /* An object with this name already exists in the previous segment.
900 Copy over meta data */
901 prevFound = 0;
902 a = 0;
903 while (prevFound == 0) {
904 a++;
905 if (a > n_segment) {
906 fprintf(stderr, "tdms2sdds: Error: unable to find %s in a previous segment.\n", segment->meta_data.object[i].path);
907 exit(EXIT_FAILURE);
908 }
909 for (n = 0; n < (*tdms).segment[n_segment - a].meta_data.n_objects; n++) {
910 if (strcmp((*tdms).segment[n_segment - a].meta_data.object[n].path, segment->meta_data.object[i].path) == 0) {
911 prevFound = 1;
912 segment->meta_data.object[i].raw_data_datatype = (*tdms).segment[n_segment - a].meta_data.object[n].raw_data_datatype;
913 segment->meta_data.object[i].raw_data_dimensions = (*tdms).segment[n_segment - a].meta_data.object[n].raw_data_dimensions;
914 segment->meta_data.object[i].raw_data_count = (*tdms).segment[n_segment - a].meta_data.object[n].raw_data_count;
915 if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
916 segment->meta_data.object[i].raw_data_total_size = (*tdms).segment[n_segment - a].meta_data.object[n].raw_data_total_size;
917 }
918
919 /* Copy over previous properties excluding any that were overwritten */
920 /* There will be errors if new properties are inserted after the first segment in the TDMS file */
921 for (j = 0; j < (*tdms).segment[n_segment - a].meta_data.object[n].n_properties; j++) {
922 for (k = 0; k < segment->meta_data.object[i].n_properties; k++) {
923 if (strcmp((*tdms).segment[n_segment - a].meta_data.object[n].property[j].name, segment->meta_data.object[i].property[k].name) == 0) {
924 break;
925 }
926 }
927 p = segment->meta_data.object[i].n_properties;
928 segment->meta_data.object[i].n_properties++;
929 segment->meta_data.object[i].property = realloc(segment->meta_data.object[i].property, sizeof(TDMS_META_DATA_OBJECT_PROPERTY) * segment->meta_data.object[i].n_properties);
930 segment->meta_data.object[i].property[p].name = (*tdms).segment[n_segment - a].meta_data.object[n].property[j].name;
931 segment->meta_data.object[i].property[p].datatype = (*tdms).segment[n_segment - a].meta_data.object[n].property[j].datatype;
932 segment->meta_data.object[i].property[p].value = (*tdms).segment[n_segment - a].meta_data.object[n].property[j].value;
933 /* check for waveform channel properties */
934 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_xname") == 0) {
935 segment->xpart.name = segment->meta_data.object[i].property[p].value;
936 }
937 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_xunit_string") == 0) {
938 segment->xpart.unit = segment->meta_data.object[i].property[p].value;
939 }
940 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_start_time") == 0) {
941 segment->xpart.start_time = *(double *)(segment->meta_data.object[i].property[p].value);
942 }
943 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_start_offset") == 0) {
944 segment->xpart.start_offset = *(double *)(segment->meta_data.object[i].property[p].value);
945 segment->xpart.start_offset += (*tdms).segment[n_segment - a].xpart.range;
946 /*put code here */
947 }
948 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_increment") == 0) {
949 segment->xpart.increment = *(double *)(segment->meta_data.object[i].property[p].value);
950 }
951 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_samples") == 0) {
952 segment->xpart.samples = *(int32_t *)(segment->meta_data.object[i].property[p].value);
953 }
954 if (strcmp(segment->meta_data.object[i].property[p].name, "wf_time_pref") == 0) {
955 segment->xpart.time_pref = segment->meta_data.object[i].property[p].value;
956 }
957 }
958 }
959 }
960 }
961 }
962
963 segment->raw_data.n_channels++;
964 if (segment->meta_data.object[i].raw_data_dimensions != 1) {
965 fprintf(stderr, "tdms2sdds: Error: raw data dimension is %d and should have been 1.\n", segment->meta_data.object[i].raw_data_dimensions);
966 exit(EXIT_FAILURE);
967 }
968 if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI8) ||
969 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU8) ||
970 (segment->meta_data.object[i].raw_data_datatype == tdsTypeBoolean)) {
971 channel_size = 1 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
972 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI16) ||
973 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU16)) {
974 channel_size = 2 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
975 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI32) ||
976 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU32) ||
977 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloat) ||
978 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloatWithUnit)) {
979 channel_size = 4 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
980 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI64) ||
981 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU64) ||
982 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloat) ||
983 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloatWithUnit)) {
984 channel_size = 8 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
985 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeTimeStamp) {
986 channel_size = 16 * segment->meta_data.object[i].raw_data_dimensions * segment->meta_data.object[i].raw_data_count;
987 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
988 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
989 exit(EXIT_FAILURE);
990 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeVoid) {
991 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
992 exit(EXIT_FAILURE);
993 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloat) {
994 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
995 exit(EXIT_FAILURE);
996 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloatWithUnit) {
997 fprintf(stderr, "tdms2sdds: extended float type with unit channels are not yet supported in tdms2sdds\n");
998 exit(EXIT_FAILURE);
999 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeDAQmxRawData) {
1000 fprintf(stderr, "tdms2sdds: extended DAQmx raw data channels are not yet supported in tdms2sdds\n");
1001 exit(EXIT_FAILURE);
1002 } else {
1003 fprintf(stderr, "tdms2sdds: unknown data type\n");
1004 exit(EXIT_FAILURE);
1005 }
1006 chunk_size += channel_size;
1007 }
1008 }
1009
1010 if (segment->lead_in.next_segment_offset == -1) {
1011 if (filesize == -1) {
1012 fprintf(stderr, "tdms2sdds: Error: cannot calculate file size because you are using stdin\n");
1013 exit(EXIT_FAILURE);
1014 }
1015 segment->lead_in.next_segment_offset = filesize;
1016 }
1017 total_chunks = segment->lead_in.next_segment_offset - segment->lead_in.raw_data_offset;
1018 n_chunks = total_chunks / chunk_size;
1019
1020 segment->raw_data.channel = malloc(sizeof(TDMS_RAW_DATA_CHANNEL) * segment->raw_data.n_channels);
1021
1022 if (segment->lead_in.toc & kTocInterleavedData) {
1023 fprintf(stderr, "tdms2sdds does not yet support interleaved data\n");
1024 exit(EXIT_FAILURE);
1025 } else {
1026 j = 0;
1027 for (i = 0; i < segment->meta_data.n_objects; i++) {
1028 if (segment->meta_data.object[i].raw_data_index != 0xFFFFFFFF) {
1029 segment->xpart.range = segment->xpart.increment * segment->meta_data.object[i].raw_data_count * n_chunks;
1030
1031 if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI8) ||
1032 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU8) ||
1033 (segment->meta_data.object[i].raw_data_datatype == tdsTypeBoolean)) {
1034 segment->raw_data.channel[j].values = malloc(1 * segment->meta_data.object[i].raw_data_count * n_chunks);
1035 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI16) ||
1036 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU16)) {
1037 segment->raw_data.channel[j].values = malloc(2 * segment->meta_data.object[i].raw_data_count * n_chunks);
1038 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI32) ||
1039 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU32) ||
1040 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloat) ||
1041 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloatWithUnit)) {
1042 segment->raw_data.channel[j].values = malloc(4 * segment->meta_data.object[i].raw_data_count * n_chunks);
1043 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeI64) ||
1044 (segment->meta_data.object[i].raw_data_datatype == tdsTypeU64) ||
1045 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloat) ||
1046 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloatWithUnit)) {
1047 segment->raw_data.channel[j].values = malloc(8 * segment->meta_data.object[i].raw_data_count * n_chunks);
1048 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeTimeStamp) {
1049 /* This is converted into a double value */
1050 segment->raw_data.channel[j].values = malloc(8 * segment->meta_data.object[i].raw_data_count * n_chunks);
1051 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
1052 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
1053 exit(EXIT_FAILURE);
1054 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeVoid) {
1055 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
1056 exit(EXIT_FAILURE);
1057 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloat) {
1058 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
1059 exit(EXIT_FAILURE);
1060 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloatWithUnit) {
1061 fprintf(stderr, "tdms2sdds: extended float type with unit channels are not yet supported in tdms2sdds\n");
1062 exit(EXIT_FAILURE);
1063 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeDAQmxRawData) {
1064 fprintf(stderr, "tdms2sdds: extended DAQmx raw data channels are not yet supported in tdms2sdds\n");
1065 exit(EXIT_FAILURE);
1066 } else {
1067 fprintf(stderr, "tdms2sdds: unknown data type\n");
1068 exit(EXIT_FAILURE);
1069 }
1070 segment->raw_data.channel[j].n_values = segment->meta_data.object[i].raw_data_count * n_chunks;
1071 j++;
1072 }
1073 }
1074 for (chunk = 0; chunk < n_chunks; chunk++) {
1075 j = 0;
1076 for (i = 0; i < segment->meta_data.n_objects; i++) {
1077 if (segment->meta_data.object[i].raw_data_index != 0xFFFFFFFF) {
1078 if (segment->meta_data.object[i].raw_data_datatype == tdsTypeBoolean) {
1079 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1080 bytesRead = fread(&(((int8_t *)(segment->raw_data.channel[j].values))[k]), 1, 1, fd);
1081 }
1082 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeI8) {
1083 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1084 bytesRead = fread(&(((int8_t *)(segment->raw_data.channel[j].values))[k]), 1, 1, fd);
1085 }
1086 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeU8) {
1087 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1088 bytesRead = fread(&(((uint8_t *)(segment->raw_data.channel[j].values))[k]), 1, 1, fd);
1089 }
1090 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeI16) {
1091 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1092 bytesRead = fread(&(((int16_t *)(segment->raw_data.channel[j].values))[k]), 1, 2, fd);
1093 }
1094 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeU16) {
1095 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1096 bytesRead = fread(&(((uint16_t *)(segment->raw_data.channel[j].values))[k]), 1, 2, fd);
1097 }
1098 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeI32) {
1099 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1100 bytesRead = fread(&(((int32_t *)(segment->raw_data.channel[j].values))[k]), 1, 4, fd);
1101 }
1102 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeU32) {
1103 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1104 bytesRead = fread(&(((uint32_t *)(segment->raw_data.channel[j].values))[k]), 1, 4, fd);
1105 }
1106 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeI64) {
1107 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1108 bytesRead = fread(&(((int64_t *)(segment->raw_data.channel[j].values))[k]), 1, 8, fd);
1109 }
1110 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeU64) {
1111 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1112 bytesRead = fread(&(((uint64_t *)(segment->raw_data.channel[j].values))[k]), 1, 8, fd);
1113 }
1114 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloat) ||
1115 (segment->meta_data.object[i].raw_data_datatype == tdsTypeSingleFloatWithUnit)) {
1116 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1117 bytesRead = fread(&(((float *)(segment->raw_data.channel[j].values))[k]), 1, 4, fd);
1118 }
1119 } else if ((segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloat) ||
1120 (segment->meta_data.object[i].raw_data_datatype == tdsTypeDoubleFloatWithUnit)) {
1121 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1122 bytesRead = fread(&(((double *)(segment->raw_data.channel[j].values))[k]), 1, 8, fd);
1123 }
1124 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeTimeStamp) {
1125 for (k = chunk * segment->meta_data.object[i].raw_data_count; k < (chunk + 1) * segment->meta_data.object[i].raw_data_count; k++) {
1126 bytesRead = fread(&uLLong, 1, 8, fd);
1127 bytesRead = fread(&LLong, 1, 8, fd);
1128 /*LLong = LLong - 2082844791LL; */ /* Subtract seconds between 1904 and 1970 */
1129 segment->raw_data.channel[j].values[k] = LLong + (uLLong * 5.42101086242752217e-20);
1130 }
1131 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeString) {
1132 fprintf(stderr, "tdms2sdds: string type channels are not yet supported in tdms2sdds\n");
1133 exit(EXIT_FAILURE);
1134 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeVoid) {
1135 fprintf(stderr, "tdms2sdds: void type channels are not yet supported in tdms2sdds\n");
1136 exit(EXIT_FAILURE);
1137 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloat) {
1138 fprintf(stderr, "tdms2sdds: extended float type channels are not yet supported in tdms2sdds\n");
1139 exit(EXIT_FAILURE);
1140 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeExtendedFloatWithUnit) {
1141 fprintf(stderr, "tdms2sdds: extended float with unit type channels are not yet supported in tdms2sdds\n");
1142 exit(EXIT_FAILURE);
1143 } else if (segment->meta_data.object[i].raw_data_datatype == tdsTypeDAQmxRawData) {
1144 fprintf(stderr, "tdms2sdds: DAQmx raw data channels are not yet supported in tdms2sdds\n");
1145 exit(EXIT_FAILURE);
1146 } else {
1147 fprintf(stderr, "tdms2sdds: unknown data type\n");
1148 exit(EXIT_FAILURE);
1149 }
1150 j++;
1151 }
1152 }
1153 }
1154 }
1155 (void)bytesRead;
1156}
1157
1158void TDMS_GetValue(FILE *fd, void **value, int32_t datatype) {
1159 uint64_t uLLong;
1160 int64_t LLong;
1161 size_t bytesRead;
1162
1163 if (datatype == tdsTypeI8) {
1164 *value = malloc(sizeof(int8_t));
1165 bytesRead = fread(((int8_t *)(*value)), 1, 1, fd);
1166 } else if (datatype == tdsTypeU8) {
1167 *value = malloc(sizeof(uint8_t));
1168 bytesRead = fread(((uint8_t *)(*value)), 1, 1, fd);
1169 } else if (datatype == tdsTypeI16) {
1170 *value = malloc(sizeof(int16_t));
1171 bytesRead = fread(((int16_t *)(*value)), 1, 2, fd);
1172 } else if (datatype == tdsTypeU16) {
1173 *value = malloc(sizeof(uint16_t));
1174 bytesRead = fread(((uint16_t *)(*value)), 1, 2, fd);
1175 } else if (datatype == tdsTypeI32) {
1176 *value = malloc(sizeof(int32_t));
1177 bytesRead = fread(((int32_t *)(*value)), 1, 4, fd);
1178 } else if (datatype == tdsTypeU32) {
1179 *value = malloc(sizeof(uint32_t));
1180 bytesRead = fread(((uint32_t *)(*value)), 1, 4, fd);
1181 } else if (datatype == tdsTypeI64) {
1182 *value = malloc(sizeof(int64_t));
1183 bytesRead = fread(((int64_t *)(*value)), 1, 8, fd);
1184 } else if (datatype == tdsTypeU64) {
1185 *value = malloc(sizeof(uint64_t));
1186 bytesRead = fread(((uint64_t *)(*value)), 1, 8, fd);
1187 } else if ((datatype == tdsTypeSingleFloat) || (datatype == tdsTypeSingleFloatWithUnit)) {
1188 *value = malloc(sizeof(float));
1189 bytesRead = fread(((float *)(*value)), 1, 4, fd);
1190 } else if ((datatype == tdsTypeDoubleFloat) || (datatype == tdsTypeDoubleFloatWithUnit)) {
1191 *value = malloc(sizeof(double));
1192 bytesRead = fread(((double *)(*value)), 1, 8, fd);
1193 } else if (datatype == tdsTypeBoolean) {
1194 *value = malloc(sizeof(int8_t));
1195 bytesRead = fread(((int8_t *)(*value)), 1, 1, fd);
1196 } else if (datatype == tdsTypeTimeStamp) {
1197 *value = malloc(sizeof(double));
1198 bytesRead = fread(&uLLong, 1, 8, fd);
1199 bytesRead = fread(&LLong, 1, 8, fd);
1200 /*LLong = LLong - 2082844791LL; */ /* Subtract seconds between 1904 and 1970 */
1201 *((double *)(*value)) = LLong + (uLLong * 5.42101086242752217e-20);
1202 } else if (datatype == tdsTypeVoid) {
1203 fprintf(stderr, "tdms2sdds: datatype Void is not yet supported in tdms2sdds\n");
1204 exit(EXIT_FAILURE);
1205 } else if (datatype == tdsTypeExtendedFloat) {
1206 fprintf(stderr, "tdms2sdds: datatype ExtendedFloat is not yet supported in tdms2sdds\n");
1207 exit(EXIT_FAILURE);
1208 } else if (datatype == tdsTypeExtendedFloatWithUnit) {
1209 fprintf(stderr, "tdms2sdds: datatype ExtendedFloatWithUnit is not yet supported in tdms2sdds\n");
1210 exit(EXIT_FAILURE);
1211 } else if (datatype == tdsTypeDAQmxRawData) {
1212 fprintf(stderr, "tdms2sdds: datatype DAQmxRawData is not yet supported in tdms2sdds\n");
1213 exit(EXIT_FAILURE);
1214 } else {
1215 fprintf(stderr, "tdms2sdds: unknown data type\n");
1216 exit(EXIT_FAILURE);
1217 }
1218 (void)bytesRead;
1219}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
int32_t SDDS_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_DefineSimpleParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data parameter 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_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter 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:474
void SDDS_ClearErrors()
Clears all recorded error messages from the SDDS error stack.
Definition SDDS_utils.c:354
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:318
int32_t SDDS_IsBigEndianMachine()
Determines whether the current machine uses big-endian byte ordering.
long edit_string(char *text, char *edit)
Edits the provided text based on the specified edit commands.
Definition edit_string.c:75
#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_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
long fexists(const char *filename)
Checks if a file exists.
Definition fexists.c:27
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c: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