SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
SDDSUtil.cc
Go to the documentation of this file.
1/**
2 * @file SDDSUtil.cc
3 * @brief Archived utility functions for the original SDDS3 implementation.
4 *
5 * @details Contains legacy byte-order, type, string, buffering, and numeric
6 * conversion helpers used by the archived SDDS3 classes.
7 *
8 * @note This source is retained for migration reference and is not compiled
9 * into libSDDSpp.
10 *
11 * @copyright
12 * - (c) The University of Chicago
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
19#include <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22#include <stdarg.h>
23#include <ctype.h>
24#include "SDDS3.h"
25
26/*
27 * isBigEndianMachine returns true on big endian operating systems like Solaris
28 * and false on little endian operating systems like linux and windows.
29 *
30 */
31int32_t SDDS_isBigEndianMachine() {
32 int32_t x = 1;
33 if ( *((char*)&x) )
34 return false;
35 return true;
36}
37
38int32_t SDDS_identifyType(char* typeName) {
39 int32_t i;
40 const char *SDDS_type_name_old[SDDS_NUM_TYPES] = {
41 "double", "float", "long", "ulong", "short", "ushort", "string", "character"
42 };
43 const char *SDDS_type_name[SDDS_NUM_TYPES] = {
44 "real64", "real32", "int32", "uint32", "int16", "uint16", "string", "character"
45 };
46 for (i=0; i<SDDS_NUM_TYPES; i++) {
47 if (strcasecmp(typeName, SDDS_type_name[i]) == 0)
48 return i+1;
49 if (strcasecmp(typeName, SDDS_type_name_old[i]) == 0)
50 return i+1;
51 }
52 return 0;
53}
54
55int32_t SDDS_verifyPrintfFormat(char *string, int32_t type) {
56 char *percent, *s;
57 int32_t len, tmp;
58
59 s = string;
60 do {
61 if ((percent = strchr(s, '%'))) {
62 if (*(percent+1)!='%')
63 break;
64 s = percent+1;
65 }
66 } while (percent);
67 if (!percent || !*++percent)
68 return(0);
69
70 string = percent;
71 switch (type) {
72 case SDDS_DOUBLE:
73 case SDDS_FLOAT:
74 if ((len = strcspn(string, "fegEG"))==strlen(string))
75 return(0);
76 if (len==0)
77 return(1);
78 if ((tmp=strspn(string, "-+.0123456789 "))<len)
79 return(0);
80 break;
81 case SDDS_LONG:
82 if ((len = strcspn(string, "d"))==strlen(string))
83 return(0);
84 if (*(string+len-1)!='l')
85 return(0);
86 if (--len==0)
87 return(1);
88 if ((tmp=strspn(string, "-+.0123456789 "))<len)
89 return(0);
90 break;
91 case SDDS_ULONG:
92 if ((len = strcspn(string, "u"))==strlen(string))
93 return(0);
94 if (*(string+len-1)!='l')
95 return(0);
96 if (--len==0)
97 return(1);
98 if ((tmp=strspn(string, "-+.0123456789 "))<len)
99 return(0);
100 break;
101 case SDDS_SHORT:
102 if ((len = strcspn(string, "d"))==strlen(string))
103 return(0);
104 if (*(string+len-1)!='h')
105 return(0);
106 if (--len==0)
107 return(1);
108 if ((tmp=strspn(string, "-+.0123456789 "))<len)
109 return(0);
110 break;
111 case SDDS_USHORT:
112 if ((len = strcspn(string, "u"))==strlen(string))
113 return(0);
114 if (*(string+len-1)!='h')
115 return(0);
116 if (--len==0)
117 return(1);
118 if ((tmp=strspn(string, "-+.0123456789 "))<len)
119 return(0);
120 break;
121 case SDDS_STRING:
122 if ((len = strcspn(string, "s"))==strlen(string))
123 return(0);
124 if (len==0)
125 return(1);
126 if ((tmp=strspn(string, "-0123456789"))<len)
127 return(0);
128 break;
129 case SDDS_CHARACTER:
130 if ((len = strcspn(string, "c"))==strlen(string))
131 return(0);
132 if (len!=0)
133 return(0);
134 break;
135 default:
136 return(0);
137 }
138 /* no errors found--its probably okay */
139 return(1);
140}
141
142int32_t SDDS_isValidType(int32_t type) {
143 if ((type >= 1) && (type <= SDDS_NUM_TYPES)) {
144 return 1;
145 }
146 return 0;
147}
148
149static uint32_t nameValidityFlags = 0;
150void SDDS_setNameValidityFlags(uint32_t flags) {
151 nameValidityFlags = flags;
152}
153
154int32_t SDDS_isValidName(char *name) {
155 char *ptr;
156 int32_t isValid = 1;
157 char *validChars = (char*)"@:#+%-._$&/[]";
158 char *startChars = (char*)".:";
159
160 if (nameValidityFlags&SDDS_ALLOW_ANY_NAME) {
161 return(1);
162 }
163 ptr = name;
164 if (strlen(name)==0) {
165 isValid = 0;
166 } else if (!(nameValidityFlags&SDDS_ALLOW_V15_NAME)) {
167 /* post V1.5 allows only alpha and startChars members as first character */
168 /* V1.5 allows alpha, digits, and any validChars members */
169 if (!(isalpha(*ptr) || strchr(startChars, *ptr))) {
170 isValid = 0;
171 }
172 }
173 while (isValid && *ptr) {
174 if (!(isalnum(*ptr) || strchr(validChars, *ptr))) {
175 isValid = 0;
176 }
177 ptr++;
178 }
179 if (!isValid) {
180 return(0);
181 }
182 return(1);
183}
184
185int32_t SDDS_fileIsLocked(char *filename) {
186#if defined(F_TEST)
187 FILE *fp;
188 if (!(fp = fopen(filename, "rb")))
189 return 0;
190 if (lockf(fileno(fp), F_TEST, 0)==-1) {
191 fclose(fp);
192 return 1;
193 }
194 fclose(fp);
195 return 0;
196#else
197 return 0;
198#endif
199}
200
201int32_t SDDS_lockFile(FILE *fp, char *filename, char *caller) {
202#if defined(F_TEST)
203 if (lockf(fileno(fp), F_TEST, 0)==-1) {
204 fprintf(stderr, "Unable to access file %s--file is locked (%s)", filename, caller);
205 return 0;
206 }
207 if (lockf(fileno(fp), F_TLOCK, 0)==-1) {
208 fprintf(stderr, "Unable to establish lock on file %s (%s)", filename, caller);
209 return 0;
210 }
211 return 1;
212#else
213 return 1;
214#endif
215}
216
217void *SDDS_calloc(size_t nelem, size_t elem_size) {
218 if (elem_size<=0)
219 elem_size = 4;
220 if (nelem<=0)
221 nelem = 1;
222 return(calloc(nelem, elem_size));
223}
224
225void *SDDS_malloc(size_t size) {
226 if (size<=0)
227 size = 4;
228 return(malloc(size));
229}
230
231void SDDS_free(void *mem) {
232 /* this is required so the free will be consistent with the malloc.
233 On WIN32 the release (optimized) version of malloc is different
234 from the debug (unoptimized) version, so debug programs freeing
235 memory that was allocated by release, library routines encounter
236 problems. */
237 free(mem);
238}
239
240/***************************
241 SDDS_printNamelistField
242
243 C++ Arguments: char **string, int32_t strings
244
245 Results: 0 on success
246 1 on failure
247 ***************************/
248int32_t SDDS_freeStringArray(char **string, int32_t strings) {
249 int32_t i;
250 if (!string) {
251 return(1);
252 }
253 for (i=0; i<strings; i++) {
254 if (string[i]) {
255 free(string[i]);
256 string[i] = NULL;
257 }
258 }
259 return(0);
260}
261
262void *SDDS_realloc(void *old_ptr, size_t new_size) {
263 /* this is required because some realloc's don't behave properly when asked to return a
264 * pointer to 0 memory. They return NULL.
265 */
266 if (new_size<=0)
267 new_size = 4;
268 /* this is required because some realloc's don't behave properly when given a NULL pointer */
269 if (!old_ptr)
270 return(SDDS_malloc(new_size));
271 else
272 return(realloc(old_ptr, new_size));
273}
274
275/***********************************************************************************************
276 * SDDS_printNamelistField *
277 * *
278 * C++ Arguments: FILE *fp, char *name, char *value *
279 * voidp *gzfp, char *name, char *value *
280 * *
281 * Results: 0 on success *
282 * 1 on failure *
283 ***********************************************************************************************/
284int32_t SDDS_printNamelistField(FILE *fp, char *name, char *value) {
285 char c;
286 char *s;
287 int32_t hasWhitespace;
288 if (!name) {
289 return(1);
290 }
291 if (!value || !strlen(name)) {
292 return(0);
293 }
294 if (!strlen(value)) {
295 fprintf(fp, "%s=\"\", ", name);
296 } else {
297 fprintf(fp, "%s=", name);
298 s = value;
299 hasWhitespace=0;
300 if (SDDS_hasWhitespace(s) || SDDS_stringIsBlank(s) || (strpbrk(s, " ,*$\t\n\b"))) {
301 fputc('"', fp);
302 hasWhitespace = 1;
303 }
304 while (s && *s) {
305 c = *s++;
306 if (c=='!') {
307 fputs("\\!", fp);
308 } else if (c=='\\') {
309 fputs("\\\\", fp);
310 } else if (c=='"') {
311 fputs("\\\"", fp);
312 } else if (c==' ') {
313 fputc(' ', fp); /* don't escape plain spaces */
314 } else if (isspace(c) || !isprint(c)) {
315 fprintf(fp, "\\%03o", c);
316 } else {
317 fputc(c, fp);
318 }
319 }
320 if (hasWhitespace) {
321 fputc('"', fp);
322 }
323 fputs(", ", fp);
324 }
325 return(0);
326}
327
328int32_t SDDS_printNamelistField(voidp *gzfp, char *name, char *value) {
329 char c;
330 char *s;
331 int32_t hasWhitespace;
332 if (!name) {
333 return(1);
334 }
335 if (!value || !strlen(name)) {
336 return(0);
337 }
338 if (!strlen(value)) {
339 gzprintf(gzfp, "%s=\"\", ", name);
340 } else {
341 gzprintf(gzfp, "%s=", name);
342 s = value;
343 hasWhitespace=0;
344 if (SDDS_hasWhitespace(s) || SDDS_stringIsBlank(s) || (strpbrk(s, " ,*$\t\n\b"))) {
345 gzputc(gzfp, '"');
346 hasWhitespace = 1;
347 }
348 while (s && *s) {
349 c = *s++;
350 if (c=='!') {
351 gzputs(gzfp, "\\!");
352 } else if (c=='\\') {
353 gzputs(gzfp, "\\\\");
354 } else if (c=='"') {
355 gzputs(gzfp, "\\\"");
356 } else if (c==' ') {
357 gzputc(gzfp, ' '); /* don't escape plain spaces */
358 } else if (isspace(c) || !isprint(c)) {
359 gzprintf(gzfp, "\\%03o", c);
360 } else {
361 gzputc(gzfp, c);
362 }
363 }
364 if (hasWhitespace) {
365 gzputc(gzfp, '"');
366 }
367 gzputs(gzfp, ", ");
368 }
369 return(0);
370}
371
372/***********************************************************************************************
373 * SDDS_blankToNull *
374 * *
375 * C++ Arguments: char *string *
376 * *
377 * Results: string if not blank or NULL *
378 * NULL if string is blank or NULL *
379 ***********************************************************************************************/
380char *SDDS_blankToNull(char *string) {
381 if (!string || SDDS_stringIsBlank(string)) {
382 return(NULL);
383 }
384 return(string);
385}
386
387/***********************************************************************************************
388 * SDDS_stringIsBlank *
389 * *
390 * C++ Arguments: char *string *
391 * *
392 * Results: 1 if string is blank *
393 * 0 if string is NULL or not blank *
394 ***********************************************************************************************/
395int32_t SDDS_stringIsBlank(char *string) {
396 if (!string) {
397 return(1);
398 }
399 while (*string) {
400 if (!isspace(*string++)) {
401 return(0);
402 }
403 }
404 return(1);
405}
406
407/***********************************************************************************************
408 * SDDS_getTypeName *
409 * *
410 * C++ Arguments: int32_t type *
411 * *
412 * Results: parameter type in string form on success *
413 * NULL on failure *
414 ***********************************************************************************************/
415char* SDDS_getTypeName(int32_t type) {
416 const char *SDDS_type_name[SDDS_NUM_TYPES] = {
417 "real64", "real32", "int32", "uint32", "int16", "uint16", "string", "character"
418 };
419 if ((type < 1) || (type > SDDS_NUM_TYPES)) {
420 return(NULL);
421 }
422 return((char*)(SDDS_type_name[type - 1]));
423}
424
425/***********************************************************************************************
426 * SDDS_getVer1TypeName *
427 * *
428 * C++ Arguments: int32_t type *
429 * *
430 * Results: parameter type in string form on success *
431 * NULL on failure *
432 ***********************************************************************************************/
433char* SDDS_getVer1TypeName(int32_t type) {
434 const char *SDDS_type_name[SDDS_NUM_TYPES] = {
435 "double", "float", "long", "ulong", "short", "ushort", "string", "character"
436 };
437 if ((type < 1) || (type > SDDS_NUM_TYPES)) {
438 return(NULL);
439 }
440 return((char*)(SDDS_type_name[type - 1]));
441}
442
443/***********************************************************************************************
444 * SDDS_getVer2TypeName *
445 * *
446 * C++ Arguments: int32_t type *
447 * *
448 * Results: parameter type in string form on success *
449 * NULL on failure *
450 ***********************************************************************************************/
451char* SDDS_getVer2TypeName(int32_t type) {
452 const char *SDDS_type_name[SDDS_NUM_TYPES] = {
453 "double", "float", "long", "ulong", "short", "ushort", "string", "character"
454 };
455 if ((type < 1) || (type > SDDS_NUM_TYPES)) {
456 return(NULL);
457 }
458 return((char*)(SDDS_type_name[type - 1]));
459}
460
461/***********************************************************************************************
462 * SDDS_hasWhitespace *
463 * *
464 * C++ Arguments: char *string *
465 * *
466 * Results: 1 if string has whitespace *
467 * 0 if string is NULL or does not have white space *
468 ***********************************************************************************************/
469int32_t SDDS_hasWhitespace(char *string) {
470 if (!string) {
471 return(0);
472 }
473 while (*string) {
474 if (isspace(*string)) {
475 return(1);
476 }
477 string++;
478 }
479 return(0);
480}
481
482/***********************************************************************************************
483 * SDDS_getNamelist *
484 * *
485 * C++ Arguments: char *buffer, int32_t buflen, FILE *fp *
486 * char *buffer, int32_t buflen, voidp *gzfp *
487 * *
488 * Results: 1 if namelist found *
489 * 0 if namelist not found *
490 ***********************************************************************************************/
491int32_t SDDS_getNamelist(char *buffer, int32_t buflen, FILE *fp) {
492 char *ptr, *flag, *buffer0;
493 int32_t n;
494
495 while ((flag=SDDS_fgetsSkipComments(buffer, buflen, fp, '!'))) {
496 if ((ptr=strchr(buffer, '&')) && !SDDS_isQuoted(buffer, ptr, '"')) {
497 break;
498 }
499 }
500 if (!flag) {
501 return(0);
502 }
503 n = strlen(buffer)-1;
504 if (buffer[n]=='\n') {
505 buffer[n] = ' ';
506 if ((n-1 >= 0) && (buffer[n-1]=='\r')) {
507 buffer[n-1] = ' ';
508 }
509 }
510
511 /* check for the beginning of a namelist (an unquoted &) */
512 ptr = buffer;
513 while (*ptr) {
514 if (*ptr=='"') {
515 /* skip quoted section */
516 ptr++;
517 while (*ptr!='"' && *ptr) {
518 ptr++;
519 }
520 if (*ptr) {
521 ptr++;
522 }
523 continue;
524 }
525 if (*ptr=='&') {
526 if (strncmp(ptr, "&end", 4)==0) {
527 return(0);
528 }
529 break;
530 }
531 ptr++;
532 }
533 if (!*ptr) {
534 return(0);
535 }
536
537 /* remove the trailing &end if there is one */
538 if ((n=strlen(buffer))>=4) {
539 ptr = buffer+n-4;
540 while (1) {
541 if (*ptr=='&' &&
542 (ptr==buffer || *(ptr-1)!='\\') &&
543 strncmp(ptr, "&end", 4)==0 &&
544 !SDDS_isQuoted(buffer, ptr, '"')) {
545 *ptr = 0;
546 return(1);
547 }
548 if (ptr==buffer) {
549 break;
550 }
551 ptr--;
552 }
553 }
554
555 /* read in the remainder of the namelist */
556 buffer0 = buffer;
557 buflen -= strlen(buffer);
558 buffer += strlen(buffer);
559 while ((flag=SDDS_fgetsSkipComments(buffer, buflen, fp, '!'))) {
560 n = strlen(buffer)-1;
561 if (buffer[n]=='\n') {
562 buffer[n] = ' ';
563 if ((n-1 >= 0) && (buffer[n-1]=='\r')) {
564 buffer[n-1] = ' ';
565 }
566 }
567 if ((ptr=strstr(buffer, "&end")) && !SDDS_isQuoted(buffer0, ptr, '"')) {
568 return(1);
569 }
570 buflen -= strlen(buffer);
571 buffer += strlen(buffer);
572 if (buflen==0) {
573 return(0);
574 }
575 }
576 return(0);
577}
578
579int32_t SDDS_getNamelist(char *buffer, int32_t buflen, voidp *gzfp) {
580 char *ptr, *flag, *buffer0;
581 int32_t n;
582
583 while ((flag=SDDS_fgetsSkipComments(buffer, buflen, gzfp, '!'))) {
584 if ((ptr=strchr(buffer, '&')) && !SDDS_isQuoted(buffer, ptr, '"')) {
585 break;
586 }
587 }
588 if (!flag) {
589 return(0);
590 }
591 n = strlen(buffer)-1;
592 if (buffer[n]=='\n') {
593 buffer[n] = ' ';
594 if ((n-1 >= 0) && (buffer[n-1]=='\r')) {
595 buffer[n-1] = ' ';
596 }
597 }
598
599 /* check for the beginning of a namelist (an unquoted &) */
600 ptr = buffer;
601 while (*ptr) {
602 if (*ptr=='"') {
603 /* skip quoted section */
604 ptr++;
605 while (*ptr!='"' && *ptr) {
606 ptr++;
607 }
608 if (*ptr) {
609 ptr++;
610 }
611 continue;
612 }
613 if (*ptr=='&') {
614 if (strncmp(ptr, "&end", 4)==0) {
615 return(0);
616 }
617 break;
618 }
619 ptr++;
620 }
621 if (!*ptr) {
622 return(0);
623 }
624
625 /* remove the trailing &end if there is one */
626 if ((n=strlen(buffer))>=4) {
627 ptr = buffer+n-4;
628 while (1) {
629 if (*ptr=='&' &&
630 (ptr==buffer || *(ptr-1)!='\\') &&
631 strncmp(ptr, "&end", 4)==0 &&
632 !SDDS_isQuoted(buffer, ptr, '"')) {
633 *ptr = 0;
634 return(1);
635 }
636 if (ptr==buffer) {
637 break;
638 }
639 ptr--;
640 }
641 }
642
643 /* read in the remainder of the namelist */
644 buffer0 = buffer;
645 buflen -= strlen(buffer);
646 buffer += strlen(buffer);
647 while ((flag=SDDS_fgetsSkipComments(buffer, buflen, gzfp, '!'))) {
648 n = strlen(buffer)-1;
649 if (buffer[n]=='\n') {
650 buffer[n] = ' ';
651 if ((n-1 >= 0) && (buffer[n-1]=='\r')) {
652 buffer[n-1] = ' ';
653 }
654 }
655 if ((ptr=strstr(buffer, "&end")) && !SDDS_isQuoted(buffer0, ptr, '"')) {
656 return(1);
657 }
658 buflen -= strlen(buffer);
659 buffer += strlen(buffer);
660 if (buflen==0) {
661 return(0);
662 }
663 }
664 return(0);
665}
666
667char *SDDS_fgetsSkipComments(char *s, int32_t slen, FILE *fp,
668 char skip_char /* ignore lines that begin with this character */
669 ) {
670 while (fgets(s, slen, fp)) {
671 if (s[0]!=skip_char) {
672 SDDS_cutOutComments(s, skip_char);
673 return(s);
674 } else if (s[1]=='#') {
675 SDDS_parseSpecialComments(s+2);
676 }
677 }
678 return(NULL);
679}
680
681char *SDDS_fgetsSkipComments(char *s, int32_t slen, voidp *gzfp,
682 char skip_char /* ignore lines that begin with this character */
683 ) {
684 while (gzgets(gzfp, s, slen)) {
685 if (s[0]!=skip_char) {
686 SDDS_cutOutComments(s, skip_char);
687 return(s);
688 } else if (s[1]=='#') {
689 SDDS_parseSpecialComments(s+2);
690 }
691 }
692 return(NULL);
693}
694
695char *SDDS_fgetsSkipCommentsResize(char **s, int32_t *slen, FILE *fp,
696 char skip_char /* ignore lines that begin with this character */
697 ) {
698 int32_t spaceLeft, length, newLine;
699 char *sInsert, *fgetsReturn;
700
701 sInsert = *s;
702 spaceLeft = *slen;
703 newLine = 1;
704 while ((fgetsReturn=fgets(sInsert, spaceLeft, fp))) {
705 if (newLine && sInsert[0]=='!') {
706 continue;
707 }
708 SDDS_cutOutComments(sInsert, skip_char);
709 length = strlen(sInsert);
710 if (sInsert[length-1]!='\n' && !feof(fp)) {
711 /* buffer wasn't long enough to get the whole line. Resize and add more data. */
712 spaceLeft = *slen;
713 *slen = *slen*2;
714 *s = (char*)SDDS_realloc(*s, sizeof(**s)**slen);
715 sInsert = *s + strlen(*s);
716 newLine = 0;
717 } else {
718 break;
719 }
720 }
721 if (!fgetsReturn) {
722 return(NULL);
723 }
724 return(*s);
725}
726
727char *SDDS_fgetsSkipCommentsResize(char **s, int32_t *slen, voidp *gzfp,
728 char skip_char /* ignore lines that begin with this character */
729 ) {
730 int32_t spaceLeft, length, newLine;
731 char *sInsert, *fgetsReturn;
732
733 sInsert = *s;
734 spaceLeft = *slen;
735 newLine = 1;
736 while ((fgetsReturn=gzgets(gzfp, sInsert, spaceLeft))) {
737 if (newLine && sInsert[0]=='!') {
738 continue;
739 }
740 SDDS_cutOutComments(sInsert, skip_char);
741 length = strlen(sInsert);
742 if (sInsert[length-1]!='\n' && !gzeof(gzfp)) {
743 /* buffer wasn't long enough to get the whole line. Resize and add more data. */
744 spaceLeft = *slen;
745 *slen = *slen*2;
746 *s = (char*)SDDS_realloc(*s, sizeof(**s)**slen);
747 sInsert = *s + strlen(*s);
748 newLine = 0;
749 } else {
750 break;
751 }
752 }
753 if (!fgetsReturn) {
754 return(NULL);
755 }
756 return(*s);
757}
758
759void SDDS_cutOutComments(char *s, char cc) {
760 int32_t length, hasNewline;
761 char *s0;
762
763 if (!cc || !s) {
764 return;
765 }
766
767 hasNewline = 0;
768 length = strlen(s);
769 if (s[length-1]=='\n') {
770 hasNewline = 1;
771 }
772
773 if (*s==cc) {
774 /* check for special information */
775 if (*(s+1)=='#') {
776 SDDS_parseSpecialComments(s+2);
777 }
778 *s = 0;
779 return;
780 }
781 s0 = s;
782 while (*s) {
783 if (*s=='"') {
784 while (*++s && *s!='"')
785 ;
786 if (!*s) {
787 return;
788 }
789 s++;
790 continue;
791 }
792 if (*s==cc) {
793 if (s!=s0 && *(s-1)=='\\') {
794 strcpy(s-1, s);
795 } else {
796 if (hasNewline) {
797 *s = '\n';
798 *(s+1) = 0;
799 } else {
800 *s = 0;
801 }
802 return;
803 }
804 }
805 s++;
806 }
807}
808
809#define COMMENT_COMMANDS 3
810static const char *commentCommandName[COMMENT_COMMANDS] = {
811 "big-endian", "little-endian",
812 "fixed-rowcount",
813};
814#define SDDS_BIGENDIAN_SEEN 0x0001UL
815#define SDDS_LITTLEENDIAN_SEEN 0x0002UL
816#define SDDS_FIXED_ROWCOUNT_SEEN 0x0004UL
817static uint32_t commentCommandFlag[COMMENT_COMMANDS] = {
818 SDDS_BIGENDIAN_SEEN, SDDS_LITTLEENDIAN_SEEN,
819 SDDS_FIXED_ROWCOUNT_SEEN,
820};
821static uint32_t commentFlags = 0;
822
823uint32_t SDDS_getSpecialCommentsModes() {
824 return commentFlags;
825}
826
827void SDDS_resetSpecialCommentsModes() {
828 commentFlags = 0;
829}
830
831void SDDS_parseSpecialComments(char *s) {
832 char buffer[SDDS_MAXLINE];
833 int32_t size;
834 int32_t i;
835 size = strlen(s);
836
837 while (SDDS_getToken(&s, &size, buffer, SDDS_MAXLINE)>0) {
838 for (i=0; i<COMMENT_COMMANDS; i++) {
839 if (strcmp(buffer, commentCommandName[i])==0) {
840 commentFlags |= commentCommandFlag[i];
841 break;
842 }
843 }
844 }
845}
846
847int32_t SDDS_getToken(char **st, int32_t *strlength, char *buffer, int32_t buflen) {
848 char *ptr0, *ptr1, *escptr, *s;
849
850 s = *st;
851
852 /* save the pointer to the head of the string */
853 ptr0 = s;
854
855 /* skip leading white-space */
856 while (isspace(*s)) {
857 s++;
858 }
859 if (*s==0) {
860 return(-1);
861 }
862 ptr1 = s;
863
864 if (*s=='"') {
865 /* if quoted string, skip to next quotation mark */
866 ptr1 = s+1; /* beginning of actual token */
867 do {
868 s++;
869 escptr = NULL;
870 if (*s=='\\' && *(s+1)=='\\') {
871 /* skip and remember literal \ (indicated by \\ in the string) */
872 escptr = s+1;
873 s += 2;
874 }
875 } while (*s && (*s!='"' || (*(s-1)=='\\' && (s-1)!=escptr)));
876 /* replace trailing quotation mark with a space */
877 if (*s=='"') {
878 *s = ' ';
879 }
880 } else {
881 /* skip to first white-space following token */
882 do {
883 s++;
884 /* imbedded quotation marks are handled here */
885 if (*s=='"' && *(s-1)!='\\') {
886 while (*++s && !(*s=='"' && *(s-1)!='\\'))
887 ;
888 }
889 } while (*s && !isspace(*s));
890 }
891
892 if ((int32_t)(s-ptr1)>=buflen) {
893 return(-1);
894 }
895 strncpy(buffer, ptr1, s-ptr1);
896 buffer[s-ptr1]=0;
897
898 /* update the original string to delete the token */
899 *st += s-ptr0;
900 *strlength -= s-ptr0;
901
902 /* return the string length including whitespace */
903 return((int32_t)(s-ptr1));
904}
905
906int32_t SDDS_isQuoted(char *string, char *position, char quotation_mark) {
907 int32_t in_quoted_section;
908 char *string0;
909
910 if (*position==quotation_mark) {
911 return(1);
912 }
913
914 in_quoted_section = 0;
915 string0 = string;
916 while (*string) {
917 if (*string==quotation_mark && (string==string0 || *(string-1)!='\\')) {
918 in_quoted_section = !in_quoted_section;
919 } else if (string==position) {
920 return(in_quoted_section);
921 }
922 string++;
923 }
924 return(0);
925}
926
927char *SDDS_prepareToParseTagValuePairs(char *s) {
928 char *ptr;
929 int32_t length;
930
931 /* remove the trailing &end if there is one */
932 if ((length=strlen(s))>=4) {
933 ptr = s+length-4;
934 while (1) {
935 if (*ptr=='&' && (ptr==s || *(ptr-1)!='\\') && strncmp(ptr, "&end", 4)==0
936 && !SDDS_isQuoted(s, ptr, '"')) {
937 *ptr = 0;
938 break;
939 }
940 if (ptr==s) {
941 break;
942 }
943 ptr--;
944 }
945 }
946
947 /* make sure there is no group name */
948 while (*s==' ') {
949 s++;
950 }
951 if (*s=='&') {
952 while (*s && *s!=' ') {
953 s++;
954 }
955 }
956 return(s);
957}
958
959/******************************************
960 SDDS_copyString
961
962 C++ Arguments: char **target, char *source
963
964 Results: 0 on success
965 1 on failure
966*******************************************/
967int32_t SDDS_copyString(char **target, char *source) {
968 if (!source) {
969 *target = NULL;
970 } else {
971 if (!(*target=(char*)SDDS_malloc(sizeof(**target)*(strlen(source)+1)))) {
972 return(1);
973 }
974 strcpy(*target, source);
975 }
976 return(0);
977}
978
979/* \ddd = octal value
980 * ANSI escape codes (n t b r f v \ ' " a ?
981 * SDDS escape codes (! )
982 */
983void SDDS_interpretEscapes(char *s) {
984 char *ptr;
985 int32_t count;
986
987 ptr = s;
988 while (*s) {
989 if (*s!='\\')
990 *ptr++ = *s++;
991 else {
992 s++;
993 if (!*s) {
994 *ptr++ = '\\';
995 *ptr++ = 0;
996 return;
997 }
998 switch (*s) {
999 case 'n':
1000 *ptr++ = '\n';
1001 s++;
1002 break;
1003 case 't':
1004 *ptr++ = '\t';
1005 s++;
1006 break;
1007 case 'b':
1008 *ptr++ = '\b';
1009 s++;
1010 break;
1011 case 'r':
1012 *ptr++ = '\r';
1013 s++;
1014 break;
1015 case 'f':
1016 *ptr++ = '\f';
1017 s++;
1018 break;
1019 case 'v':
1020 *ptr++ = '\v';
1021 s++;
1022 break;
1023 case '\\':
1024 *ptr++ = '\\';
1025 s++;
1026 break;
1027 case '\'':
1028 *ptr++ = '\'';
1029 s++;
1030 break;
1031 case '"':
1032 *ptr++ = '\"';
1033 s++;
1034 break;
1035 case 'a':
1036 *ptr++ = '\a';
1037 s++;
1038 break;
1039 case '?':
1040 *ptr++ = '\?';
1041 s++;
1042 break;
1043 case '!':
1044 *ptr++ = '!';
1045 s++;
1046 break;
1047 default:
1048 if (*s>='0' && *s<='9') {
1049 *ptr = 0;
1050 count = 0;
1051 while (++count<=3 && *s>='0' && *s<='9')
1052 *ptr = 8*(*ptr) + *s++ - '0';
1053 ptr++;
1054 }
1055 else {
1056 *ptr++ = '\\';
1057 }
1058 break;
1059 }
1060 }
1061 }
1062 *ptr = 0;
1063}
1064
1065/******************************************
1066 SDDS_bufferedRead
1067
1068 C++ Arguments: void *target, size_t targetSize, FILE *fp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1069 void *target, size_t targetSize, voidp *gzfp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1070
1071 Results: 0 on success
1072 1 on failure
1073*******************************************/
1074int32_t SDDS_bufferedRead(void *target, size_t targetSize, FILE *fp,
1075 SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1076 if (!fBuffer->bufferSize) {
1077 /* just read into users buffer or seek if no buffer given */
1078 if (!target) {
1079 return(fseek(fp, targetSize, SEEK_CUR));
1080 } else {
1081 return(fread(target, 1, targetSize, fp)!=targetSize);
1082 }
1083 }
1084 if ((fBuffer->bytesLeft-=targetSize)>=0) {
1085 /* sufficient data is already in the buffer */
1086 if (target) {
1087 memcpy((char*)target, (char*)fBuffer->data, targetSize);
1088 }
1089 fBuffer->data += targetSize;
1090 return(0);
1091 } else {
1092 /* need to read additional data into buffer */
1093 int32_t bytesNeeded, offset;
1094 fBuffer->bytesLeft += targetSize; /* adds back amount subtracted above */
1095 /* first, use the data that is already available. this cleans out the buffer */
1096 if ((offset=fBuffer->bytesLeft)) {
1097 /* some data is available in the buffer */
1098 if (target) {
1099 memcpy((char*)target, (char*)fBuffer->data, offset);
1100 }
1101 bytesNeeded = targetSize - offset;
1102 fBuffer->bytesLeft = 0;
1103 } else {
1104 bytesNeeded = targetSize;
1105 }
1106 fBuffer->data = fBuffer->buffer;
1107 if (fBuffer->bufferSize < bytesNeeded) {
1108 /* just read what is needed directly into user's memory or seek */
1109 if (!target) {
1110 return(fseek(fp, bytesNeeded, SEEK_CUR));
1111 } else {
1112 return(fread((char*)target+offset, 1, bytesNeeded, fp)!=bytesNeeded);
1113 }
1114 }
1115 /* fill the buffer */
1116 if ((fBuffer->bytesLeft = fread(fBuffer->data, 1, fBuffer->bufferSize, fp))<bytesNeeded) {
1117 return(1);
1118 }
1119 if (target) {
1120 memcpy((char*)target+offset, (char*)fBuffer->data, bytesNeeded);
1121 }
1122 fBuffer->data += bytesNeeded;
1123 fBuffer->bytesLeft -= bytesNeeded;
1124 return(0);
1125 }
1126}
1127
1128int32_t SDDS_bufferedRead(void *target, size_t targetSize, voidp *gzfp,
1129 SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1130 if (!fBuffer->bufferSize) {
1131 ((SDDSFile*)sddsfile)->setError((char*)"You must presently have a nonzero file buffer to use zLib (reading/writing .gz files");
1132 return(1);
1133 }
1134 if ((fBuffer->bytesLeft-=targetSize)>=0) {
1135 /* sufficient data is already in the buffer */
1136 if (target) {
1137 memcpy((char*)target, (char*)fBuffer->data, targetSize);
1138 }
1139 fBuffer->data += targetSize;
1140 return(0);
1141 } else {
1142 /* need to read additional data into buffer */
1143 int32_t bytesNeeded, offset;
1144 fBuffer->bytesLeft += targetSize; /* adds back amount subtracted above */
1145 /* first, use the data that is already available. this cleans out the buffer */
1146 if ((offset=fBuffer->bytesLeft)) {
1147 /* some data is available in the buffer */
1148 if (target) {
1149 memcpy((char*)target, (char*)fBuffer->data, offset);
1150 }
1151 bytesNeeded = targetSize - offset;
1152 fBuffer->bytesLeft = 0;
1153 } else {
1154 bytesNeeded = targetSize;
1155 }
1156 fBuffer->data = fBuffer->buffer;
1157 if (fBuffer->bufferSize < bytesNeeded) {
1158 /* just read what is needed directly into user's memory or seek */
1159 if (!target) {
1160 return(gzseek(gzfp, targetSize, SEEK_CUR));
1161 } else {
1162 return(gzread(gzfp, (char*)target, targetSize)!=targetSize);
1163 }
1164 }
1165 /* fill the buffer */
1166 if ((fBuffer->bytesLeft = gzread(gzfp, fBuffer->data, fBuffer->bufferSize))<bytesNeeded) {
1167 return(1);
1168 }
1169 if (target) {
1170 memcpy((char*)target+offset, (char*)fBuffer->data, bytesNeeded);
1171 }
1172 fBuffer->data += bytesNeeded;
1173 fBuffer->bytesLeft -= bytesNeeded;
1174 return(0);
1175 }
1176}
1177
1178/******************************************
1179 SDDS_bufferedWrite
1180
1181 C++ Arguments: void *target, size_t targetSize, FILE *fp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1182 void *target, size_t targetSize, voidp *gzfp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1183
1184 Results: 0 on success
1185 1 on failure
1186*******************************************/
1187int32_t SDDS_bufferedWrite(void *target, size_t targetSize, FILE *fp,
1188 SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1189 if (!fBuffer->bufferSize) {
1190 return(fwrite(target, 1, targetSize, fp)!=targetSize);
1191 }
1192 if ((fBuffer->bytesLeft-=targetSize)>=0) {
1193 memcpy((char*)fBuffer->data, (char*)target, targetSize);
1194 fBuffer->data += targetSize;
1195 return(0);
1196 } else {
1197 int32_t lastLeft;
1198 /* add back what was subtracted in test above.
1199 * lastLeft is the number of bytes left in the buffer before doing anything
1200 * and also the number of bytes from the users data that get copied into the buffer.
1201 */
1202 lastLeft = (fBuffer->bytesLeft += targetSize);
1203 /* copy part of the data into the buffer and write the buffer out */
1204 memcpy((char*)fBuffer->data, (char*)target, fBuffer->bytesLeft);
1205 if (fwrite(fBuffer->buffer, 1, fBuffer->bufferSize, fp)!=fBuffer->bufferSize)
1206 return(1);
1207 if (fflush(fp)) {
1208 ((SDDSFile*)sddsfile)->setError((char*)"Problem flushing file (SDDS_bufferedWrite)");
1209 return(1);
1210 }
1211 /* reset the data pointer and the bytesLeft value.
1212 * also, determine if the remaining data is too large for the buffer.
1213 * if so, just write it out.
1214 */
1215 fBuffer->data = fBuffer->buffer;
1216 if ((targetSize -= lastLeft)>(fBuffer->bytesLeft = fBuffer->bufferSize)) {
1217 return(fwrite((char*)target+lastLeft, 1, targetSize, fp)!=targetSize);
1218 }
1219 /* copy remaining data into the buffer.
1220 * could do this with a recursive call, but this is more efficient.
1221 */
1222 memcpy((char*)fBuffer->data, (char*)target+lastLeft, targetSize);
1223 fBuffer->data += targetSize;
1224 fBuffer->bytesLeft -= targetSize;
1225 return(0);
1226 }
1227}
1228
1229int32_t SDDS_bufferedWrite(void *target, size_t targetSize, voidp *gzfp,
1230 SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1231 if (!fBuffer->bufferSize) {
1232 ((SDDSFile*)sddsfile)->setError((char*)"You must presently have a nonzero file buffer to use zLib (reading/writing .gz files");
1233 }
1234 if ((fBuffer->bytesLeft-=targetSize)>=0) {
1235 memcpy((char*)fBuffer->data, (char*)target, targetSize);
1236 fBuffer->data += targetSize;
1237 return(0);
1238 } else {
1239 int32_t lastLeft;
1240 lastLeft = (fBuffer->bytesLeft += targetSize);
1241 memcpy((char*)fBuffer->data, (char*)target, fBuffer->bytesLeft);
1242 if (gzwrite(gzfp, fBuffer->buffer, fBuffer->bufferSize)!=fBuffer->bufferSize)
1243 return(1);
1244 fBuffer->bytesLeft = fBuffer->bufferSize;
1245 fBuffer->data = fBuffer->buffer;
1246 return(SDDS_bufferedWrite((char*)target+lastLeft, targetSize-lastLeft, gzfp, fBuffer, sddsfile));
1247 }
1248}
1249
1250/******************************************
1251 SDDS_flushBuffer
1252
1253 C++ Arguments: FILE *fp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1254 voidp *gzfp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1255
1256 Results: 0 on success
1257 1 on failure
1258*******************************************/
1259int32_t SDDS_flushBuffer(FILE *fp, SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1260 int32_t writeBytes;
1261 if (!fBuffer->bufferSize) {
1262 if (fflush(fp)) {
1263 ((SDDSFile*)sddsfile)->setError((char*)"Problem flushing file (SDDS_flushBuffer)");
1264 return(1);
1265 }
1266 return(0);
1267 }
1268 if ((writeBytes = fBuffer->bufferSize - fBuffer->bytesLeft)) {
1269 if (writeBytes<0) {
1270 ((SDDSFile*)sddsfile)->setError((char*)"Unable to flush buffer: negative byte count (SDDS_flushBuffer).");
1271 return(1);
1272 }
1273 if (fwrite(fBuffer->buffer, 1, writeBytes, fp)!=writeBytes) {
1274 ((SDDSFile*)sddsfile)->setError((char*)"Unable to flush buffer: write operation failed (SDDS_flushBuffer).");
1275 return(1);
1276 }
1277 fBuffer->bytesLeft = fBuffer->bufferSize;
1278 fBuffer->data = fBuffer->buffer;
1279 }
1280 if (fflush(fp)) {
1281 ((SDDSFile*)sddsfile)->setError((char*)"Problem flushing file (SDDS_flushBuffer)");
1282 return(1);
1283 }
1284 return(0);
1285}
1286
1287int32_t SDDS_flushBuffer(voidp *gzfp, SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1288 int32_t writeBytes;
1289 if ((writeBytes = fBuffer->bufferSize - fBuffer->bytesLeft)) {
1290 if (gzwrite(gzfp, fBuffer->buffer, writeBytes)!=writeBytes) {
1291 ((SDDSFile*)sddsfile)->setError((char*)"Unable to flush buffer: write operation failed (SDDS_flushBuffer).");
1292 return(1);
1293 }
1294 fBuffer->bytesLeft = fBuffer->bufferSize;
1295 fBuffer->data = fBuffer->buffer;
1296 }
1297 return(0);
1298}
1299
1300/******************************************
1301 SDDS_writeBinaryString
1302
1303 C++ Arguments: char *string, FILE *fp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1304 char *string, voidp *gzfp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1305
1306 Results: 0 on success
1307 1 on failure
1308*******************************************/
1309int32_t SDDS_writeBinaryString(char *string, FILE *fp, SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1310 int32_t length;
1311 static char *dummy_string = (char*)"";
1312 if (string == NULL) {
1313 string = dummy_string;
1314 }
1315 length = strlen(string);
1316 if (SDDS_bufferedWrite(&length, sizeof(length), fp, fBuffer, sddsfile)) {
1317 ((SDDSFile*)sddsfile)->setError((char*)"Unable to write string--error writing length (SDDS_writeBinaryString)");
1318 return(1);
1319 }
1320 if (length && SDDS_bufferedWrite(string, sizeof(*string)*length, fp, fBuffer, sddsfile)) {
1321 ((SDDSFile*)sddsfile)->setError((char*)"Unable to write string--error writing contents (SDDS_writeBinaryString)");
1322 return(1);
1323 }
1324 return(0);
1325}
1326
1327int32_t SDDS_writeBinaryString(char *string, voidp *gzfp, SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1328 int32_t length;
1329 static char *dummy_string = (char*)"";
1330 if (string == NULL) {
1331 string = dummy_string;
1332 }
1333 length = strlen(string);
1334 if (SDDS_bufferedWrite(&length, sizeof(length), gzfp, fBuffer, sddsfile)) {
1335 ((SDDSFile*)sddsfile)->setError((char*)"Unable to write string--error writing length (SDDS_writeBinaryString)");
1336 return(1);
1337 }
1338 if (length && SDDS_bufferedWrite(string, sizeof(*string)*length, gzfp, fBuffer, sddsfile)) {
1339 ((SDDSFile*)sddsfile)->setError((char*)"Unable to write string--error writing contents (SDDS_writeBinaryString)");
1340 return(1);
1341 }
1342 return(0);
1343}
1344
1345/******************************************
1346 SDDS_readBinaryString
1347
1348 C++ Arguments: char *string, FILE *fp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1349 char *string, voidp *gzfp, SDDS_FILEBUFFER *fBuffer, void *sddsfile
1350
1351 Results: 0 on success
1352 1 on failure
1353*******************************************/
1354int32_t SDDS_readBinaryString(char **string, FILE *fp, SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1355 int32_t length;
1356 if (SDDS_bufferedRead(&length, 4, fp, fBuffer, sddsfile)) {
1357 ((SDDSFile*)sddsfile)->setError((char*)"Unable to read string length (SDDS_readBinaryString)");
1358 return(1);
1359 }
1360 if (!(*string=(char*)SDDS_malloc(sizeof(char)*(length+1)))) {
1361 ((SDDSFile*)sddsfile)->setError((char*)"Unable to allocate memory (SDDS_readBinaryString)");
1362 return(1);
1363 }
1364 if (length) {
1365 if (SDDS_bufferedRead(*string, sizeof(char)*length, fp, fBuffer, sddsfile)) {
1366 ((SDDSFile*)sddsfile)->setError((char*)"Unable to read string (SDDS_readBinaryString)");
1367 return(1);
1368 }
1369 }
1370 (*string)[length] = 0;
1371 return(0);
1372}
1373
1374int32_t SDDS_readBinaryString(char **string, voidp *gzfp, SDDS_FILEBUFFER *fBuffer, void *sddsfile) {
1375 int32_t length;
1376 if (SDDS_bufferedRead(&length, 4, gzfp, fBuffer, sddsfile)) {
1377 ((SDDSFile*)sddsfile)->setError((char*)"Unable to read string length (SDDS_readBinaryString)");
1378 return(1);
1379 }
1380 if (!(*string=(char*)SDDS_malloc(sizeof(char)*(length+1)))) {
1381 ((SDDSFile*)sddsfile)->setError((char*)"Unable to allocate memory (SDDS_readBinaryString)");
1382 return(1);
1383 }
1384 if (length) {
1385 if (SDDS_bufferedRead(*string, sizeof(char)*length, gzfp, fBuffer, sddsfile)) {
1386 ((SDDSFile*)sddsfile)->setError((char*)"Unable to read string (SDDS_readBinaryString)");
1387 return(1);
1388 }
1389 }
1390 (*string)[length] = 0;
1391 return(0);
1392}
1393
1394/******************************************
1395 SDDS_registerProgramName
1396
1397 C++ Arguments: const char *name
1398
1399 Results: none
1400*******************************************/
1401static char *registeredProgramName = NULL;
1402void SDDS_registerProgramName(const char *name) {
1403 if (name != NULL) {
1404 if (SDDS_copyString(&registeredProgramName, (char*)name)) {
1405 registeredProgramName = NULL;
1406 }
1407 } else {
1408 registeredProgramName = NULL;
1409 }
1410}
1411
1412char *SDDS_getProgramName() {
1413 return(registeredProgramName);
1414}
1415
1416/******************************************
1417 SDDS_bomb
1418
1419 C++ Arguments: char *message
1420
1421 Please try to avoid calling this function and
1422 exit your code from the main routine instead.
1423 I understand that this may not always be possible.
1424
1425 Results: none
1426*******************************************/
1427void SDDS_bomb(char *message) {
1428 if (registeredProgramName)
1429 fprintf(stderr, "Error (%s): %s\n", registeredProgramName, message?message:"?");
1430 else
1431 fprintf(stderr, "Error: %s\n", message?message:"?");
1432 exit(1);
1433}
1434
1435void SDDS_warning(char *message) {
1436 if (registeredProgramName)
1437 fprintf(stderr, "Warning (%s): %s\n", registeredProgramName, message?message:"?");
1438 else
1439 fprintf(stderr, "Warning: %s\n", message?message:"?");
1440}
char * SDDS_type_name[SDDS_NUM_TYPES]
Array of supported data type names.
Definition SDDS_data.c:43
#define SDDS_NUM_TYPES
Total number of defined SDDS data types.
Definition SDDStypes.h:97
#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_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