SDDSlib
Loading...
Searching...
No Matches
SDDS_mplsupport.c
Go to the documentation of this file.
1/**
2 * @file SDDS_mplsupport.c
3 * @brief Functions and definitions for handling SDDS datasets and integrating with MPL (Matplotlib).
4 *
5 * This file provides a collection of macros, type definitions, and functions designed to manipulate
6 * SDDS (Self Describing Data Sets) data structures for seamless integration with MPL (Matplotlib).
7 * The functionalities include data sampling, string manipulation, match processing, column and
8 * parameter handling, and writing MPL-compatible tables to SDDS files.
9 *
10 * @copyright
11 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
12 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
13 *
14 * @license
15 * This file is distributed under the terms of the Software License Agreement
16 * found in the file LICENSE included with this distribution.
17 *
18 * @authors
19 * M. Borland
20 * C. Saunders
21 * R. Soliday
22 */
23
24#include "mdb.h"
25#include "SDDS.h"
26#include "table.h"
27#include "match_string.h"
28
29#define COLUMN_BASED 0
30#define PARAMETER_BASED 1
31#define DATA_CLASS_KEYWORDS 2
32static char *data_class_keyword[DATA_CLASS_KEYWORDS] = {
33 "column", "parameter"};
34
35#define is_logic_character(c) ((c) == '|' || (c) == '&' || (c) == '!')
36
37typedef struct
38{
39 char *name, *string;
40 int32_t logic, last;
42
43/**
44 * @brief Copies elements from the source array to the target array with sampling.
45 *
46 * This function copies elements from the source array to the target array, selecting
47 * every `sample_interval`-th element from the source.
48 *
49 * @param target Pointer to the target array where sampled elements will be stored.
50 * @param source Pointer to the source array from which elements are copied.
51 * @param source_points Number of elements in the source array.
52 * @param sample_interval Interval at which elements are sampled from the source.
53 * @return The number of elements copied to the target array.
54 */
55int64_t copy_doubles_with_sampling(double *target, double *source, int64_t source_points, int64_t sample_interval) {
56 int64_t i, j;
57 for (i = j = 0; i < source_points; i += sample_interval, j++)
58 target[j] = source[i];
59 return (j);
60}
61
62/**
63 * @brief Removes specified bounding characters from a string.
64 *
65 * This function trims characters specified in `t` from both the beginning and the end
66 * of the string `s`. It modifies the string `s` in place and returns a pointer to it.
67 *
68 * @param s The string from which to remove bounding characters.
69 * @param t A string containing characters to be removed from the start and end of `s`.
70 * @return Pointer to the modified string `s`.
71 */
72char *delete_bounding_characters(char *s, char *t) {
73 register char *ptr1, *ptr0, *ptrt;
74
75 if (!s)
76 return (s);
77 ptr0 = s;
78 while (*ptr0) {
79 ptrt = t;
80 while (*ptrt && *ptrt != *ptr0)
81 ptrt++;
82 if (*ptrt == *ptr0)
83 ptr0++;
84 else
85 break;
86 }
87
88 ptr1 = ptr0 + strlen(ptr0) - 1;
89 while (ptr1 != ptr0) {
90 ptrt = t;
91 while (*ptrt && *ptrt != *ptr1)
92 ptrt++;
93 if (*ptrt == *ptr1)
94 ptr1--;
95 else
96 break;
97 }
98
99 *++ptr1 = 0;
100 strcpy_ss(s, ptr0);
101 return (s);
102}
103
104/**
105 * @brief Processes match requests for columns and parameters based on an option string.
106 *
107 * This function parses the `option_string` to generate match criteria for columns and
108 * parameters. It populates the `column_match` and `parameter_match` arrays with the
109 * corresponding match terms.
110 *
111 * @param column_match Double pointer to an array of MATCH_TERM structures for columns.
112 * @param parameter_match Double pointer to an array of MATCH_TERM structures for parameters.
113 * @param option_string The string containing match options and criteria.
114 * @return Returns 1 on successful processing, or 0 if an error occurs.
115 */
116int32_t process_match_requests(MATCH_TERM **column_match, MATCH_TERM **parameter_match, char *option_string) {
117 int64_t i, matches, arguments, data_class;
118 int64_t need_name, need_operation;
119 char *ptr, **argument, *token;
120 MATCH_TERM *match;
121 char s[400], t[200];
122
123 *column_match = *parameter_match = NULL;
124 argument = NULL;
125
126 while ((token = get_token_t(option_string, " "))) {
127 if (SDDS_StringIsBlank(token))
128 break;
129 arguments = 0;
130 argument = trealloc(argument, sizeof(*argument) * (arguments + 1));
131 strcpy(t, token);
132 while ((argument[arguments] = get_token_t(token, ","))) {
133 arguments++;
134 argument = trealloc(argument, sizeof(*argument) * (arguments + 1));
135 }
136 match = NULL;
137 matches = 0;
138 switch (data_class = match_string(argument[0], data_class_keyword, DATA_CLASS_KEYWORDS, UNIQUE_MATCH)) {
139 case COLUMN_BASED:
140 if (*column_match) {
141 SDDS_SetError("Only one column-based match request is allowed (process_match_request)");
142 return (0);
143 }
144 break;
145 case PARAMETER_BASED:
146 if (*parameter_match) {
147 SDDS_SetError("Only one parameter-based match request is allowed (process_match_request)");
148 return (0);
149 }
150 break;
151 default:
152 sprintf(s, "Unrecognized keyword for match-type: %s\nToken was: %s\nspecify column or parameter (process_match_request)", argument[0], t);
153 SDDS_SetError(s);
154 return (0);
155 }
156
157 need_name = 1;
158 need_operation = -1;
159 i = 1;
160 do {
161 if (is_logic_character(argument[i][0])) {
162 if (need_name)
163 return (0);
164 do {
165 /* will come here only for &, |, or ! applying to expressions */
166 if (need_name)
167 return (0);
168 switch (argument[i][0]) {
169 case '&':
170 if (match[matches].logic & SDDS_AND || match[matches].logic & SDDS_OR || match[matches].logic & SDDS_NEGATE_EXPRESSION)
171 return (0);
172 match[matches].logic |= SDDS_AND;
173 break;
174 case '|':
175 if (match[matches].logic & SDDS_AND || match[matches].logic & SDDS_OR || match[matches].logic & SDDS_NEGATE_EXPRESSION)
176 return (0);
177 match[matches].logic |= SDDS_OR;
178 break;
179 case '!':
180 if (!(match[matches].logic & SDDS_AND || match[matches].logic & SDDS_OR) || match[matches].logic & SDDS_NEGATE_EXPRESSION)
181 return (0);
182 match[matches].logic |= SDDS_NEGATE_EXPRESSION;
183 }
184 } while (++i < arguments && is_logic_character(argument[i][0]));
185 matches++;
186 if (i >= arguments)
187 break;
188 need_name = 1;
189 } else if (need_operation > 0)
190 return (0);
191
192 /* should have a name=string object now */
193 if (is_logic_character(argument[i][0]))
194 return (0);
195 if (arguments - i < 1)
196 return (0);
197 match = trealloc(match, sizeof(*match) * (matches + 1));
198 if (!(ptr = strchr(argument[i], '=')))
199 return (0);
200 *ptr = 0;
201 match[matches].name = argument[i++];
202 match[matches].string = ptr + 1;
203 match[matches].logic = 0;
204 match[matches].last = 1;
205 if (matches)
206 match[matches - 1].last = 0;
207 if (arguments - i > 0 && argument[i][0] == '!') {
208 match[matches].logic = SDDS_NEGATE_MATCH;
209 i++;
210 }
211 if (++need_operation > 0)
212 need_name = 0;
213 else
214 matches++;
215 } while (arguments > i);
216 match[0].logic |= SDDS_AND;
217 if (data_class == COLUMN_BASED)
218 *column_match = match;
219 else
220 *parameter_match = match;
221 }
222 return (1);
223}
224
225/**
226 * @brief Prints a list of columns in the SDDS dataset.
227 *
228 * This function outputs the list of available columns in the provided SDDS dataset to the specified file pointer.
229 *
230 * @param SDDS_dataset Pointer to the SDDS_DATASET structure containing dataset information.
231 * @param message A message to display before listing the columns.
232 * @param fp File pointer where the list of columns will be printed.
233 */
234void SDDS_PrintListOfColumns(SDDS_DATASET *SDDS_dataset, char *message, FILE *fp) {
235 char **name;
236 int32_t names, i;
237
238 if (!(name = SDDS_GetColumnNames(SDDS_dataset, &names))) {
239 SDDS_SetError("Problem getting list of column names");
240 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
241 } else {
242 if (!names)
243 fputs("no columns defined in this file\n", fp);
244 else {
245 fputs(message, fp);
246 for (i = 0; i < names; i++)
247 fprintf(fp, " %s\n", name[i]);
248 }
249 }
250}
251
252/**
253 * @brief Prints a list of parameters in the SDDS dataset.
254 *
255 * This function outputs the list of available parameters in the provided SDDS dataset to the specified file pointer.
256 *
257 * @param SDDS_dataset Pointer to the SDDS_DATASET structure containing dataset information.
258 * @param message A message to display before listing the parameters.
259 * @param fp File pointer where the list of parameters will be printed.
260 */
261void SDDS_PrintListOfParameters(SDDS_DATASET *SDDS_dataset, char *message, FILE *fp) {
262 char **name;
263 int32_t names, i;
264
265 if (!(name = SDDS_GetParameterNames(SDDS_dataset, &names))) {
266 SDDS_SetError("Problem getting list of parameter names");
267 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
268 } else {
269 if (!names)
270 fputs("no parameters defined in this file\n", fp);
271 else {
272 fputs(message, fp);
273 for (i = 0; i < names; i++)
274 fprintf(fp, " %s\n", name[i]);
275 }
276 }
277}
278
279/**
280 * @brief Reads SDDS data into an MPL-compatible table structure.
281 *
282 * This function initializes an SDDS dataset from the specified file, processes the data
283 * according to the provided sample interval and flags, and populates the `mpl_data` table
284 * with the sampled data. It handles column and parameter-based matching as specified by
285 * `SDDS_tags`.
286 *
287 * @param mpl_data Pointer to the TABLE structure where the SDDS data will be stored.
288 * @param file The filename of the SDDS data file to read.
289 * @param sample_interval The interval at which data points are sampled from the source.
290 * @param mpl_flags Flags controlling the behavior of the MPL data processing.
291 * @param SDDS_tags Optional tags specifying columns or parameters of interest.
292 * @return Returns 1 on successful reading and processing, or 0 if an error occurs.
293 */
294int32_t SDDS_ReadIntoMplTable(TABLE *mpl_data, char *file, int64_t sample_interval, int32_t mpl_flags, char *SDDS_tags) {
295 SDDS_DATASET SDDS_dataset;
296 int32_t first;
297 int64_t i, new_points, n_rows;
298 SDDS_LAYOUT *layout;
299 char *xname, *yname, *sxname, *syname, *option_string, *ptr;
300 COLUMN_DEFINITION *xdef, *ydef, *sxdef, *sydef;
301 PARAMETER_DEFINITION *xpdef, *ypdef, *sxpdef, *sypdef;
302 PARAMETER_DEFINITION *titledef, *toplinedef, *pardef;
303 char s[SDDS_MAXLINE];
304 double *data;
305 MATCH_TERM *column_match, *parameter_match;
306 int32_t accept = 1;
307
308 xname = yname = sxname = syname = NULL;
309 xdef = ydef = sxdef = sydef = NULL;
310 xpdef = ypdef = sxpdef = sypdef = titledef = toplinedef = NULL;
311 n_rows = 0;
312
313 if (!SDDS_InitializeInput(&SDDS_dataset, file)) {
314 SDDS_PrintErrors(stderr, 1);
315 return (0);
316 }
317 layout = &SDDS_dataset.layout;
318 if (SDDS_dataset.layout.n_columns < 1 && SDDS_dataset.layout.n_parameters < 1)
319 return (0);
320
321 first = 1;
322 while (SDDS_ReadPage(&SDDS_dataset) > 0) {
323 if (first) {
324 first = 0;
325#if 0
326 if ((pardef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplTitle")) && pardef->type == SDDS_STRING)
327 mpl_data->title = SDDS_GetParameter(&SDDS_dataset, "mplTitle", NULL);
328 else
329 SDDS_CopyString(&mpl_data->title, "");
330 if ((pardef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplTopline")) && pardef->type == SDDS_STRING)
331 mpl_data->topline = SDDS_GetParameter(&SDDS_dataset, "mplTopline", NULL);
332 else
333 SDDS_CopyString(&mpl_data->topline, "");
334#endif
335
336 xname = yname = sxname = syname = option_string = NULL;
337 xdef = ydef = sxdef = sydef = NULL;
338 xpdef = ypdef = sxpdef = sypdef = NULL;
339 if (SDDS_tags) {
340 /* expect columns-of-interest to be specified in this string as
341 * <xname>+<yname>[+<syname>][,<options>] or
342 * <xname>+<yname>[+<sxname>+<syname>][,<options>]
343 */
344 xname = SDDS_tags;
345 if ((yname = strchr(xname, '+'))) {
346 ptr = yname;
347 while ((option_string = strchr(ptr, ','))) {
348 if (option_string != ptr && *(option_string - 1) == '\\')
349 ptr = option_string + 1;
350 else {
351 *option_string++ = 0;
352 break;
353 }
354 }
355 *yname++ = 0;
356 if ((sxname = strchr(yname, '+'))) {
357 *sxname++ = 0;
358 if ((syname = strchr(sxname, '+'))) {
359 *syname++ = 0;
360 } else {
361 syname = sxname;
362 sxname = NULL;
363 }
364 }
365 }
366 delete_bounding_characters(xname, "\"'");
367 delete_bounding_characters(yname, "\"'");
368 if (sxname)
369 delete_bounding_characters(sxname, "\"'");
370 if (syname)
371 delete_bounding_characters(syname, "\"'");
372 }
373
374 if (!xname || !yname) {
375 xname = yname = NULL;
376 /* No columns-of-interest found in SDDS_tags. Check for parameters mplxName and mplyName */
377 if ((pardef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplxName")) && pardef->type == SDDS_STRING && (pardef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplyName")) && pardef->type == SDDS_STRING) {
378 xname = SDDS_GetParameter(&SDDS_dataset, "mplxName", NULL);
379 yname = SDDS_GetParameter(&SDDS_dataset, "mplyName", NULL);
380 if (xname && yname) {
381 /* check for mplSigmaxName and mplSigmayName */
382 if ((pardef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplSigmayName")) && pardef->type == SDDS_STRING)
383 syname = SDDS_GetParameter(&SDDS_dataset, "mplSigmayName", NULL);
384 if ((pardef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplSigmaxName")) && pardef->type == SDDS_STRING)
385 sxname = SDDS_GetParameter(&SDDS_dataset, "mplSigmaxName", NULL);
386 }
387 }
388 }
389
390 if (!xname || !yname) {
391 /* No columns-of-interest found in SDDS_tags or parameters. Just take the first two numeric
392 * column definitions in order
393 */
394 for (i = 0; i < layout->n_columns; i++) {
395 if (SDDS_NUMERIC_TYPE(layout->column_definition[i].type)) {
396 if (!xname)
397 xname = layout->column_definition[i].name;
398 else if (!yname)
399 yname = layout->column_definition[i].name;
400 else
401 break;
402 }
403 }
404 if (sxname && !syname) {
405 syname = sxname;
406 sxname = NULL;
407 }
408 }
409
410 if (!xname || !yname)
411 return (0);
412
413 if (!((xdef = SDDS_GetColumnDefinition(&SDDS_dataset, xname)) && SDDS_NUMERIC_TYPE(xdef->type)) && !((xpdef = SDDS_GetParameterDefinition(&SDDS_dataset, xname)) && SDDS_NUMERIC_TYPE(xpdef->type))) {
414 fprintf(stderr, "error: column (or parameter) %s does not exist or is non-numeric\n", xname);
415 SDDS_PrintListOfColumns(&SDDS_dataset, "Valid columns are:\n", stderr);
416 SDDS_PrintListOfParameters(&SDDS_dataset, "Valid parameters are:\n", stderr);
417 return (0);
418 }
419 if (xdef) {
420 if (!((ydef = SDDS_GetColumnDefinition(&SDDS_dataset, yname)) && SDDS_NUMERIC_TYPE(ydef->type))) {
421 fprintf(stderr, "error: column %s does not exist or is non-numeric\n", yname);
422 SDDS_PrintListOfColumns(&SDDS_dataset, "Valid columns are:\n", stderr);
423 return (0);
424 }
425 if (sxname && !((sxdef = SDDS_GetColumnDefinition(&SDDS_dataset, sxname)) && SDDS_NUMERIC_TYPE(sxdef->type))) {
426 fprintf(stderr, "error: column %s does not exist or is non-numeric\n", sxname);
427 SDDS_PrintListOfColumns(&SDDS_dataset, "Valid columns are:\n", stderr);
428 return (0);
429 }
430 if (syname && !((sydef = SDDS_GetColumnDefinition(&SDDS_dataset, syname)) && SDDS_NUMERIC_TYPE(sydef->type))) {
431 fprintf(stderr, "error: column %s does not exist or is non-numeric\n", syname);
432 SDDS_PrintListOfColumns(&SDDS_dataset, "Valid columns are:\n", stderr);
433 return (0);
434 }
435 if (xdef->symbol && !(mpl_flags & SDDS_NOCOMPRESS_NAMES))
436 delete_chars(xdef->symbol, " ");
437 if (ydef->symbol && !(mpl_flags & SDDS_NOCOMPRESS_NAMES))
438 delete_chars(ydef->symbol, " ");
439 if (sxdef && sxdef->symbol && !(mpl_flags & SDDS_NOCOMPRESS_NAMES))
440 delete_chars(sxdef->symbol, " ");
441 if (sydef && sydef->symbol && !(mpl_flags & SDDS_NOCOMPRESS_NAMES))
442 delete_chars(sydef->symbol, " ");
443
444 if (xdef->units && !SDDS_StringIsBlank(xdef->units))
445 sprintf(s, "%s (%s)", xdef->symbol ? xdef->symbol : xdef->name, xdef->units);
446 else
447 sprintf(s, "%s", xdef->symbol ? xdef->symbol : xdef->name);
448 SDDS_CopyString(&mpl_data->xlab, s);
449 if (ydef->units && !SDDS_StringIsBlank(ydef->units))
450 sprintf(s, "%s (%s)", ydef->symbol ? ydef->symbol : ydef->name, ydef->units);
451 else
452 sprintf(s, "%s", ydef->symbol ? ydef->symbol : ydef->name);
453 SDDS_CopyString(&mpl_data->ylab, s);
454 toplinedef = titledef = NULL;
455 if ((toplinedef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplTopline")) && (toplinedef->type != SDDS_STRING || !SDDS_GetParameter(&SDDS_dataset, toplinedef->name, &mpl_data->topline))) {
457 toplinedef = NULL;
458 }
459 if (!toplinedef) {
460 if (layout->description)
461 SDDS_CopyString(&mpl_data->topline, layout->description);
462 else
463 SDDS_CopyString(&mpl_data->topline, "");
464 }
465 if ((titledef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplTitle"))) {
466 if (titledef->type != SDDS_STRING || !SDDS_GetParameter(&SDDS_dataset, titledef->name, &mpl_data->title))
467 titledef = NULL;
468 }
469 if (!titledef) {
470 if (!option_string)
471 sprintf(s, "%s vs %s", ydef->description ? ydef->description : (ydef->symbol ? ydef->symbol : yname), xdef->description ? xdef->description : (xdef->symbol ? xdef->symbol : xname));
472 else
473 sprintf(s, "%s vs %s : %s", ydef->description ? ydef->description : (ydef->symbol ? ydef->symbol : yname), xdef->description ? xdef->description : (xdef->symbol ? xdef->symbol : xname), option_string);
474 SDDS_CopyString(&mpl_data->title, s);
475 }
476 } else {
477 if (!((ypdef = SDDS_GetParameterDefinition(&SDDS_dataset, yname)) && SDDS_NUMERIC_TYPE(ypdef->type))) {
478 fprintf(stderr, "error: parameter %s does not exist or is non-numeric\n", yname);
479 SDDS_PrintListOfParameters(&SDDS_dataset, "Valid parameters are:\n", stderr);
480 return (0);
481 }
482 if (sxname && !((sxpdef = SDDS_GetParameterDefinition(&SDDS_dataset, sxname)) && SDDS_NUMERIC_TYPE(sxpdef->type))) {
483 fprintf(stderr, "error: parameter %s does not exist or is non-numeric\n", sxname);
484 SDDS_PrintListOfParameters(&SDDS_dataset, "Valid parameters are:\n", stderr);
485 return (0);
486 }
487 if (syname && !((sypdef = SDDS_GetParameterDefinition(&SDDS_dataset, syname)) && SDDS_NUMERIC_TYPE(sypdef->type))) {
488 fprintf(stderr, "error: parameter %s does not exist or is non-numeric\n", syname);
489 SDDS_PrintListOfParameters(&SDDS_dataset, "Valid parameters are:\n", stderr);
490 return (0);
491 }
492
493 if (xpdef->units && !SDDS_StringIsBlank(xpdef->units))
494 sprintf(s, "%s (%s)", xpdef->symbol ? delete_chars(xpdef->symbol, " ") : xpdef->name, xpdef->units);
495 else
496 sprintf(s, "%s", xpdef->symbol ? delete_chars(xpdef->symbol, " ") : xpdef->name);
497 SDDS_CopyString(&mpl_data->xlab, s);
498 if (ypdef->units && !SDDS_StringIsBlank(ypdef->units))
499 sprintf(s, "%s (%s)", ypdef->symbol ? delete_chars(ypdef->symbol, " ") : ypdef->name, ypdef->units);
500 else
501 sprintf(s, "%s", ypdef->symbol ? delete_chars(ypdef->symbol, " ") : ypdef->name);
502 SDDS_CopyString(&mpl_data->ylab, s);
503 toplinedef = titledef = NULL;
504 if ((toplinedef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplTopline")) && (toplinedef->type != SDDS_STRING || !SDDS_GetParameter(&SDDS_dataset, toplinedef->name, &mpl_data->topline))) {
506 toplinedef = NULL;
507 }
508 if (!toplinedef) {
509 if (layout->description)
510 SDDS_CopyString(&mpl_data->topline, layout->description);
511 else
512 SDDS_CopyString(&mpl_data->topline, "");
513 }
514 if ((titledef = SDDS_GetParameterDefinition(&SDDS_dataset, "mplTitle"))) {
515 if (titledef->type != SDDS_STRING || !SDDS_GetParameter(&SDDS_dataset, titledef->name, &mpl_data->title))
516 titledef = NULL;
517 }
518 if (!titledef) {
519 if (!option_string)
520 sprintf(s, "%s vs %s", ypdef->description ? ypdef->description : (ypdef->symbol ? ypdef->symbol : yname), xpdef->description ? xpdef->description : (xpdef->symbol ? xpdef->symbol : xname));
521 else
522 sprintf(s, "%s vs %s : %s", ypdef->description ? ypdef->description : (ypdef->symbol ? ypdef->symbol : yname), xpdef->description ? xpdef->description : (xpdef->symbol ? xpdef->symbol : xname), option_string);
523 SDDS_CopyString(&mpl_data->title, s);
524 }
525 }
526
527 mpl_data->c1 = mpl_data->c2 = mpl_data->s1 = mpl_data->s2 = NULL;
528 mpl_data->n_data = 0;
529 mpl_data->flags = (sxname ? SIGMA_X_PRESENT : 0) + (syname ? SIGMA_Y_PRESENT : 0);
530
531 column_match = parameter_match = NULL;
532 if (option_string && !process_match_requests(&column_match, &parameter_match, option_string))
533 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
534 } /* end of block for first page */
535 if (!SDDS_dataset.n_rows && xdef)
536 continue;
537
538 accept = 1;
539 if (parameter_match) {
540 i = -1;
541 do {
542 i++;
543 if (!(pardef = SDDS_GetParameterDefinition(&SDDS_dataset, parameter_match[i].name)) || !(pardef->type == SDDS_STRING || pardef->type == SDDS_CHARACTER)) {
544 fprintf(stderr, "error: unknown or numeric parameter %s given for match\n", parameter_match[i].name);
545 exit(1);
546 }
547 if (pardef->type == SDDS_STRING) {
548 char **ppc;
549 ppc = SDDS_GetParameter(&SDDS_dataset, parameter_match[i].name, NULL);
550 strcpy(s, *ppc);
551 } else {
552 char *pc;
553 pc = SDDS_GetParameter(&SDDS_dataset, parameter_match[i].name, NULL);
554 sprintf(s, "%c", *pc);
555 }
556 accept = SDDS_Logic(accept, wild_match(s, parameter_match[i].string), parameter_match[i].logic);
557 } while (!parameter_match[i].last);
558 }
559 if (!accept)
560 continue;
561
562 if (xdef) {
563 if (!SDDS_SetColumnFlags(&SDDS_dataset, 1) ||
564 (sxname && syname &&
565 !SDDS_SetColumnsOfInterest(&SDDS_dataset, SDDS_NAME_STRINGS, xname, yname, sxname, syname, NULL)) ||
566 (syname && !sxname && !SDDS_SetColumnsOfInterest(&SDDS_dataset, SDDS_NAME_STRINGS, xname, yname, syname, NULL)) || !SDDS_SetColumnsOfInterest(&SDDS_dataset, SDDS_NAME_STRINGS, xname, yname, NULL))
567 return (0);
568
569 if (column_match) {
570 i = -1;
571 do {
572 i++;
573 if (SDDS_MatchRowsOfInterest(&SDDS_dataset, column_match[i].name, column_match[i].string, column_match[i].logic) < 0) {
574 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
575 exit(1);
576 }
577 } while (!column_match[i].last);
578 }
579
580 if ((n_rows = SDDS_CountRowsOfInterest(&SDDS_dataset)) <= 0)
581 continue;
582
583 if (!(new_points = ceil((1.0 * n_rows) / sample_interval)))
584 new_points = 1;
585 } else
586 new_points = 1;
587
588 /* allocate all four arrays, since that is the expected behavior from get_table() */
589 if (!(mpl_data->c1 = SDDS_Realloc(mpl_data->c1, sizeof(*mpl_data->c1) * (mpl_data->n_data + new_points))) ||
590 !(mpl_data->c2 = SDDS_Realloc(mpl_data->c2, sizeof(*mpl_data->c2) * (mpl_data->n_data + new_points))) ||
591 !(mpl_data->s1 = SDDS_Realloc(mpl_data->s1, sizeof(*mpl_data->s1) * (mpl_data->n_data + new_points))) || !(mpl_data->s2 = SDDS_Realloc(mpl_data->s2, sizeof(*mpl_data->s2) * (mpl_data->n_data + new_points)))) {
592 SDDS_SetError("Allocation failure creating mpl-compatible structure");
593 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
594 }
595
596 for (i = 0; i < new_points; i++)
597 mpl_data->c1[i + mpl_data->n_data] = mpl_data->c2[i + mpl_data->n_data] = mpl_data->s1[i + mpl_data->n_data] = mpl_data->s2[i + mpl_data->n_data] = 0;
598
599 if (xdef) {
600 if (!(data = SDDS_GetColumnInDoubles(&SDDS_dataset, xdef->name)) || (i = copy_doubles_with_sampling((mpl_flags & SWAP ? mpl_data->c2 : mpl_data->c1) + mpl_data->n_data, data, n_rows, sample_interval)) != new_points) {
601 sprintf(s, "Sampling problem: %" PRId64 " rows created, %" PRId64 " expected", i, new_points);
602 SDDS_SetError(s);
603 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
604 return (0);
605 }
606 free(data);
607 if (!(data = SDDS_GetColumnInDoubles(&SDDS_dataset, ydef->name)) || (i = copy_doubles_with_sampling((mpl_flags & SWAP ? mpl_data->c1 : mpl_data->c2) + mpl_data->n_data, data, n_rows, sample_interval)) != new_points) {
608 sprintf(s, "Sampling problem: %" PRId64 " rows created, %" PRId64 " expected", i, new_points);
609 SDDS_SetError(s);
610 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
611 return (0);
612 }
613 free(data);
614 if (sxdef) {
615 if (!(data = SDDS_GetColumnInDoubles(&SDDS_dataset, sxdef->name)) || (i = copy_doubles_with_sampling((mpl_flags & SWAP ? mpl_data->s2 : mpl_data->s1) + mpl_data->n_data, data, n_rows, sample_interval)) != new_points) {
616 sprintf(s, "Sampling problem: %" PRId64 " rows created, %" PRId64 " expected", i, new_points);
617 SDDS_SetError(s);
618 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
619 return (0);
620 }
621 free(data);
622 }
623 if (sydef) {
624 if (!(data = SDDS_GetColumnInDoubles(&SDDS_dataset, sydef->name)) || (i = copy_doubles_with_sampling((mpl_flags & SWAP ? mpl_data->s1 : mpl_data->s2) + mpl_data->n_data, data, n_rows, sample_interval)) != new_points) {
625 sprintf(s, "Sampling problem: %" PRId64 " rows created, %" PRId64 " expected", i, new_points);
626 SDDS_SetError(s);
627 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
628 return (0);
629 }
630 free(data);
631 }
632 } else {
633 int32_t buffer[16];
634 SDDS_GetParameter(&SDDS_dataset, xpdef->name, buffer);
635 mpl_data->c1[mpl_data->n_data] = SDDS_ConvertToDouble(xpdef->type, buffer, 0);
636 SDDS_GetParameter(&SDDS_dataset, ypdef->name, buffer);
637 mpl_data->c2[mpl_data->n_data] = SDDS_ConvertToDouble(ypdef->type, buffer, 0);
638 if (sxpdef) {
639 SDDS_GetParameter(&SDDS_dataset, sxpdef->name, buffer);
640 mpl_data->s1[mpl_data->n_data] = SDDS_ConvertToDouble(sxpdef->type, buffer, 0);
641 }
642 if (sypdef) {
643 SDDS_GetParameter(&SDDS_dataset, sypdef->name, buffer);
644 mpl_data->s2[mpl_data->n_data] = SDDS_ConvertToDouble(sypdef->type, buffer, 0);
645 }
646 if (SDDS_NumberOfErrors()) {
647 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
648 return (0);
649 }
650 }
651 mpl_data->n_data += new_points;
652 }
653 if (xdef)
655 if (ydef)
657 if (sxdef)
659 if (sydef)
661 if (titledef)
663 if (toplinedef)
665 if (first || !SDDS_Terminate(&SDDS_dataset)) {
666 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
667 return (0);
668 }
669 return (1);
670}
671
672/**
673 * @brief Cleans and fixes an MPL-compatible name by removing specific sequences and extra spaces.
674 *
675 * This function iterates through the provided `name` string and removes any occurrence of a
676 * dollar sign ('$') followed by specific characters (`'a'`, `'b'`, `'n'`, `'g'`, `'r'`,
677 * `'s'`, `'e'`, `'d'`, `'i'`, `'v'`, `'u'`). Additionally, it removes any extra spaces within
678 * the string, ensuring that only single spaces remain between words.
679 *
680 * @param name A mutable string representing the name to be fixed. The string is modified in place.
681 *
682 * @note This function assumes that the `name` string is mutable and has sufficient space to handle in-place modifications.
683 */
684void SDDS_FixMplName(char *name) {
685 char *ptr, *ptr1;
686 ptr = name;
687 while ((ptr = strchr(ptr, '$'))) {
688 switch (*(ptr + 1)) {
689 case 'a':
690 case 'b':
691 case 'n':
692 case 'g':
693 case 'r':
694 case 's':
695 case 'e':
696 case 'd':
697 case 'i':
698 case 'v':
699 case 'u':
700 strcpy(ptr, ptr + 2);
701 break;
702 default:
703 ptr += 1;
704 break;
705 }
706 }
707 ptr = name;
708 while ((ptr = strchr(ptr, ' '))) {
709 ptr1 = ptr;
710 while (*ptr1 == ' ')
711 ptr1++;
712 strcpy(ptr, ptr1);
713 }
714}
715
716/**
717 * @brief Extracts the name and unit from a labeled string.
718 *
719 * This function parses a label string to separate the name and its associated unit. It looks for
720 * the pattern " (unit)" within the label. If found, it splits the label into the `name` and `unit`
721 * components. The function also trims any trailing spaces from the `name`.
722 *
723 * @param name Double pointer to a string where the extracted name will be stored. Memory is allocated internally.
724 * @param unit Double pointer to a string where the extracted unit will be stored. Memory is allocated internally.
725 * If no unit is found, `*unit` is set to `NULL`.
726 * @param label The input label string containing the name and optionally the unit in the format "Name (Unit)".
727 *
728 * @note The caller is responsible for freeing the memory allocated for `*name` and `*unit` if they are not `NULL`.
729 */
730void SDDS_ExtractNameAndUnit(char **name, char **unit, char *label) {
731 char *ptr, *uptr;
732
733 if ((uptr = strstr(label, " ("))) {
734 *uptr = 0;
735 uptr += 2;
736 if ((ptr = strchr(uptr, ')')))
737 *ptr = 0;
738 SDDS_CopyString(unit, uptr);
739 } else
740 *unit = NULL;
741 ptr = label + strlen(label) - 1;
742 while (ptr != label && *ptr == ' ')
743 *ptr-- = 0;
744 SDDS_CopyString(name, label);
745}
746
747/**
748 * @brief Adds an MPL-compatible column definition to an SDDS dataset.
749 *
750 * This function defines a new column in the provided `SDDS_dataset` based on the given label, suffix,
751 * and default name. It handles the extraction of the symbol and unit from the label, ensures that
752 * the column name is unique within the dataset, and appends the suffix to create the final column name.
753 *
754 * @param SDDS_dataset Pointer to the SDDS_DATASET structure where the column will be added.
755 * @param label The label string containing the name and optionally the unit in the format "Name (Unit)".
756 * @param suffix An optional suffix to append to the column name. Can be `NULL` if no suffix is needed.
757 * @param default_name The default name to use if the `label` is blank.
758 * @param filename The name of the file being processed, used for error reporting.
759 *
760 * @return Returns the index of the newly added column on success, or `-1` if an error occurs.
761 *
762 * @see SDDS_DefineColumn
763 */
764int32_t SDDS_AddMplDefinition(SDDS_DATASET *SDDS_dataset, char *label, char *suffix, char *default_name, char *filename) {
765 char *symbol, *name, *unit;
766 int32_t index;
767
768 unit = NULL;
769 if (SDDS_StringIsBlank(label)) {
770 name = SDDS_Malloc(sizeof(*name) * (strlen(default_name) + (suffix ? strlen(suffix) : 0) + 1));
771 sprintf(name, "%s%s", default_name, suffix ? suffix : "");
772 SDDS_CopyString(&symbol, name);
773 } else {
774 SDDS_ExtractNameAndUnit(&symbol, &unit, label);
775 name = SDDS_Malloc(sizeof(*name) * (strlen(symbol) + (suffix ? strlen(suffix) : 0) + 1));
776 sprintf(name, "%s%s", symbol, suffix ? suffix : "");
777 SDDS_FixMplName(name);
778 }
779 if (SDDS_GetColumnIndex(SDDS_dataset, name) >= 0) {
780 fprintf(stderr, "error: column name %s already exists in file %s\n", name, filename);
781 return -1;
782 }
783 if ((index = SDDS_DefineColumn(SDDS_dataset, name, symbol, unit, NULL, NULL, SDDS_DOUBLE, 0)) < 0) {
784 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
785 return -1;
786 }
787 free(name);
788 free(symbol);
789 if (unit)
790 free(unit);
791 return index;
792}
793
794/**
795 * @brief Writes an MPL-compatible table to an SDDS file.
796 *
797 * This function initializes an SDDS output file, defines necessary columns based on the provided
798 * `mpl_data`, and writes the data to the file. It handles optional sigma columns, ensures that
799 * the output file does not overwrite existing files by renaming them if necessary, and respects
800 * environment variables for output configuration.
801 *
802 * @param mpl_data Pointer to the TABLE structure containing MPL data to be written.
803 * @param file The filename of the SDDS file where the data will be written.
804 *
805 * @return Returns `1` on successful writing of the MPL table, or `0` if an error occurs.
806 *
807 * @note This function relies on several SDDS utility functions and assumes that the SDDS library
808 * is properly initialized and configured.
809 *
810 * @see SDDS_DefineColumn
811 * @see SDDS_WritePage
812 */
813int32_t SDDS_WriteMplTable(TABLE *mpl_data, char *file) {
814 SDDS_DATASET page;
815 char *mplSDDSOutput = NULL;
816 int32_t mplSDDS_datamode = SDDS_BINARY, mplSDDS_disable = 1;
817 int32_t sx_index, sy_index;
818
819 if (!mpl_data) {
820 fprintf(stderr, "error: NULL mpl TABLE passed (SDDS_WriteMplTable)\n");
821 return 0;
822 }
823 if (!file) {
824 fprintf(stderr, "error: NULL filename passed (SDDS_WriteMplTable)\n");
825 return 0;
826 }
827 if (!mplSDDSOutput) {
828 if (!(mplSDDSOutput = getenv("mplSDDSOutput")))
829 SDDS_CopyString(&mplSDDSOutput, "");
830 }
831 if (mplSDDSOutput[0]) {
832 if (strstr(mplSDDSOutput, "enable"))
833 mplSDDS_disable = 0;
834 if (strstr(mplSDDSOutput, "ascii"))
835 mplSDDS_datamode = SDDS_ASCII;
836 }
837
838 if (mplSDDS_disable)
839 return 0;
840
841 if (fexists(file)) {
842 char *buffer;
843 buffer = SDDS_Malloc(sizeof(*file) * (strlen(file) + 2));
844 sprintf(buffer, "%s~", file);
845 if (rename(file, buffer) != 0) {
846 SDDS_SetError("Cannot save previous version of output file (SDDS_WriteMplTable)");
847 free(buffer);
848 return 0;
849 }
850 free(buffer);
851 }
852
853 if (!SDDS_InitializeOutput(&page, mplSDDS_datamode, 1, NULL, NULL, file) ||
854 (mpl_data->topline && !SDDS_StringIsBlank(mpl_data->topline) && SDDS_DefineParameter(&page, "mplTopline", NULL, NULL, NULL, NULL, SDDS_STRING, mpl_data->topline) < 0) || (mpl_data->title && !SDDS_StringIsBlank(mpl_data->title) && SDDS_DefineParameter(&page, "mplTitle", NULL, NULL, NULL, NULL, SDDS_STRING, mpl_data->title) < 0)) {
855 SDDS_SetError("Problem initializing SDDS output of mpl page data (SDDS_WriteMplTable)");
856 return 0;
857 }
858 if (SDDS_AddMplDefinition(&page, mpl_data->xlab, NULL, "x", file) < 0 || SDDS_AddMplDefinition(&page, mpl_data->ylab, NULL, "y", file) < 0) {
859 SDDS_SetError("Unable to define primary mpl columns for SDDS output (SDDS_WriteMplTable)");
860 return 0;
861 }
862 sx_index = sy_index = -1;
863 if (mpl_data->flags & SIGMA_X_PRESENT && (sx_index = SDDS_AddMplDefinition(&page, mpl_data->xlab, "Sigma", "x", file)) < 0) {
864 SDDS_SetError("Unable to define sigma-x column for SDDS output (SDDS_WriteMplTable)");
865 return 0;
866 }
867 if (mpl_data->flags & SIGMA_Y_PRESENT && (sy_index = SDDS_AddMplDefinition(&page, mpl_data->ylab, "Sigma", "y", file)) < 0) {
868 SDDS_SetError("Unable to define sigma-y column for SDDS output (SDDS_WriteMplTable)");
869 return 0;
870 }
871 if (!SDDS_WriteLayout(&page)) {
872 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
873 return 0;
874 }
875 if (!SDDS_StartPage(&page, mpl_data->n_data)) {
876 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
877 return 0;
878 }
879 if (!SDDS_SetColumn(&page, SDDS_SET_BY_INDEX, mpl_data->c1, mpl_data->n_data, 0) ||
880 !SDDS_SetColumn(&page, SDDS_SET_BY_INDEX, mpl_data->c2, mpl_data->n_data, 1) || (sx_index >= 0 && !SDDS_SetColumn(&page, SDDS_SET_BY_INDEX, mpl_data->s1, mpl_data->n_data, sx_index)) || (sy_index >= 0 && !SDDS_SetColumn(&page, SDDS_SET_BY_INDEX, mpl_data->s2, mpl_data->n_data, sy_index))) {
881 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
882 return 0;
883 }
884 if (!SDDS_WritePage(&page) || !SDDS_Terminate(&page)) {
885 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
886 return 0;
887 }
888 return 1;
889}
890
891
892
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
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.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
int32_t SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Sets the acceptance flags for columns based on specified naming criteria.
int64_t SDDS_MatchRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *selection_column, char *label_to_match, int32_t logic)
Matches and marks rows of interest in an SDDS dataset based on label matching.
int32_t SDDS_Logic(int32_t previous, int32_t match, uint32_t logic)
Applies logical operations to determine the new state of a row flag based on previous and current mat...
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
int32_t SDDS_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value)
Sets the acceptance flags for all columns in the current data table of a data set.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int64_t copy_doubles_with_sampling(double *target, double *source, int64_t source_points, int64_t sample_interval)
Copies elements from the source array to the target array with sampling.
int32_t SDDS_ReadIntoMplTable(TABLE *mpl_data, char *file, int64_t sample_interval, int32_t mpl_flags, char *SDDS_tags)
Reads SDDS data into an MPL-compatible table structure.
int32_t SDDS_AddMplDefinition(SDDS_DATASET *SDDS_dataset, char *label, char *suffix, char *default_name, char *filename)
Adds an MPL-compatible column definition to an SDDS dataset.
int32_t SDDS_WriteMplTable(TABLE *mpl_data, char *file)
Writes an MPL-compatible table to an SDDS file.
int32_t process_match_requests(MATCH_TERM **column_match, MATCH_TERM **parameter_match, char *option_string)
Processes match requests for columns and parameters based on an option string.
void SDDS_FixMplName(char *name)
Cleans and fixes an MPL-compatible name by removing specific sequences and extra spaces.
void SDDS_PrintListOfParameters(SDDS_DATASET *SDDS_dataset, char *message, FILE *fp)
Prints a list of parameters in the SDDS dataset.
void SDDS_PrintListOfColumns(SDDS_DATASET *SDDS_dataset, char *message, FILE *fp)
Prints a list of columns in the SDDS dataset.
void SDDS_ExtractNameAndUnit(char **name, char **unit, char *label)
Extracts the name and unit from a labeled string.
char * delete_bounding_characters(char *s, char *t)
Removes specified bounding characters from a string.
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
double SDDS_ConvertToDouble(int32_t type, void *data, int64_t index)
Converts a value to double based on its type.
Definition SDDS_rpn.c:199
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
PARAMETER_DEFINITION * SDDS_GetParameterDefinition(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the definition of a specified parameter from the SDDS dataset.
int32_t SDDS_FreeParameterDefinition(PARAMETER_DEFINITION *source)
Frees memory allocated for a parameter definition.
char ** SDDS_GetParameterNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all parameters in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:639
int32_t SDDS_NumberOfErrors()
Retrieves the number of errors recorded by SDDS library routines.
Definition SDDS_utils.c:304
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
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
int32_t SDDS_FreeColumnDefinition(COLUMN_DEFINITION *source)
Frees memory allocated for a column definition.
COLUMN_DEFINITION * SDDS_GetColumnDefinition(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the definition of a specified column from the SDDS dataset.
Definition SDDS_utils.c:978
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138