SDDSlib
Loading...
Searching...
No Matches
SDDS_process.c
Go to the documentation of this file.
1/**
2 * @file SDDS_process.c
3 * @brief Processes SDDS layout headers and translates namelist structures.
4 *
5 * This file implements a suite of functions responsible for reading and processing
6 * SDDS (Self Describing Data Sets) layout headers. The primary purpose of these
7 * routines is to facilitate the translation between external namelist structures
8 * used for input and the internal data structures that store the SDDS layout.
9 *
10 * Key functionalities include:
11 * - Parsing description sections of SDDS datasets.
12 * - Handling column, parameter, array, and associate definitions.
13 * - Managing include commands and data modes.
14 * - Providing utility functions for tag-value pair extraction and namelist parsing.
15 *
16 * The implemented functions ensure robust argument checking and support for
17 * multiple protocol versions, allowing for future scalability and compatibility.
18 *
19 * @copyright
20 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
21 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
22 *
23 * @license
24 * This file is distributed under the terms of the Software License Agreement
25 * found in the file LICENSE included with this distribution.
26 *
27 * @authors
28 * M. Borland,
29 * C. Saunders,
30 * R. Soliday
31 * H. Shang
32 */
33
34#include "mdb.h"
35#include "match_string.h"
36#include "SDDS.h"
37#include "SDDS_internal.h"
38
39#undef DEBUG
40
41
42/**************************************************************************/
43/* These routines are the "routers" that call the processing routines for */
44/* the protocol version of the file being read. They also do a lot of */
45/* the argument checking. I've avoided using arrays of function ponters */
46/* here to allow for the possibility that future versions may require */
47/* additional arguments. */
48/**************************************************************************/
49
50/**
51 * @brief Process the description section of the SDDS dataset.
52 *
53 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
54 * @param s Pointer to the description string.
55 * @return Returns 1 on success, 0 on failure.
56 */
57int32_t SDDS_ProcessDescription(SDDS_DATASET *SDDS_dataset, char *s) {
58 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessDescription"))
59 return (0);
60 if (!s) {
61 SDDS_SetError("Unable to process description--namelist text pointer is NULL (SDDS_ProcessDescription)");
62 return (0);
63 }
64 switch (SDDS_dataset->layout.version) {
65 case 1:
66 return (SDDS1_ProcessDescription(SDDS_dataset, s));
67 case 2:
68 return (SDDS1_ProcessDescription(SDDS_dataset, s));
69 case 3:
70 return (SDDS1_ProcessDescription(SDDS_dataset, s));
71 case 4:
72 return (SDDS1_ProcessDescription(SDDS_dataset, s));
73 case 5:
74 return (SDDS1_ProcessDescription(SDDS_dataset, s));
75 default:
76 SDDS_SetError("Unable to process description--protocol version number is invalid (SDDS_ProcessDescription)");
77 return (0);
78 }
79}
80
81/**
82 * @brief Process the column definition section of the SDDS dataset.
83 *
84 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
85 * @param s Pointer to the column definition string.
86 * @return Returns 1 on success, 0 on failure.
87 */
88int32_t SDDS_ProcessColumnDefinition(SDDS_DATASET *SDDS_dataset, char *s) {
89 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS1_ProcessColumnDefinition"))
90 return (0);
91 if (!s) {
92 SDDS_SetError("Unable to process column definition--namelist text pointer NULL (SDDS1_ProcessColumnDefinition)");
93 return (0);
94 }
95 switch (SDDS_dataset->layout.version) {
96 case 1:
97 return (SDDS1_ProcessColumnDefinition(SDDS_dataset, s));
98 case 2:
99 return (SDDS1_ProcessColumnDefinition(SDDS_dataset, s));
100 case 3:
101 return (SDDS1_ProcessColumnDefinition(SDDS_dataset, s));
102 case 4:
103 return (SDDS1_ProcessColumnDefinition(SDDS_dataset, s));
104 case 5:
105 return (SDDS1_ProcessColumnDefinition(SDDS_dataset, s));
106 default:
107 SDDS_SetError("Unable to process column definition--protocol version number is invalid (SDDS_ProcessColumnDefinition)");
108 return (0);
109 }
110}
111
112/**
113 * @brief Process the parameter definition section of the SDDS dataset.
114 *
115 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
116 * @param s Pointer to the parameter definition string.
117 * @return Returns 1 on success, 0 on failure.
118 */
119int32_t SDDS_ProcessParameterDefinition(SDDS_DATASET *SDDS_dataset, char *s) {
120 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessParameterDefinition"))
121 return (0);
122 if (!s) {
123 SDDS_SetError("Unable to process parameter definition--namelist text pointer NULL (SDDS_ProcessParameterDefinition)");
124 return (0);
125 }
126 switch (SDDS_dataset->layout.version) {
127 case 1:
128 return (SDDS1_ProcessParameterDefinition(SDDS_dataset, s));
129 case 2:
130 return (SDDS1_ProcessParameterDefinition(SDDS_dataset, s));
131 case 3:
132 return (SDDS1_ProcessParameterDefinition(SDDS_dataset, s));
133 case 4:
134 return (SDDS1_ProcessParameterDefinition(SDDS_dataset, s));
135 case 5:
136 return (SDDS1_ProcessParameterDefinition(SDDS_dataset, s));
137 default:
138 SDDS_SetError("Unable to process parameter definition--protocol version number is invalid (SDDS_ProcessParameterDefinition)");
139 return (0);
140 }
141}
142
143/**
144 * @brief Process the include command within the SDDS dataset.
145 *
146 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
147 * @param s Pointer to the include command string.
148 * @return Returns a FILE pointer on success, NULL on failure.
149 */
150FILE *SDDS_ProcessIncludeCommand(SDDS_DATASET *SDDS_dataset, char *s) {
151 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessIncludeCommand"))
152 return (NULL);
153 if (!s) {
154 SDDS_SetError("Unable to process parameter definition--namelist text pointer NULL (SDDS_ProcessIncludeCommand)");
155 return (NULL);
156 }
157 switch (SDDS_dataset->layout.version) {
158 case 1:
159 return (SDDS1_ProcessIncludeCommand(SDDS_dataset, s));
160 case 2:
161 return (SDDS1_ProcessIncludeCommand(SDDS_dataset, s));
162 case 3:
163 return (SDDS1_ProcessIncludeCommand(SDDS_dataset, s));
164 case 4:
165 return (SDDS1_ProcessIncludeCommand(SDDS_dataset, s));
166 case 5:
167 return (SDDS1_ProcessIncludeCommand(SDDS_dataset, s));
168 default:
169 SDDS_SetError("Unable to process parameter definition--protocol version number is invalid (SDDS_ProcessIncludeCommand)");
170 return (0);
171 }
172}
173
174/**
175 * @brief Process the associate definition section of the SDDS dataset.
176 *
177 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
178 * @param s Pointer to the associate definition string.
179 * @return Returns 1 on success, 0 on failure.
180 */
181int32_t SDDS_ProcessAssociateDefinition(SDDS_DATASET *SDDS_dataset, char *s) {
182 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessAssociateDefinition"))
183 return (0);
184 if (!s) {
185 SDDS_SetError("Unable to process associate definition--namelist text pointer NULL (SDDS_ProcessAssociateDefinition)");
186 return (0);
187 }
188 switch (SDDS_dataset->layout.version) {
189 case 1:
190 return (SDDS1_ProcessAssociateDefinition(SDDS_dataset, s));
191 case 2:
192 return (SDDS1_ProcessAssociateDefinition(SDDS_dataset, s));
193 case 3:
194 return (SDDS1_ProcessAssociateDefinition(SDDS_dataset, s));
195 case 4:
196 return (SDDS1_ProcessAssociateDefinition(SDDS_dataset, s));
197 case 5:
198 return (SDDS1_ProcessAssociateDefinition(SDDS_dataset, s));
199 default:
200 SDDS_SetError("Unable to process associate definition--protocol version number is invalid (SDDS_ProcessAssociateDefinition)");
201 return (0);
202 }
203}
204
205/**
206 * @brief Process the data mode section of the SDDS dataset.
207 *
208 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
209 * @param s Pointer to the data mode string.
210 * @return Returns 1 on success, 0 on failure.
211 */
212int32_t SDDS_ProcessDataMode(SDDS_DATASET *SDDS_dataset, char *s) {
213 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessDataMode"))
214 return (0);
215 if (!s) {
216 SDDS_SetError("Unable to process data mode--namelist text pointer is NULL (SDDS_ProcessDataMode)");
217 return (0);
218 }
219 switch (SDDS_dataset->layout.version) {
220 case 1:
221 return (SDDS1_ProcessDataMode(SDDS_dataset, s));
222 case 2:
223 return (SDDS1_ProcessDataMode(SDDS_dataset, s));
224 case 3:
225 return (SDDS1_ProcessDataMode(SDDS_dataset, s));
226 case 4:
227 return (SDDS1_ProcessDataMode(SDDS_dataset, s));
228 case 5:
229 return (SDDS1_ProcessDataMode(SDDS_dataset, s));
230 default:
231 SDDS_SetError("Unable to process data mode--protocol version number is invalid (SDDS_ProcessDataMode)");
232 return (0);
233 }
234}
235
236/**
237 * @brief Process the array definition section of the SDDS dataset.
238 *
239 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
240 * @param s Pointer to the array definition string.
241 * @return Returns 1 on success, 0 on failure.
242 */
243int32_t SDDS_ProcessArrayDefinition(SDDS_DATASET *SDDS_dataset, char *s) {
244 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessArrayDefinition"))
245 return (0);
246 if (!s) {
247 SDDS_SetError("Unable to process array definition--namelist text pointer NULL (SDDS_ProcessArrayDefinition)");
248 return (0);
249 }
250 switch (SDDS_dataset->layout.version) {
251 case 1:
252 return (SDDS1_ProcessArrayDefinition(SDDS_dataset, s));
253 case 2:
254 return (SDDS1_ProcessArrayDefinition(SDDS_dataset, s));
255 case 3:
256 return (SDDS1_ProcessArrayDefinition(SDDS_dataset, s));
257 case 4:
258 return (SDDS1_ProcessArrayDefinition(SDDS_dataset, s));
259 case 5:
260 return (SDDS1_ProcessArrayDefinition(SDDS_dataset, s));
261 default:
262 SDDS_SetError("Unable to process array definition--protocol version number is invalid (SDDS_ProcessArrayDefinition)");
263 return (0);
264 }
265}
266
267/***********************************************************
268 * The SDDS_ProcessXString routines provide an easy-to-use
269 * alternative to the SDDS_DefineX routines for user programs.
270 */
271
272/**
273 * @brief Process a column definition string.
274 *
275 * This function parses a string containing column definition information and
276 * updates the SDDS dataset accordingly.
277 *
278 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
279 * @param string Pointer to the column definition string.
280 * @param mode Mode indicating how the column is defined.
281 * @return Returns 1 on success, 0 on failure.
282 */
283int32_t SDDS_ProcessColumnString(SDDS_DATASET *SDDS_dataset, char *string, int32_t mode) {
284 char *ptr1, *ptr2;
285 char *s;
286 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessColumnString"))
287 return (0);
288 if (!string)
289 return (0);
290 if (!SDDS_CopyString(&s, string))
291 return 0;
292 if (!(ptr1 = strchr(s, '&')) || !(ptr2 = strchr(ptr1, ' '))) {
293 free(s);
294 return 0;
295 }
296 *ptr2 = 0;
297 if (strcmp(ptr1, "&column") != 0) {
298 free(s);
299 return (0);
300 }
301 if (SDDS_ProcessColumnDefinition(SDDS_dataset, ptr2 + 1)) {
302 free(s);
303 SDDS_dataset->layout.column_definition[SDDS_dataset->layout.n_columns - 1].definition_mode = mode;
304 if (!SDDS_SaveLayout(SDDS_dataset))
305 return (0);
306 return (1);
307 }
308 free(s);
309 return (0);
310}
311
312/**
313 * @brief Process a parameter definition string.
314 *
315 * This function parses a string containing parameter definition information and
316 * updates the SDDS dataset accordingly.
317 *
318 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
319 * @param string Pointer to the parameter definition string.
320 * @param mode Mode indicating how the parameter is defined.
321 * @return Returns 1 on success, 0 on failure.
322 */
323int32_t SDDS_ProcessParameterString(SDDS_DATASET *SDDS_dataset, char *string, int32_t mode) {
324 char *ptr1, *ptr2;
325 char *s;
326 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessParameterString"))
327 return (0);
328 if (!string)
329 return (0);
330 if (!SDDS_CopyString(&s, string))
331 return 0;
332 if (!(ptr1 = strchr(s, '&')) || !(ptr2 = strchr(ptr1, ' '))) {
333 free(s);
334 return 0;
335 }
336 *ptr2 = 0;
337 if (strcmp(ptr1, "&parameter") != 0) {
338 free(s);
339 return (0);
340 }
341 if (SDDS_ProcessParameterDefinition(SDDS_dataset, ptr2 + 1)) {
342 free(s);
343 SDDS_dataset->layout.parameter_definition[SDDS_dataset->layout.n_parameters - 1].definition_mode = mode;
344 if (!SDDS_SaveLayout(SDDS_dataset))
345 return (0);
346 return (1);
347 }
348 free(s);
349 return (0);
350}
351
352/**
353 * @brief Process an array definition string.
354 *
355 * This function parses a string containing array definition information and
356 * updates the SDDS dataset accordingly.
357 *
358 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
359 * @param string Pointer to the array definition string.
360 * @return Returns 1 on success, 0 on failure.
361 */
362int32_t SDDS_ProcessArrayString(SDDS_DATASET *SDDS_dataset, char *string) {
363 char *ptr1, *ptr2;
364 char *s;
365 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessArrayString"))
366 return (0);
367 if (!string)
368 return (0);
369 if (!SDDS_CopyString(&s, string))
370 return 0;
371 if (!(ptr1 = strchr(s, '&')) || !(ptr2 = strchr(ptr1, ' '))) {
372 free(s);
373 return 0;
374 }
375 *ptr2 = 0;
376 if (strcmp(ptr1, "&array") != 0) {
377 free(s);
378 return (0);
379 }
380 if (SDDS_ProcessArrayDefinition(SDDS_dataset, ptr2 + 1)) {
381 free(s);
382 if (!SDDS_SaveLayout(SDDS_dataset))
383 return (0);
384 return (1);
385 }
386 free(s);
387 return (0);
388}
389
390/**
391 * @brief Process an associate definition string.
392 *
393 * This function parses a string containing associate definition information and
394 * updates the SDDS dataset accordingly.
395 *
396 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
397 * @param string Pointer to the associate definition string.
398 * @return Returns 1 on success, 0 on failure.
399 */
400int32_t SDDS_ProcessAssociateString(SDDS_DATASET *SDDS_dataset, char *string) {
401 char *ptr1, *ptr2;
402 char *s;
403
404 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ProcessAssociateString"))
405 return (0);
406 if (!string)
407 return (0);
408 if (!SDDS_CopyString(&s, string))
409 return 0;
410 if (!(ptr1 = strchr(s, '&')) || !(ptr2 = strchr(ptr1, ' '))) {
411 free(s);
412 return 0;
413 }
414 *ptr2 = 0;
415 if (strcmp(ptr1, "&associate") != 0) {
416 free(s);
417 return (0);
418 }
419 *ptr2 = ' ';
420 if (SDDS_ProcessAssociateDefinition(SDDS_dataset, ptr2 + 1)) {
421 free(s);
422 if (!SDDS_SaveLayout(SDDS_dataset))
423 return (0);
424 return (1);
425 }
426 free(s);
427 return (0);
428}
429
430/**
431 * @brief Retrieve a tag-value pair from the input string.
432 *
433 * This function parses a substring to extract a tag and its corresponding value.
434 * It handles quoted strings and escaped characters.
435 *
436 * @param ptr Pointer to the current position in the string.
437 * @param tag Double pointer to store the extracted tag.
438 * @param value Double pointer to store the extracted value.
439 * @return Returns a pointer to the next position in the string after the pair,
440 * or NULL if an error occurs.
441 */
442char *SDDS_GetTagValuePair(char *ptr, char **tag, char **value) {
443 /* char find; */
444 char buffer[1024];
445
446 if (!*ptr)
447 return NULL;
448 *tag = *value = NULL;
449 while (*ptr == ' ' || *ptr == ',' || *ptr == '\t')
450 ptr++;
451 if (!*ptr)
452 return ptr;
453
454 *tag = ptr; /* start of field name */
455 while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '=')
456 ptr++;
457 if (*ptr != '=') {
458 *ptr++ = 0; /* ends the field name */
459 /* skip something of the form <0 or more spaces>=<0 or more spaces> */
460 while (*ptr == ' ' || *ptr == '\t')
461 ptr++;
462 if (*ptr++ != '=' || !*ptr) {
463 sprintf(buffer, "Namelist error: Field name %s ends string", *tag);
464 SDDS_SetError(buffer);
465 return NULL;
466 }
467 } else {
468 *ptr++ = 0;
469 }
470 while (*ptr == ' ' || *ptr == '\t')
471 ptr++;
472 if (!*ptr) {
473 sprintf(buffer, "Namelist error: Field name %s ends string", *tag);
474 SDDS_SetError(buffer);
475 return NULL;
476 }
477 if (!strlen(*tag)) {
478 sprintf(buffer, "Namelist error: Field name is blank");
479 SDDS_SetError(buffer);
480 return NULL;
481 }
482
483 if (*ptr == '"' && *(ptr - 1) != '\\') {
484 ptr++;
485 if (*ptr == '"' && *(ptr - 1) != '\\') {
486 *ptr = 0;
487 *value = ptr;
488 return ptr + 1;
489 }
490 *value = ptr++;
491 while (*ptr && !(*ptr == '"' && *(ptr - 1) != '\\'))
492 ptr++;
493 if (*ptr == '"' && *(ptr - 1) != '\\')
494 *ptr = 0; /* end of value */
495 } else {
496 *value = ptr; /* start of value */
497 while (*ptr != ' ' && *ptr != ',' && *ptr != '\t' && *ptr)
498 ptr++;
499 if (!*ptr)
500 return ptr;
501 *ptr = 0; /* end of value */
502 }
503 return ptr + 1;
504}
505
506/**
507 * @brief Prepare the string for parsing tag-value pairs.
508 *
509 * This function removes the trailing '&end' if present and ensures there is no group name.
510 *
511 * @param s Pointer to the input string.
512 * @return Returns a pointer to the modified string ready for parsing.
513 */
515 char *ptr;
516 int32_t length;
517
518 /* remove the trailing &end if there is one */
519 if ((length = strlen(s)) >= 4) {
520 ptr = s + length - 4;
521 while (1) {
522 if (*ptr == '&' && (ptr == s || *(ptr - 1) != '\\') && strncmp(ptr, "&end", 4) == 0 && !SDDS_IsQuoted(s, ptr, '"')) {
523 *ptr = 0;
524 break;
525 }
526 if (ptr == s)
527 break;
528 ptr--;
529 }
530 }
531
532 /* make sure there is no group name */
533 while (*s == ' ')
534 s++;
535 if (*s == '&') {
536 while (*s && *s != ' ')
537 s++;
538 }
539 return s;
540}
541
542/**
543 * @brief Find the index of a field based on its tag.
544 *
545 * @param tag Pointer to the tag string.
546 * @param fieldInfo Array of SDDS_FIELD_INFORMATION structures.
547 * @param fieldInfos Number of elements in the fieldInfo array.
548 * @return Returns the index of the matching field, or -1 if not found.
549 */
550int32_t SDDS_FindFieldIndex(char *tag, SDDS_FIELD_INFORMATION *fieldInfo, int32_t fieldInfos) {
551 int32_t i;
552 for (i = 0; i < fieldInfos; i++) {
553 if (strcmp(tag, fieldInfo[i].name) == 0)
554 return i;
555 }
556 return -1;
557}
558
559/**
560 * @brief Match an enumeration string to its corresponding value.
561 *
562 * @param value Pointer to the enumeration string.
563 * @param enumPair Array of SDDS_ENUM_PAIR structures.
564 * @return Returns the corresponding integer value if matched, -1 otherwise.
565 */
566int32_t SDDS_MatchEnum(char *value, SDDS_ENUM_PAIR *enumPair) {
567 while (enumPair->name) {
568 if (strcmp(value, enumPair->name) == 0)
569 return enumPair->value;
570 enumPair++;
571 }
572 return -1;
573}
574
575/**
576 * @brief Parse a namelist string and populate the corresponding data structure.
577 *
578 * This function parses a namelist string containing tag-value pairs and assigns
579 * the values to the appropriate fields in the provided data structure based on
580 * the field information provided.
581 *
582 * @param data Pointer to the data structure to populate.
583 * @param fieldInfo Array of SDDS_FIELD_INFORMATION structures describing the fields.
584 * @param fieldInfos Number of elements in the fieldInfo array.
585 * @param s Pointer to the namelist string.
586 * @return Returns 1 on success, 0 on failure.
587 */
588int32_t SDDS_ParseNamelist(void *data, SDDS_FIELD_INFORMATION *fieldInfo, int32_t fieldInfos, char *s) {
589 char buffer[1024], *ptr, *tag, *value;
590 int32_t index, longValue;
591
593 while (*ptr && !SDDS_StringIsBlank(ptr) && (ptr = SDDS_GetTagValuePair(ptr, &tag, &value))) {
594 if (!tag)
595 break; /* normal termination */
596 if ((index = SDDS_FindFieldIndex(tag, fieldInfo, fieldInfos)) < 0) {
597 sprintf(buffer, "Unrecognized namelist tag given: %s", tag);
598 SDDS_SetError(buffer);
599 return 0;
600 } else {
601 if (fieldInfo[index].enumPair) {
602 if (fieldInfo[index].type != SDDS_LONG) {
603 fprintf(stderr, "SDDS_ParseNamelist: namelist setup problem---get expert help!\n");
604 exit(1);
605 }
606 /* map a string value into an integer */
607 if ((longValue = SDDS_MatchEnum(value, fieldInfo[index].enumPair)) < 0) {
608 sprintf(buffer, "Unrecognized value given for %s: %s", tag, value);
609 SDDS_SetError(buffer);
610 return 0;
611 } else
612 *((int32_t *)((char *)data + fieldInfo[index].offset)) = longValue;
613 } else {
614 switch (fieldInfo[index].type) {
615 case SDDS_STRING:
616 if (!(SDDS_CopyString((char **)((char *)data + fieldInfo[index].offset), value))) {
617 SDDS_SetError("Problem setting string value for namelist");
618 return 0;
619 }
620 break;
621 case SDDS_CHARACTER:
622 *((char *)data + fieldInfo[index].offset) = *value;
623 break;
624 case SDDS_SHORT:
625 if (!sscanf(value, "%hd", (short *)((char *)data + fieldInfo[index].offset))) {
626 SDDS_SetError("Problem scanning short value for namelist");
627 return 0;
628 }
629 break;
630 case SDDS_USHORT:
631 if (!sscanf(value, "%hu", (unsigned short *)((char *)data + fieldInfo[index].offset))) {
632 SDDS_SetError("Problem scanning unsigned short value for namelist");
633 return 0;
634 }
635 break;
636 case SDDS_LONG:
637 if (!sscanf(value, "%" SCNd32, (int32_t *)((char *)data + fieldInfo[index].offset))) {
638 SDDS_SetError("Problem scanning int32_t value for namelist");
639 return 0;
640 }
641 break;
642 case SDDS_ULONG:
643 if (!sscanf(value, "%" SCNu32, (uint32_t *)((char *)data + fieldInfo[index].offset))) {
644 SDDS_SetError("Problem scanning uint32_t value for namelist");
645 return 0;
646 }
647 break;
648 case SDDS_LONG64:
649 if (!sscanf(value, "%" SCNd64, (int64_t *)((char *)data + fieldInfo[index].offset))) {
650 SDDS_SetError("Problem scanning int64_t value for namelist");
651 return 0;
652 }
653 break;
654 case SDDS_ULONG64:
655 if (!sscanf(value, "%" SCNu64, (uint64_t *)((char *)data + fieldInfo[index].offset))) {
656 SDDS_SetError("Problem scanning uint64_t value for namelist");
657 return 0;
658 }
659 break;
660 case SDDS_LONGDOUBLE:
661 if (!sscanf(value, "%Lf", (long double *)((char *)data + fieldInfo[index].offset))) {
662 SDDS_SetError("Problem scanning long double value for namelist");
663 return 0;
664 }
665 break;
666 case SDDS_DOUBLE:
667 if (!sscanf(value, "%lf", (double *)((char *)data + fieldInfo[index].offset))) {
668 SDDS_SetError("Problem scanning double value for namelist");
669 return 0;
670 }
671 break;
672 case SDDS_FLOAT:
673 if (!sscanf(value, "%f", (float *)((char *)data + fieldInfo[index].offset))) {
674 SDDS_SetError("Problem scanning float value for namelist");
675 return 0;
676 }
677 break;
678 default:
679 SDDS_SetError("Internal error: unknown field information type");
680 return 0;
681 }
682 }
683 }
684 }
685 if (!ptr) {
686 SDDS_SetError("Problem parsing description namelist");
687 return 0;
688 }
689 return 1;
690}
691
692/***********************************************/
693/* SDDS protocol version 1 routines begin here */
694/***********************************************/
695
696/**
697 * @brief Process the description section for SDDS protocol version 1.
698 *
699 * @param SDDS_dataset Pointer to the SDDS_DATASET structure.
700 * @param s Pointer to the description string.
701 * @return Returns 1 on success, 0 on failure.
702 */
703int32_t SDDS1_ProcessDescription(SDDS_DATASET *SDDS_dataset, char *s) {
704 SDDS_dataset->layout.description = NULL;
705 SDDS_dataset->layout.contents = NULL;
706
707 if (!SDDS_ParseNamelist((void *)&SDDS_dataset->layout, SDDS_DescriptionFieldInformation, SDDS_DESCRIPTION_FIELDS, s)) {
708 SDDS_SetError("Problem parsing description namelist");
709 return 0;
710 }
711#if DEBUG
712 fprintf(stderr, "Description scanned: description=>%s<, contents = >%s<\n", SDDS_dataset->layout.description, SDDS_dataset->layout.contents);
713#endif
714 return 1;
715}
716
717/**
718 * @brief Processes and defines a column within an SDDS dataset.
719 *
720 * This function parses a column definition string, extracts the necessary
721 * column information, and defines the column in the given SDDS dataset.
722 *
723 * @param SDDS_dataset Pointer to the SDDS dataset where the column will be defined.
724 * @param s String containing the column definition in namelist format.
725 *
726 * @return
727 * - Returns `1` on successful processing and definition of the column.
728 * - Returns `0` if an error occurs during parsing or definition.
729 */
730int32_t SDDS1_ProcessColumnDefinition(SDDS_DATASET *SDDS_dataset, char *s) {
731 COLUMN_DEFINITION colDef;
732 int32_t code;
733
734 colDef.name = colDef.symbol = colDef.units = colDef.description = colDef.format_string = NULL;
735 colDef.type = -1;
736 colDef.field_length = 0;
737
738 if (!SDDS_ParseNamelist((void *)&colDef, SDDS_ColumnFieldInformation, SDDS_COLUMN_FIELDS, s)) {
739 SDDS_SetError("Problem parsing column namelist");
740 return 0;
741 }
742 code = SDDS_DefineColumn(SDDS_dataset, colDef.name, colDef.symbol, colDef.units, colDef.description, colDef.format_string, colDef.type, colDef.field_length);
743 if (colDef.name)
744 free(colDef.name);
745 if (colDef.symbol)
746 free(colDef.symbol);
747 if (colDef.units)
748 free(colDef.units);
749 if (colDef.description)
750 free(colDef.description);
751 if (colDef.format_string)
752 free(colDef.format_string);
753
754 if (code < 0) {
755 SDDS_SetError("Unable to process column definition--call to define column failed (SDDS1_ProcessColumnDefinition)");
756 return (0);
757 }
758 return (1);
759}
760
761/**
762 * @brief Processes and defines a parameter within an SDDS dataset.
763 *
764 * This function parses a parameter definition string, extracts the necessary
765 * parameter information, and defines the parameter in the given SDDS dataset.
766 *
767 * @param SDDS_dataset Pointer to the SDDS dataset where the parameter will be defined.
768 * @param s String containing the parameter definition in namelist format.
769 *
770 * @return
771 * - Returns `1` on successful processing and definition of the parameter.
772 * - Returns `0` if an error occurs during parsing or definition.
773 */
774int32_t SDDS1_ProcessParameterDefinition(SDDS_DATASET *SDDS_dataset, char *s) {
775 PARAMETER_DEFINITION paramDef;
776 int32_t code;
777
778 paramDef.name = paramDef.symbol = paramDef.units = paramDef.description = paramDef.format_string = paramDef.fixed_value = NULL;
779 paramDef.type = -1;
780
781 if (!SDDS_ParseNamelist((void *)&paramDef, SDDS_ParameterFieldInformation, SDDS_PARAMETER_FIELDS, s)) {
782 SDDS_SetError("Problem parsing parameter namelist");
783 return 0;
784 }
785 code = SDDS_DefineParameter(SDDS_dataset, paramDef.name, paramDef.symbol, paramDef.units, paramDef.description, paramDef.format_string, paramDef.type, paramDef.fixed_value);
786 if (paramDef.name)
787 free(paramDef.name);
788 if (paramDef.symbol)
789 free(paramDef.symbol);
790 if (paramDef.units)
791 free(paramDef.units);
792 if (paramDef.description)
793 free(paramDef.description);
794 if (paramDef.format_string)
795 free(paramDef.format_string);
796
797 if (code < 0) {
798 SDDS_SetError("Unable to process parameter definition--call to define parameter failed (SDDS1_ProcessParameterDefinition)");
799 return (0);
800 }
801 return (1);
802}
803
804/**
805 * @brief Processes an include command by opening the specified file.
806 *
807 * This function parses an include command string to extract the filename,
808 * then attempts to open the file for reading. It returns a file pointer
809 * if successful.
810 *
811 * @param SDDS_dataset Pointer to the SDDS dataset (unused in current implementation).
812 * @param s String containing the include command in namelist format.
813 *
814 * @return
815 * - Returns a pointer to the opened `FILE` on success.
816 * - Returns `NULL` if parsing fails or the file cannot be opened.
817 */
818FILE *SDDS1_ProcessIncludeCommand(SDDS_DATASET *SDDS_dataset, char *s) {
819 FILE *fp;
820 char *filename;
821
822 filename = NULL;
823 if (!SDDS_ParseNamelist((void *)&filename, SDDS_IncludeFieldInformation, SDDS_INCLUDE_FIELDS, s)) {
824 SDDS_SetError("Problem parsing include namelist");
825 return 0;
826 }
827 if (!filename || !(fp = fopen(filename, "r"))) {
828 SDDS_SetError("Unable to process include command--invalid/nonexistent file (SDDS1_ProcessIncludeCommand)");
829 return (NULL);
830 }
831 return (fp);
832}
833
834/**
835 * @brief Processes and defines an associate within an SDDS dataset.
836 *
837 * This function parses an associate definition string, extracts the necessary
838 * associate information, and defines the associate in the given SDDS dataset.
839 *
840 * @param SDDS_dataset Pointer to the SDDS dataset where the associate will be defined.
841 * @param s String containing the associate definition in namelist format.
842 *
843 * @return
844 * - Returns `1` on successful processing and definition of the associate.
845 * - Returns `0` if an error occurs during parsing or definition.
846 */
847int32_t SDDS1_ProcessAssociateDefinition(SDDS_DATASET *SDDS_dataset, char *s) {
848 ASSOCIATE_DEFINITION assocDef;
849 int32_t code;
850
851 assocDef.name = assocDef.filename = assocDef.path = assocDef.description = assocDef.contents = NULL;
852 assocDef.sdds = 0;
853 if (!SDDS_ParseNamelist((void *)&assocDef, SDDS_AssociateFieldInformation, SDDS_ASSOCIATE_FIELDS, s)) {
854 SDDS_SetError("Problem parsing associate namelist");
855 return 0;
856 }
857
858 code = SDDS_DefineAssociate(SDDS_dataset, assocDef.name, assocDef.filename, assocDef.path, assocDef.description, assocDef.contents, assocDef.sdds);
859 if (code < 0) {
860 SDDS_SetError("Unable to process associate definition--call to define associate failed (SDDS1_ProcessAssociateDefinition)");
861 return (0);
862 }
863 return (1);
864}
865
866/**
867 * @brief Processes and sets the data mode for an SDDS dataset.
868 *
869 * This function parses a data mode definition string, extracts the necessary
870 * data mode information, and sets the data mode in the given SDDS dataset.
871 *
872 * @param SDDS_dataset Pointer to the SDDS dataset where the data mode will be set.
873 * @param s String containing the data mode definition in namelist format.
874 *
875 * @return
876 * - Returns `1` on successful processing and setting of the data mode.
877 * - Returns `0` if an error occurs during parsing or if mandatory fields are missing.
878 */
879int32_t SDDS1_ProcessDataMode(SDDS_DATASET *SDDS_dataset, char *s) {
880 DATA_MODE *dataMode;
881 dataMode = &(SDDS_dataset->layout.data_mode);
882 dataMode->mode = 0;
883 dataMode->endian = 0;
884 dataMode->lines_per_row = 1;
885 dataMode->no_row_counts = dataMode->additional_header_lines = 0;
886 dataMode->fixed_row_count = 0;
887 dataMode->column_major = 0;
888 if (!SDDS_ParseNamelist((void *)dataMode, SDDS_DataFieldInformation, SDDS_DATA_FIELDS, s)) {
889 SDDS_SetError("Problem parsing data namelist");
890 return 0;
891 }
892 if (dataMode->mode == 0) {
893 SDDS_SetError("Problem with data namelist: mode not given.");
894 return 0;
895 }
896 if (dataMode->mode == SDDS_ASCII && dataMode->lines_per_row < 0) {
897 SDDS_SetError("Unable to process data mode--lines_per_row is invalid (SDDS1_ProcessDataMode)");
898 return (0);
899 }
900 return 1;
901}
902
903/**
904 * @brief Processes and defines an array within an SDDS dataset.
905 *
906 * This function parses an array definition string, extracts the necessary
907 * array information, and defines the array in the given SDDS dataset.
908 *
909 * @param SDDS_dataset Pointer to the SDDS dataset where the array will be defined.
910 * @param s String containing the array definition in namelist format.
911 *
912 * @return
913 * - Returns `1` on successful processing and definition of the array.
914 * - Returns `0` if an error occurs during parsing or definition.
915 */
916int32_t SDDS1_ProcessArrayDefinition(SDDS_DATASET *SDDS_dataset, char *s) {
917 ARRAY_DEFINITION arrayDef;
918 int32_t code;
919
920 arrayDef.name = arrayDef.symbol = arrayDef.units = arrayDef.description = arrayDef.format_string = arrayDef.group_name = NULL;
921 arrayDef.type = -1;
922 arrayDef.field_length = 0;
923 arrayDef.dimensions = 1;
924
925 if (!SDDS_ParseNamelist((void *)&arrayDef, SDDS_ArrayFieldInformation, SDDS_ARRAY_FIELDS, s)) {
926 SDDS_SetError("Problem parsing array namelist");
927 return 0;
928 }
929 code = SDDS_DefineArray(SDDS_dataset, arrayDef.name, arrayDef.symbol, arrayDef.units, arrayDef.description, arrayDef.format_string, arrayDef.type, arrayDef.field_length, arrayDef.dimensions, arrayDef.group_name);
930 if (arrayDef.name)
931 free(arrayDef.name);
932 if (arrayDef.symbol)
933 free(arrayDef.symbol);
934 if (arrayDef.units)
935 free(arrayDef.units);
936 if (arrayDef.description)
937 free(arrayDef.description);
938 if (arrayDef.format_string)
939 free(arrayDef.format_string);
940 if (arrayDef.group_name)
941 free(arrayDef.group_name);
942
943 if (code < 0) {
944 SDDS_SetError("Unable to process array definition--call to define array failed (SDDS1_ProcessArrayDefinition)");
945 return (0);
946 }
947 return (1);
948}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_SaveLayout(SDDS_DATASET *SDDS_dataset)
Definition SDDS_copy.c:615
SDDS_FIELD_INFORMATION SDDS_AssociateFieldInformation[SDDS_ASSOCIATE_FIELDS]
Field information for associate definitions.
Definition SDDS_data.c:225
SDDS_FIELD_INFORMATION SDDS_ArrayFieldInformation[SDDS_ARRAY_FIELDS]
Field information for array definitions.
Definition SDDS_data.c:175
SDDS_FIELD_INFORMATION SDDS_ColumnFieldInformation[SDDS_COLUMN_FIELDS]
Field information for column definitions.
Definition SDDS_data.c:193
SDDS_FIELD_INFORMATION SDDS_DescriptionFieldInformation[SDDS_DESCRIPTION_FIELDS]
Field information for SDDS layout descriptions.
Definition SDDS_data.c:107
SDDS_FIELD_INFORMATION SDDS_ParameterFieldInformation[SDDS_PARAMETER_FIELDS]
Field information for parameter definitions.
Definition SDDS_data.c:209
SDDS_FIELD_INFORMATION SDDS_IncludeFieldInformation[SDDS_INCLUDE_FIELDS]
Field information for include directives.
Definition SDDS_data.c:240
SDDS_FIELD_INFORMATION SDDS_DataFieldInformation[SDDS_DATA_FIELDS]
Field information for data mode settings.
Definition SDDS_data.c:159
int32_t SDDS_IsQuoted(char *string, char *position, char quotation_mark)
Checks if a position in a string is within a quoted section.
Definition SDDS_input.c:217
Internal definitions and function declarations for SDDS with LZMA support.
int32_t SDDS_DefineAssociate(SDDS_DATASET *SDDS_dataset, const char *name, const char *filename, const char *path, const char *description, const char *contents, int32_t sdds)
Defines an associate for the SDDS dataset.
int32_t SDDS_DefineArray(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, int32_t dimensions, const char *group_name)
Defines a data array within the SDDS dataset.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_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_ProcessParameterString(SDDS_DATASET *SDDS_dataset, char *string, int32_t mode)
Process a parameter definition string.
int32_t SDDS1_ProcessArrayDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Processes and defines an array within an SDDS dataset.
int32_t SDDS_ProcessAssociateString(SDDS_DATASET *SDDS_dataset, char *string)
Process an associate definition string.
int32_t SDDS_ProcessArrayDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Process the array definition section of the SDDS dataset.
int32_t SDDS_ProcessParameterDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Process the parameter definition section of the SDDS dataset.
int32_t SDDS_ProcessColumnString(SDDS_DATASET *SDDS_dataset, char *string, int32_t mode)
Process a column definition string.
int32_t SDDS1_ProcessAssociateDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Processes and defines an associate within an SDDS dataset.
int32_t SDDS_ProcessAssociateDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Process the associate definition section of the SDDS dataset.
FILE * SDDS1_ProcessIncludeCommand(SDDS_DATASET *SDDS_dataset, char *s)
Processes an include command by opening the specified file.
int32_t SDDS1_ProcessDataMode(SDDS_DATASET *SDDS_dataset, char *s)
Processes and sets the data mode for an SDDS dataset.
FILE * SDDS_ProcessIncludeCommand(SDDS_DATASET *SDDS_dataset, char *s)
Process the include command within the SDDS dataset.
int32_t SDDS_ProcessDataMode(SDDS_DATASET *SDDS_dataset, char *s)
Process the data mode section of the SDDS dataset.
int32_t SDDS_MatchEnum(char *value, SDDS_ENUM_PAIR *enumPair)
Match an enumeration string to its corresponding value.
char * SDDS_GetTagValuePair(char *ptr, char **tag, char **value)
Retrieve a tag-value pair from the input string.
char * SDDS_PrepareToParseTagValuePairs(char *s)
Prepare the string for parsing tag-value pairs.
int32_t SDDS_ProcessDescription(SDDS_DATASET *SDDS_dataset, char *s)
Process the description section of the SDDS dataset.
int32_t SDDS_FindFieldIndex(char *tag, SDDS_FIELD_INFORMATION *fieldInfo, int32_t fieldInfos)
Find the index of a field based on its tag.
int32_t SDDS1_ProcessDescription(SDDS_DATASET *SDDS_dataset, char *s)
Process the description section for SDDS protocol version 1.
int32_t SDDS1_ProcessParameterDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Processes and defines a parameter within an SDDS dataset.
int32_t SDDS_ParseNamelist(void *data, SDDS_FIELD_INFORMATION *fieldInfo, int32_t fieldInfos, char *s)
Parse a namelist string and populate the corresponding data structure.
int32_t SDDS_ProcessArrayString(SDDS_DATASET *SDDS_dataset, char *string)
Process an array definition string.
int32_t SDDS_ProcessColumnDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Process the column definition section of the SDDS dataset.
int32_t SDDS1_ProcessColumnDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Processes and defines a column within an SDDS dataset.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
int32_t SDDS_CheckDataset(SDDS_DATASET *SDDS_dataset, const char *caller)
Validates the SDDS dataset pointer.
Definition SDDS_utils.c:552
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
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
Definition SDDStypes.h:67
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
Definition SDDStypes.h:31
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49