SDDSlib
Loading...
Searching...
No Matches
SDDS_input.c
Go to the documentation of this file.
1/**
2 * @file SDDS_input.c
3 * @brief This file contains the functions related to reading SDDS files.
4 *
5 * The SDDS_input.c file provides functions for reading data from SDDS files.
6 * It includes functions for opening and closing SDDS files, reading headers,
7 * and reading data tables.
8 *
9 * @copyright
10 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
11 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
12 *
13 * @license
14 * This file is distributed under the terms of the Software License Agreement
15 * found in the file LICENSE included with this distribution.
16 *
17 * @author M. Borland, C. Saunders, R. Soliday, H. Shang
18 */
19
20#include "mdb.h"
21#include "match_string.h"
22#include "SDDS.h"
23#include "SDDS_internal.h"
24#include "namelist.h"
25#include "scan.h"
26
27#if defined(_WIN32)
28# include <fcntl.h>
29# include <io.h>
30# if !defined(_MINGW)
31# define pclose(x) _pclose(x)
32# endif
33# if defined(__BORLANDC__)
34# define _setmode(handle, amode) setmode(handle, amode)
35# endif
36#endif
37
38#define DEBUG 0
39
40/**
41 * Initializes a SDDS_DATASET structure for use in reading data from a SDDS file. This involves opening the file and reading the SDDS header.
42 *
43 * @param SDDS_dataset Address of the SDDS_DATASET structure for the data set.
44 * @param filename A NULL-terminated character string giving the name of the file to set up for input.
45 *
46 * @return 1 on success. On failure, returns 0 and records an error message.
47 *
48 */
49int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename) {
50 /* char *ptr, *datafile, *headerfile; */
51 char s[SDDS_MAXLINE];
52#if defined(zLib)
53 char *extension;
54#endif
55 if (sizeof(gzFile) != sizeof(void *)) {
56 SDDS_SetError("gzFile is not the same size as void *, possible corruption of the SDDS_LAYOUT structure");
57 return (0);
58 }
59 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_InitializeInput"))
60 return (0);
61
62 if (!SDDS_ZeroMemory((void *)SDDS_dataset, sizeof(SDDS_DATASET))) {
63 sprintf(s, "Unable to initialize input for file %s--can't zero SDDS_DATASET structure (SDDS_InitializeInput)", filename);
65 return (0);
66 }
67 SDDS_dataset->layout.gzipFile = SDDS_dataset->layout.lzmaFile = SDDS_dataset->layout.disconnected = SDDS_dataset->layout.popenUsed = 0;
68 SDDS_dataset->layout.depth = SDDS_dataset->layout.data_command_seen = SDDS_dataset->layout.commentFlags = SDDS_dataset->deferSavingLayout = 0;
69 SDDS_dataset->layout.data_mode.column_memory_mode = DEFAULT_COLUMN_MEMORY_MODE;
70 if (!filename)
71 SDDS_dataset->layout.filename = NULL;
72 else if (!SDDS_CopyString(&SDDS_dataset->layout.filename, filename)) {
73 sprintf(s, "Memory allocation failure initializing file \"%s\" (SDDS_InitializeInput)", filename);
75 return (0);
76 }
77 if (!filename) {
78#if defined(_WIN32)
79 if (_setmode(_fileno(stdin), _O_BINARY) == -1) {
80 sprintf(s, "unable to set stdin to binary mode");
82 return 0;
83 }
84#endif
85 SDDS_dataset->layout.fp = stdin;
86 } else {
87#if defined(zLib)
88 if (!(extension = strrchr(filename, '.')) || strcmp(extension, ".gz") != 0) {
89#endif
90 if ((extension = strrchr(filename, '.')) && ((strcmp(extension, ".lzma") == 0) || (strcmp(extension, ".xz") == 0))) {
91 SDDS_dataset->layout.lzmaFile = 1;
92 if (!(SDDS_dataset->layout.lzmafp = UnpackLZMAOpen(filename))) {
93 sprintf(s, "Unable to open file \"%s\" for reading (SDDS_InitializeInput)", filename);
95 return (0);
96 }
97 SDDS_dataset->layout.fp = SDDS_dataset->layout.lzmafp->fp;
98 } else {
99 if (!(SDDS_dataset->layout.fp = UnpackFopen(filename, UNPACK_REQUIRE_SDDS | UNPACK_USE_PIPE, &SDDS_dataset->layout.popenUsed, NULL))) {
100 sprintf(s, "Unable to open file \"%s\" for reading (SDDS_InitializeInput)", filename);
101 SDDS_SetError(s);
102 return (0);
103 }
104 }
105#if defined(zLib)
106 } else {
107 SDDS_dataset->layout.gzipFile = 1;
108 if (!(SDDS_dataset->layout.gzfp = UnpackGZipOpen(filename))) {
109 sprintf(s, "Unable to open file \"%s\" for reading (SDDS_InitializeInput)", filename);
110 SDDS_SetError(s);
111 return (0);
112 }
113 }
114#endif
115 }
116 SDDS_dataset->page_number = SDDS_dataset->page_started = 0;
117 SDDS_dataset->file_had_data = 0;
118 SDDS_DeferSavingLayout(SDDS_dataset, 1);
119#if defined(zLib)
120 if (SDDS_dataset->layout.gzipFile) {
121 if (!SDDS_GZipReadLayout(SDDS_dataset, SDDS_dataset->layout.gzfp))
122 return (0);
123 } else {
124#endif
125 if (SDDS_dataset->layout.lzmaFile) {
126 if (!SDDS_LZMAReadLayout(SDDS_dataset, SDDS_dataset->layout.lzmafp))
127 return (0);
128 } else {
129 if (!SDDS_ReadLayout(SDDS_dataset, SDDS_dataset->layout.fp))
130 return (0);
131 }
132#if defined(zLib)
133 }
134#endif
135 SDDS_dataset->layout.layout_written = 0;
136 SDDS_DeferSavingLayout(SDDS_dataset, 0);
137 if (!SDDS_SaveLayout(SDDS_dataset))
138 return 0;
139 if (SDDS_dataset->layout.n_columns &&
140 ((!(SDDS_dataset->column_flag = (int32_t *)SDDS_Malloc(sizeof(int32_t) * SDDS_dataset->layout.n_columns)) ||
141 !(SDDS_dataset->column_order = (int32_t *)SDDS_Malloc(sizeof(int32_t) * SDDS_dataset->layout.n_columns))) ||
142 (!SDDS_SetMemory(SDDS_dataset->column_flag, SDDS_dataset->layout.n_columns, SDDS_LONG, (int32_t)1, (int32_t)0) ||
143 !SDDS_SetMemory(SDDS_dataset->column_order, SDDS_dataset->layout.n_columns, SDDS_LONG, (int32_t)0, (int32_t)1)))) {
144 SDDS_SetError("Unable to initialize input--memory allocation failure (SDDS_InitializeInput)");
145 return (0);
146 }
147 SDDS_dataset->mode = SDDS_READMODE; /*reading */
148 SDDS_dataset->pagecount_offset = NULL;
149 if (!SDDS_dataset->layout.gzipFile && !SDDS_dataset->layout.lzmaFile && !SDDS_dataset->layout.popenUsed && SDDS_dataset->layout.filename) {
150 /* Data is not:
151 1. from a gzip file
152 2. from a file that is being internally decompressed by a command executed with popen()
153 3. from a pipe set up externally (e.g., -pipe=in on commandline)
154 */
155 SDDS_dataset->pages_read = 0;
156 SDDS_dataset->pagecount_offset = malloc(sizeof(*SDDS_dataset->pagecount_offset));
157 SDDS_dataset->pagecount_offset[0] = ftell(SDDS_dataset->layout.fp);
158 fseek(SDDS_dataset->layout.fp, 0, 2); /*point to the end of the file */
159 SDDS_dataset->endOfFile_offset = ftell(SDDS_dataset->layout.fp);
160 fseek(SDDS_dataset->layout.fp, SDDS_dataset->pagecount_offset[0], 0);
161 /*point to the beginning of the first page */
162 }
163 return (1);
164}
165
166/**
167 * @brief Initializes the SDDS dataset for headerless input.
168 *
169 * This function initializes the SDDS dataset structure for reading data from a file without a header.
170 *
171 * @param SDDS_dataset A pointer to the SDDS_DATASET structure to be initialized.
172 * @param filename The name of the file to read data from.
173 * @return Returns 1 on success, 0 on failure.
174 */
175int32_t SDDS_InitializeHeaderlessInput(SDDS_DATASET *SDDS_dataset, char *filename) {
176 /* char *ptr, *datafile; */
177
178 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_InitializeInput"))
179 return (0);
180 if (!SDDS_ZeroMemory((void *)SDDS_dataset, sizeof(SDDS_DATASET))) {
181 SDDS_SetError("Unable to initialize input--can't zero SDDS_DATASET structure (SDDS_InitializeInput)");
182 return (0);
183 }
184 SDDS_dataset->layout.gzipFile = SDDS_dataset->layout.lzmaFile = 0;
185 SDDS_dataset->layout.depth = SDDS_dataset->layout.data_command_seen = SDDS_dataset->layout.commentFlags = SDDS_dataset->deferSavingLayout = 0;
186 if (!(SDDS_dataset->layout.fp = fopen(filename, FOPEN_READ_MODE))) {
187 SDDS_SetError("Unable to open file (SDDS_InitializeInput)");
188 return (0);
189 }
190 if (!SDDS_CopyString(&SDDS_dataset->layout.filename, filename)) {
191 SDDS_SetError("Memory allocation failure (SDDS_InitializeInput)");
192 return (0);
193 }
194 SDDS_dataset->mode = SDDS_READMODE; /*reading */
195 SDDS_dataset->page_number = SDDS_dataset->page_started = 0;
196 SDDS_dataset->pages_read = 0;
197 SDDS_dataset->pagecount_offset = malloc(sizeof(*SDDS_dataset->pagecount_offset));
198 SDDS_dataset->pagecount_offset[0] = ftell(SDDS_dataset->layout.fp);
199 fseek(SDDS_dataset->layout.fp, 0, 2); /*point to the end of the file */
200 SDDS_dataset->endOfFile_offset = ftell(SDDS_dataset->layout.fp);
201 fseek(SDDS_dataset->layout.fp, SDDS_dataset->pagecount_offset[0], 0);
202 /*point to the beginning of the first page */
203 return (1);
204}
205
206/**
207 * @brief Checks if a position in a string is within a quoted section.
208 *
209 * Determines whether the specified position within a string falls inside a quoted section
210 * delimited by the given quotation mark.
211 *
212 * @param string The string to examine.
213 * @param position The position within the string to check.
214 * @param quotation_mark The character used as the quotation mark.
215 * @return Returns 1 if the position is within a quoted section, 0 otherwise.
216 */
217int32_t SDDS_IsQuoted(char *string, char *position, char quotation_mark) {
218 int32_t in_quoted_section;
219 char *string0;
220
221 if (*position == quotation_mark)
222 return (1);
223
224 in_quoted_section = 0;
225 string0 = string;
226 while (*string) {
227 if (*string == quotation_mark && (string == string0 || *(string - 1) != '\\'))
228 in_quoted_section = !in_quoted_section;
229 else if (string == position)
230 return (in_quoted_section);
231 string++;
232 }
233 return (0);
234}
235
236/**
237 * @brief Reads a namelist from a file into a buffer.
238 *
239 * This function reads a namelist from the given file stream into the provided buffer,
240 * handling comments and skipping them appropriately.
241 *
242 * @param SDDS_dataset The SDDS dataset structure.
243 * @param buffer The buffer where the namelist will be stored.
244 * @param buflen The length of the buffer.
245 * @param fp The file stream to read from.
246 * @return Returns 1 if a namelist is successfully read, 0 otherwise.
247 */
248int32_t SDDS_GetNamelist(SDDS_DATASET *SDDS_dataset, char *buffer, int32_t buflen, FILE *fp) {
249 char *ptr, *flag, *buffer0;
250 /* char *ptr1 */
251 int32_t n, i;
252 /* int32_t namelistStarted; */
253
254 while ((flag = fgetsSkipComments(SDDS_dataset, buffer, buflen, fp, '!'))) {
255 if ((ptr = strchr(buffer, '&')) && !SDDS_IsQuoted(buffer, ptr, '"'))
256 break;
257 }
258 if (!flag)
259 return 0;
260 n = strlen(buffer) - 1;
261 if (buffer[n] == '\n') {
262 buffer[n] = ' ';
263 if ((n - 1 >= 0) && (buffer[n - 1] == '\r'))
264 buffer[n - 1] = ' ';
265 }
266
267 /* check for the beginning of a namelist (an unquoted &) */
268 ptr = buffer;
269 while (*ptr) {
270 if (*ptr == '"') {
271 /* skip quoted section */
272 ptr++;
273 while (*ptr != '"' && *ptr)
274 ptr++;
275 if (*ptr)
276 ptr++;
277 continue;
278 }
279 if (*ptr == '&') {
280 if (strncmp(ptr, "&end", 4) == 0)
281 return 0;
282 break;
283 }
284 ptr++;
285 }
286 if (!*ptr)
287 return 0;
288
289 /* remove the trailing &end if there is one */
290 if ((n = strlen(buffer)) >= 4) {
291 ptr = buffer + n - 4;
292 while (1) {
293 if (*ptr == '&' && (ptr == buffer || *(ptr - 1) != '\\') && strncmp(ptr, "&end", 4) == 0 && !SDDS_IsQuoted(buffer, ptr, '"')) {
294 *ptr = 0;
295 return 1;
296 }
297 if (ptr == buffer)
298 break;
299 ptr--;
300 }
301 }
302
303 /* read in the remainder of the namelist */
304 buffer0 = buffer;
305 buflen -= strlen(buffer);
306 buffer += strlen(buffer);
307 i = 0;
308 while ((flag = fgetsSkipComments(SDDS_dataset, buffer, buflen, fp, '!'))) {
309 n = strlen(buffer) - 1;
310 if (buffer[n] == '\n') {
311 buffer[n] = ' ';
312 if ((n - 1 >= 0) && (buffer[n - 1] == '\r'))
313 buffer[n - 1] = ' ';
314 }
315 if ((ptr = strstr(buffer, "&end")) && !SDDS_IsQuoted(buffer0, ptr, '"'))
316 return 1;
317 buflen -= strlen(buffer);
318 buffer += strlen(buffer);
319 if (buflen == 0)
320 return 0;
321 /* this was needed after encountering a file that had binary crap
322 dumpted into the header. sddscheck will now report badHeader
323 instead of getting stuck in an endless loop here. */
324 i++;
325 if (i > 10000) {
326 return 0;
327 }
328 }
329 return 0;
330}
331
332/**
333 * @brief Reads a namelist from an LZMA-compressed file into a buffer.
334 *
335 * This function reads a namelist from an LZMA-compressed file stream into the provided buffer,
336 * handling comments and skipping them appropriately.
337 *
338 * @param SDDS_dataset The SDDS dataset structure.
339 * @param buffer The buffer where the namelist will be stored.
340 * @param buflen The length of the buffer.
341 * @param lzmafp The LZMA file stream to read from.
342 * @return Returns 1 if a namelist is successfully read, 0 otherwise.
343 */
344int32_t SDDS_GetLZMANamelist(SDDS_DATASET *SDDS_dataset, char *buffer, int32_t buflen, struct lzmafile *lzmafp) {
345 char *ptr, *flag, *buffer0;
346 /* char *ptr1 */
347 int32_t n;
348 /* int32_t namelistStarted; */
349
350 while ((flag = fgetsLZMASkipComments(SDDS_dataset, buffer, buflen, lzmafp, '!'))) {
351 if ((ptr = strchr(buffer, '&')) && !SDDS_IsQuoted(buffer, ptr, '"'))
352 break;
353 }
354 if (!flag)
355 return 0;
356 n = strlen(buffer) - 1;
357 if (buffer[n] == '\n') {
358 buffer[n] = ' ';
359 if ((n - 1 >= 0) && (buffer[n - 1] == '\r'))
360 buffer[n - 1] = ' ';
361 }
362
363 /* check for the beginning of a namelist (an unquoted &) */
364 ptr = buffer;
365 while (*ptr) {
366 if (*ptr == '"') {
367 /* skip quoted section */
368 ptr++;
369 while (*ptr != '"' && *ptr)
370 ptr++;
371 if (*ptr)
372 ptr++;
373 continue;
374 }
375 if (*ptr == '&') {
376 if (strncmp(ptr, "&end", 4) == 0)
377 return 0;
378 break;
379 }
380 ptr++;
381 }
382 if (!*ptr)
383 return 0;
384
385 /* remove the trailing &end if there is one */
386 if ((n = strlen(buffer)) >= 4) {
387 ptr = buffer + n - 4;
388 while (1) {
389 if (*ptr == '&' && (ptr == buffer || *(ptr - 1) != '\\') && strncmp(ptr, "&end", 4) == 0 && !SDDS_IsQuoted(buffer, ptr, '"')) {
390 *ptr = 0;
391 return 1;
392 }
393 if (ptr == buffer)
394 break;
395 ptr--;
396 }
397 }
398
399 /* read in the remainder of the namelist */
400 buffer0 = buffer;
401 buflen -= strlen(buffer);
402 buffer += strlen(buffer);
403 while ((flag = fgetsLZMASkipComments(SDDS_dataset, buffer, buflen, lzmafp, '!'))) {
404 n = strlen(buffer) - 1;
405 if (buffer[n] == '\n') {
406 buffer[n] = ' ';
407 if ((n - 1 >= 0) && (buffer[n - 1] == '\r'))
408 buffer[n - 1] = ' ';
409 }
410 if ((ptr = strstr(buffer, "&end")) && !SDDS_IsQuoted(buffer0, ptr, '"'))
411 return 1;
412 buflen -= strlen(buffer);
413 buffer += strlen(buffer);
414 if (buflen == 0)
415 return 0;
416 }
417 return 0;
418}
419
420#if defined(zLib)
421/**
422 * @brief Reads a namelist from a GZip-compressed file into a buffer.
423 *
424 * This function reads a namelist from a GZip-compressed file stream into the provided buffer,
425 * handling comments and skipping them appropriately.
426 *
427 * @param SDDS_dataset The SDDS dataset structure.
428 * @param buffer The buffer where the namelist will be stored.
429 * @param buflen The length of the buffer.
430 * @param gzfp The GZip file stream to read from.
431 * @return Returns 1 if a namelist is successfully read, 0 otherwise.
432 */
433int32_t SDDS_GetGZipNamelist(SDDS_DATASET *SDDS_dataset, char *buffer, int32_t buflen, gzFile gzfp) {
434 char *ptr, *flag, *buffer0;
435 /* char *ptr1 */
436 int32_t n;
437 /* int32_t namelistStarted; */
438
439 while ((flag = fgetsGZipSkipComments(SDDS_dataset, buffer, buflen, gzfp, '!'))) {
440 if ((ptr = strchr(buffer, '&')) && !SDDS_IsQuoted(buffer, ptr, '"'))
441 break;
442 }
443 if (!flag)
444 return 0;
445 n = strlen(buffer) - 1;
446 if (buffer[n] == '\n') {
447 buffer[n] = ' ';
448 if ((n - 1 >= 0) && (buffer[n - 1] == '\r'))
449 buffer[n - 1] = ' ';
450 }
451
452 /* check for the beginning of a namelist (an unquoted &) */
453 ptr = buffer;
454 while (*ptr) {
455 if (*ptr == '"') {
456 /* skip quoted section */
457 ptr++;
458 while (*ptr != '"' && *ptr)
459 ptr++;
460 if (*ptr)
461 ptr++;
462 continue;
463 }
464 if (*ptr == '&') {
465 if (strncmp(ptr, "&end", 4) == 0)
466 return 0;
467 break;
468 }
469 ptr++;
470 }
471 if (!*ptr)
472 return 0;
473
474 /* remove the trailing &end if there is one */
475 if ((n = strlen(buffer)) >= 4) {
476 ptr = buffer + n - 4;
477 while (1) {
478 if (*ptr == '&' && (ptr == buffer || *(ptr - 1) != '\\') && strncmp(ptr, "&end", 4) == 0 && !SDDS_IsQuoted(buffer, ptr, '"')) {
479 *ptr = 0;
480 return 1;
481 }
482 if (ptr == buffer)
483 break;
484 ptr--;
485 }
486 }
487
488 /* read in the remainder of the namelist */
489 buffer0 = buffer;
490 buflen -= strlen(buffer);
491 buffer += strlen(buffer);
492 while ((flag = fgetsGZipSkipComments(SDDS_dataset, buffer, buflen, gzfp, '!'))) {
493 n = strlen(buffer) - 1;
494 if (buffer[n] == '\n') {
495 buffer[n] = ' ';
496 if ((n - 1 >= 0) && (buffer[n - 1] == '\r'))
497 buffer[n - 1] = ' ';
498 }
499 if ((ptr = strstr(buffer, "&end")) && !SDDS_IsQuoted(buffer0, ptr, '"'))
500 return 1;
501 buflen -= strlen(buffer);
502 buffer += strlen(buffer);
503 if (buflen == 0)
504 return 0;
505 }
506 return 0;
507}
508#endif
509
510/**
511 * Reads the header layout of an SDDS dataset from a file.
512 *
513 * @param SDDS_dataset The SDDS dataset structure to store the layout information.
514 * @param fp The file pointer to the SDDS file.
515 * @return Returns 1 on success, 0 on failure.
516 */
517int32_t SDDS_ReadLayout(SDDS_DATASET *SDDS_dataset, FILE *fp) {
518 char buffer[SDDS_MAXLINE];
519 char *groupName, *ptr;
520 FILE *fp1;
521 int32_t retval, bigEndianMachine;
522 uint32_t commentFlags;
523
524 if (!fp) {
525 SDDS_SetError("Unable to read layout--NULL file pointer (SDDS_ReadLayout)");
526 return (0);
527 }
528 if (SDDS_dataset->layout.depth == 0) {
529 if (SDDS_dataset->layout.disconnected) {
530 SDDS_SetError("Can't read layout--file is disconnected (SDDS_ReadLayout)");
531 return 0;
532 }
533 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ReadLayout")) {
534 fclose(fp);
535 return (0);
536 }
537 SDDS_dataset->layout.layout_written = 1; /* it is already in the file */
538 if (!fgets(SDDS_dataset->layout.s, SDDS_MAXLINE, fp)) {
539 fclose(fp);
540 SDDS_SetError("Unable to read layout--no header lines found (SDDS_ReadLayout)");
541 return (0);
542 }
543 if (strncmp(SDDS_dataset->layout.s, "SDDS", 4) != 0) {
544 fclose(fp);
545 SDDS_SetError("Unable to read layout--no header lines found (SDDS_ReadLayout)");
546 return (0);
547 }
548 if (sscanf(SDDS_dataset->layout.s + 4, "%" SCNd32, &SDDS_dataset->layout.version) != 1) {
549 fclose(fp);
550 SDDS_SetError("Unable to read layout--no version number on first line (SDDS_ReadLayout)");
551 return (0);
552 }
553 SDDS_ResetSpecialCommentsModes(SDDS_dataset);
554 SDDS_dataset->layout.data_command_seen = 0;
555 }
556 while (SDDS_GetNamelist(SDDS_dataset, SDDS_dataset->layout.s, SDDS_MAXLINE, fp)) {
557#if DEBUG
558 strcpy(buffer, SDDS_dataset->layout.s);
559#endif
560 groupName = SDDS_dataset->layout.s + 1;
561 if (!(ptr = strpbrk(SDDS_dataset->layout.s, " \t"))) {
562 SDDS_SetError("Unable to read layout---no groupname in namelist (SDDS_ReadLayout)");
563 return 0;
564 }
565 *ptr = 0;
566 switch (match_string(groupName, SDDS_command, SDDS_NUM_COMMANDS, EXACT_MATCH)) {
567 case SDDS_DESCRIPTION_COMMAND:
568 if (!SDDS_ProcessDescription(SDDS_dataset, ptr + 1)) {
569 fclose(fp);
570 SDDS_SetError("Unable to process description (SDDS_ReadLayout)");
571 return (0);
572 }
573 break;
574 case SDDS_COLUMN_COMMAND:
575 if (!SDDS_ProcessColumnDefinition(SDDS_dataset, ptr + 1)) {
576 fclose(fp);
577 SDDS_SetError("Unable to process column definition (SDDS_ReadLayout)");
578 return (0);
579 }
580 break;
581 case SDDS_PARAMETER_COMMAND:
582 if (!SDDS_ProcessParameterDefinition(SDDS_dataset, ptr + 1)) {
583 fclose(fp);
584 SDDS_SetError("Unable to process parameter definition (SDDS_ReadLayout)");
585 return (0);
586 }
587 break;
588 case SDDS_ASSOCIATE_COMMAND:
589#if RW_ASSOCIATES != 0
590 if (!SDDS_ProcessAssociateDefinition(SDDS_dataset, ptr + 1)) {
591 fclose(fp);
592 SDDS_SetError("Unable to process associate definition (SDDS_ReadLayout)");
593 return (0);
594 }
595#endif
596 break;
597 case SDDS_DATA_COMMAND:
598 if (!SDDS_ProcessDataMode(SDDS_dataset, ptr + 1)) {
599 fclose(fp);
600 SDDS_SetError("Unable to process data mode (SDDS_ReadLayout)");
601 return (0);
602 }
603 if (SDDS_dataset->layout.data_command_seen) {
604 /* should never happen */
605 fclose(fp);
606 SDDS_SetError("Unable to read layout--multiple data commands (SDDS_ReadLayout)");
607 return (0);
608 }
609 if (!SDDS_SaveLayout(SDDS_dataset)) {
610 SDDS_SetError("Unable to read layout--couldn't save layout (SDDS_ReadLayout)");
611 return (0);
612 }
613 SDDS_dataset->layout.data_command_seen = 1;
614 commentFlags = SDDS_GetSpecialCommentsModes(SDDS_dataset);
615 if ((commentFlags & SDDS_BIGENDIAN_SEEN) && (commentFlags & SDDS_LITTLEENDIAN_SEEN)) {
616 SDDS_SetError("Unable to read data as it says it is both big and little endian (SDDS_ReadLayout)");
617 return (0);
618 }
619 bigEndianMachine = SDDS_IsBigEndianMachine();
620 SDDS_dataset->swapByteOrder = SDDS_dataset->layout.byteOrderDeclared = 0;
621 SDDS_dataset->autoRecover = 0;
622 if ((commentFlags & SDDS_BIGENDIAN_SEEN) || (SDDS_dataset->layout.data_mode.endian == SDDS_BIGENDIAN)) {
623 SDDS_dataset->layout.byteOrderDeclared = SDDS_BIGENDIAN_SEEN;
624 if (!bigEndianMachine)
625 SDDS_dataset->swapByteOrder = 1;
626 }
627 if ((commentFlags & SDDS_LITTLEENDIAN_SEEN) || (SDDS_dataset->layout.data_mode.endian == SDDS_LITTLEENDIAN)) {
628 SDDS_dataset->layout.byteOrderDeclared = SDDS_LITTLEENDIAN_SEEN;
629 if (bigEndianMachine)
630 SDDS_dataset->swapByteOrder = 1;
631 }
632 if ((commentFlags & SDDS_FIXED_ROWCOUNT_SEEN) || (SDDS_dataset->layout.data_mode.fixed_row_count))
633 if (!SDDS_SetAutoReadRecovery(SDDS_dataset, SDDS_AUTOREADRECOVER))
634 return (0);
635 return (1);
636 case SDDS_INCLUDE_COMMAND:
637 if (!(fp1 = SDDS_ProcessIncludeCommand(SDDS_dataset, ptr + 1))) {
638 fclose(fp);
639 SDDS_SetError("Unable to process include command (SDDS_ReadLayout)");
640 return (0);
641 }
642 SDDS_dataset->layout.depth += 1;
643 retval = SDDS_ReadLayout(SDDS_dataset, fp1);
644 SDDS_dataset->layout.depth -= 1;
645 fclose(fp1);
646 if (retval == 0) {
647 return (0);
648 }
649 if (SDDS_dataset->layout.data_command_seen) {
650 return (1);
651 }
652 break;
653 case SDDS_ARRAY_COMMAND:
654 if (!SDDS_ProcessArrayDefinition(SDDS_dataset, ptr + 1)) {
655 fclose(fp);
656 SDDS_SetError("Unable to process array definition (SDDS_ReadLayout)");
657 return (0);
658 }
659 break;
660 default:
661 fclose(fp);
662 sprintf(buffer, "Unknown layout entry %s given (SDDS_ReadLayout)", groupName);
663 SDDS_SetError(buffer);
664 return (0);
665 }
666 }
667 /* on recursive calls, it's okay to hit EOF */
668 if ((feof(fp) && SDDS_dataset->layout.depth != 0) || SDDS_dataset->layout.data_command_seen)
669 return (1);
670 return (0);
671}
672
673/**
674 * Reads the header layout of an SDDS dataset from a file with LZMA compression.
675 *
676 * @param SDDS_dataset The SDDS dataset structure to store the layout information.
677 * @param lzmafp The LZMA file pointer to the SDDS file.
678 * @return Returns 1 on success, 0 on failure.
679 */
680int32_t SDDS_LZMAReadLayout(SDDS_DATASET *SDDS_dataset, struct lzmafile *lzmafp) {
681 char buffer[SDDS_MAXLINE];
682 char *groupName, *ptr;
683 FILE *fp1;
684 int32_t retval, bigEndianMachine;
685 uint32_t commentFlags;
686
687 if (!lzmafp) {
688 SDDS_SetError("Unable to read layout--NULL file pointer (SDDS_LZMAReadLayout)");
689 return (0);
690 }
691 if (SDDS_dataset->layout.depth == 0) {
692 if (SDDS_dataset->layout.disconnected) {
693 SDDS_SetError("Can't read layout--file is disconnected (SDDS_LZMAReadLayout)");
694 return 0;
695 }
696 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_LZMAReadLayout")) {
697 lzma_close(lzmafp);
698 return (0);
699 }
700 SDDS_dataset->layout.layout_written = 1; /* it is already in the file */
701 if (!lzma_gets(SDDS_dataset->layout.s, SDDS_MAXLINE, lzmafp)) {
702 lzma_close(lzmafp);
703 SDDS_SetError("Unable to read layout--no header lines found (SDDS_LZMAReadLayout)");
704 return (0);
705 }
706 if (strncmp(SDDS_dataset->layout.s, "SDDS", 4) != 0) {
707 lzma_close(lzmafp);
708 SDDS_SetError("Unable to read layout--no header lines found (SDDS_LZMAReadLayout)");
709 return (0);
710 }
711 if (sscanf(SDDS_dataset->layout.s + 4, "%" SCNd32, &SDDS_dataset->layout.version) != 1) {
712 lzma_close(lzmafp);
713 SDDS_SetError("Unable to read layout--no version number on first line (SDDS_LZMAReadLayout)");
714 return (0);
715 }
716 SDDS_ResetSpecialCommentsModes(SDDS_dataset);
717 SDDS_dataset->layout.data_command_seen = 0;
718 }
719 while (SDDS_GetLZMANamelist(SDDS_dataset, SDDS_dataset->layout.s, SDDS_MAXLINE, lzmafp)) {
720#if DEBUG
721 strcpy(buffer, SDDS_dataset->layout.s);
722#endif
723 groupName = SDDS_dataset->layout.s + 1;
724 if (!(ptr = strpbrk(SDDS_dataset->layout.s, " \t"))) {
725 SDDS_SetError("Unable to read layout---no groupname in namelist (SDDS_LZMAReadLayout)");
726 return 0;
727 }
728 *ptr = 0;
729 switch (match_string(groupName, SDDS_command, SDDS_NUM_COMMANDS, EXACT_MATCH)) {
730 case SDDS_DESCRIPTION_COMMAND:
731 if (!SDDS_ProcessDescription(SDDS_dataset, ptr + 1)) {
732 lzma_close(lzmafp);
733 SDDS_SetError("Unable to process description (SDDS_LZMAReadLayout)");
734 return (0);
735 }
736 break;
737 case SDDS_COLUMN_COMMAND:
738 if (!SDDS_ProcessColumnDefinition(SDDS_dataset, ptr + 1)) {
739 lzma_close(lzmafp);
740 SDDS_SetError("Unable to process column definition (SDDS_LZMAReadLayout)");
741 return (0);
742 }
743 break;
744 case SDDS_PARAMETER_COMMAND:
745 if (!SDDS_ProcessParameterDefinition(SDDS_dataset, ptr + 1)) {
746 lzma_close(lzmafp);
747 SDDS_SetError("Unable to process parameter definition (SDDS_LZMAReadLayout)");
748 return (0);
749 }
750 break;
751 case SDDS_ASSOCIATE_COMMAND:
752#if RW_ASSOCIATES != 0
753 if (!SDDS_ProcessAssociateDefinition(SDDS_dataset, ptr + 1)) {
754 lzma_close(lzmafp);
755 SDDS_SetError("Unable to process associate definition (SDDS_LZMAReadLayout)");
756 return (0);
757 }
758#endif
759 break;
760 case SDDS_DATA_COMMAND:
761 if (!SDDS_ProcessDataMode(SDDS_dataset, ptr + 1)) {
762 lzma_close(lzmafp);
763 SDDS_SetError("Unable to process data mode (SDDS_LZMAReadLayout)");
764 return (0);
765 }
766 if (SDDS_dataset->layout.data_command_seen) {
767 /* should never happen */
768 lzma_close(lzmafp);
769 SDDS_SetError("Unable to read layout--multiple data commands (SDDS_LZMAReadLayout)");
770 return (0);
771 }
772 if (!SDDS_SaveLayout(SDDS_dataset)) {
773 SDDS_SetError("Unable to read layout--couldn't save layout (SDDS_LZMAReadLayout)");
774 return (0);
775 }
776 SDDS_dataset->layout.data_command_seen = 1;
777 commentFlags = SDDS_GetSpecialCommentsModes(SDDS_dataset);
778 if ((commentFlags & SDDS_BIGENDIAN_SEEN) && (commentFlags & SDDS_LITTLEENDIAN_SEEN)) {
779 SDDS_SetError("Unable to read data as it says it is both big and little endian (SDDS_LZMAReadLayout)");
780 return (0);
781 }
782 bigEndianMachine = SDDS_IsBigEndianMachine();
783 SDDS_dataset->swapByteOrder = SDDS_dataset->layout.byteOrderDeclared = 0;
784 SDDS_dataset->autoRecover = 0;
785 if ((commentFlags & SDDS_BIGENDIAN_SEEN) || (SDDS_dataset->layout.data_mode.endian == SDDS_BIGENDIAN)) {
786 SDDS_dataset->layout.byteOrderDeclared = SDDS_BIGENDIAN_SEEN;
787 if (!bigEndianMachine)
788 SDDS_dataset->swapByteOrder = 1;
789 }
790 if ((commentFlags & SDDS_LITTLEENDIAN_SEEN) || (SDDS_dataset->layout.data_mode.endian == SDDS_LITTLEENDIAN)) {
791 SDDS_dataset->layout.byteOrderDeclared = SDDS_LITTLEENDIAN_SEEN;
792 if (bigEndianMachine)
793 SDDS_dataset->swapByteOrder = 1;
794 }
795 if ((commentFlags & SDDS_FIXED_ROWCOUNT_SEEN) || (SDDS_dataset->layout.data_mode.fixed_row_count))
796 if (!SDDS_SetAutoReadRecovery(SDDS_dataset, SDDS_AUTOREADRECOVER))
797 return (0);
798 return (1);
799 case SDDS_INCLUDE_COMMAND:
800 if (!(fp1 = SDDS_ProcessIncludeCommand(SDDS_dataset, ptr + 1))) {
801 lzma_close(lzmafp);
802 SDDS_SetError("Unable to process include command (SDDS_LZMAReadLayout)");
803 return (0);
804 }
805 SDDS_dataset->layout.depth += 1;
806 retval = SDDS_ReadLayout(SDDS_dataset, fp1);
807 SDDS_dataset->layout.depth -= 1;
808 fclose(fp1);
809 if (retval == 0) {
810 return (0);
811 }
812 if (SDDS_dataset->layout.data_command_seen) {
813 return (1);
814 }
815 break;
816 case SDDS_ARRAY_COMMAND:
817 if (!SDDS_ProcessArrayDefinition(SDDS_dataset, ptr + 1)) {
818 lzma_close(lzmafp);
819 SDDS_SetError("Unable to process array definition (SDDS_LZMAReadLayout)");
820 return (0);
821 }
822 break;
823 default:
824 lzma_close(lzmafp);
825 sprintf(buffer, "Unknown layout entry %s given (SDDS_LZMAReadLayout)", groupName);
826 SDDS_SetError(buffer);
827 return (0);
828 }
829 }
830 /* on recursive calls, it's okay to hit EOF */
831 if ((lzma_eof(lzmafp) && SDDS_dataset->layout.depth != 0) || SDDS_dataset->layout.data_command_seen)
832 return (1);
833 return (0);
834}
835
836#if defined(zLib)
837/**
838 * Reads the header layout of an SDDS dataset from a file with GZIP compression.
839 *
840 * @param SDDS_dataset The SDDS dataset structure to store the layout information.
841 * @param gzfp The GZIP file pointer to the SDDS file.
842 * @return Returns 1 on success, 0 on failure.
843 */
844int32_t SDDS_GZipReadLayout(SDDS_DATASET *SDDS_dataset, gzFile gzfp) {
845 char buffer[SDDS_MAXLINE];
846 char *groupName, *ptr;
847 FILE *fp1;
848 int32_t retval, bigEndianMachine;
849 uint32_t commentFlags;
850
851 if (!gzfp) {
852 SDDS_SetError("Unable to read layout--NULL file pointer (SDDS_GZipReadLayout)");
853 return (0);
854 }
855 if (SDDS_dataset->layout.disconnected) {
856 SDDS_SetError("Can't read layout--file is disconnected (SDDS_GZipReadLayout)");
857 return 0;
858 }
859 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GZipReadLayout")) {
860 gzclose(gzfp);
861 return (0);
862 }
863 SDDS_dataset->layout.layout_written = 1; /* it is already in the file */
864 if (!gzgets(gzfp, SDDS_dataset->layout.s, SDDS_MAXLINE)) {
865 gzclose(gzfp);
866 SDDS_SetError("Unable to read layout--no header lines found (SDDS_GZipReadLayout)");
867 return (0);
868 }
869 if (strncmp(SDDS_dataset->layout.s, "SDDS", 4) != 0) {
870 gzclose(gzfp);
871 SDDS_SetError("Unable to read layout--no header lines found (SDDS_GZipReadLayout)");
872 return (0);
873 }
874 if (sscanf(SDDS_dataset->layout.s + 4, "%" SCNd32, &SDDS_dataset->layout.version) != 1) {
875 gzclose(gzfp);
876 SDDS_SetError("Unable to read layout--no version number on first line (SDDS_GZipReadLayout)");
877 return (0);
878 }
879 SDDS_ResetSpecialCommentsModes(SDDS_dataset);
880 if (SDDS_dataset->layout.depth == 0)
881 SDDS_dataset->layout.data_command_seen = 0;
882 while (SDDS_GetGZipNamelist(SDDS_dataset, SDDS_dataset->layout.s, SDDS_MAXLINE, gzfp)) {
883# if DEBUG
884 strcpy(buffer, SDDS_dataset->layout.s);
885# endif
886 groupName = SDDS_dataset->layout.s + 1;
887 if (!(ptr = strpbrk(SDDS_dataset->layout.s, " \t"))) {
888 SDDS_SetError("Unable to read layout---no groupname in namelist (SDDS_GZipReadLayout)");
889 return 0;
890 }
891 *ptr = 0;
892 switch (match_string(groupName, SDDS_command, SDDS_NUM_COMMANDS, EXACT_MATCH)) {
893 case SDDS_DESCRIPTION_COMMAND:
894 if (!SDDS_ProcessDescription(SDDS_dataset, ptr + 1)) {
895 gzclose(gzfp);
896 SDDS_SetError("Unable to process description (SDDS_GZipReadLayout)");
897 return (0);
898 }
899 break;
900 case SDDS_COLUMN_COMMAND:
901 if (!SDDS_ProcessColumnDefinition(SDDS_dataset, ptr + 1)) {
902 gzclose(gzfp);
903 SDDS_SetError("Unable to process column definition (SDDS_GZipReadLayout)");
904 return (0);
905 }
906 break;
907 case SDDS_PARAMETER_COMMAND:
908 if (!SDDS_ProcessParameterDefinition(SDDS_dataset, ptr + 1)) {
909 gzclose(gzfp);
910 SDDS_SetError("Unable to process parameter definition (SDDS_GZipReadLayout)");
911 return (0);
912 }
913 break;
914 case SDDS_ASSOCIATE_COMMAND:
915# if RW_ASSOCIATES != 0
916 if (!SDDS_ProcessAssociateDefinition(SDDS_dataset, ptr + 1)) {
917 gzclose(gzfp);
918 SDDS_SetError("Unable to process associate definition (SDDS_GZipReadLayout)");
919 return (0);
920 }
921# endif
922 break;
923 case SDDS_DATA_COMMAND:
924 if (!SDDS_ProcessDataMode(SDDS_dataset, ptr + 1)) {
925 gzclose(gzfp);
926 SDDS_SetError("Unable to process data mode (SDDS_GZipReadLayout)");
927 return (0);
928 }
929 if (SDDS_dataset->layout.data_command_seen) {
930 /* should never happen */
931 gzclose(gzfp);
932 SDDS_SetError("Unable to read layout--multiple data commands (SDDS_GZipReadLayout)");
933 return (0);
934 }
935 if (!SDDS_SaveLayout(SDDS_dataset)) {
936 SDDS_SetError("Unable to read layout--couldn't save layout (SDDS_GZipReadLayout)");
937 return (0);
938 }
939 SDDS_dataset->layout.data_command_seen = 1;
940 commentFlags = SDDS_GetSpecialCommentsModes(SDDS_dataset);
941 if ((commentFlags & SDDS_BIGENDIAN_SEEN) && (commentFlags & SDDS_LITTLEENDIAN_SEEN)) {
942 SDDS_SetError("Unable to read data as it says it is both big and little endian (SDDS_ReadLayout)");
943 return (0);
944 }
945 bigEndianMachine = SDDS_IsBigEndianMachine();
946 SDDS_dataset->swapByteOrder = SDDS_dataset->layout.byteOrderDeclared = 0;
947 SDDS_dataset->autoRecover = 0;
948 if ((commentFlags & SDDS_BIGENDIAN_SEEN) || (SDDS_dataset->layout.data_mode.endian == SDDS_BIGENDIAN)) {
949 SDDS_dataset->layout.byteOrderDeclared = SDDS_BIGENDIAN_SEEN;
950 if (!bigEndianMachine)
951 SDDS_dataset->swapByteOrder = 1;
952 }
953 if ((commentFlags & SDDS_LITTLEENDIAN_SEEN) || (SDDS_dataset->layout.data_mode.endian == SDDS_LITTLEENDIAN)) {
954 SDDS_dataset->layout.byteOrderDeclared = SDDS_LITTLEENDIAN_SEEN;
955 if (bigEndianMachine)
956 SDDS_dataset->swapByteOrder = 1;
957 }
958 if ((commentFlags & SDDS_FIXED_ROWCOUNT_SEEN) || (SDDS_dataset->layout.data_mode.fixed_row_count))
959 if (!SDDS_SetAutoReadRecovery(SDDS_dataset, SDDS_AUTOREADRECOVER))
960 return (0);
961 return (1);
962 case SDDS_INCLUDE_COMMAND:
963 if (!(fp1 = SDDS_ProcessIncludeCommand(SDDS_dataset, ptr + 1))) {
964 gzclose(gzfp);
965 SDDS_SetError("Unable to process include command (SDDS_GZipReadLayout)");
966 return (0);
967 }
968 SDDS_dataset->layout.depth += 1;
969 retval = SDDS_ReadLayout(SDDS_dataset, fp1);
970 SDDS_dataset->layout.depth -= 1;
971 fclose(fp1);
972 if (retval == 0) {
973 return (0);
974 }
975 if (SDDS_dataset->layout.data_command_seen) {
976 return (1);
977 }
978 break;
979 case SDDS_ARRAY_COMMAND:
980 if (!SDDS_ProcessArrayDefinition(SDDS_dataset, ptr + 1)) {
981 gzclose(gzfp);
982 SDDS_SetError("Unable to process array definition (SDDS_GZipReadLayout)");
983 return (0);
984 }
985 break;
986 default:
987 gzclose(gzfp);
988 sprintf(buffer, "Unknown layout entry %s given (SDDS_GZipReadLayout)", groupName);
989 SDDS_SetError(buffer);
990 return (0);
991 }
992 }
993 /* on recursive calls, it's okay to hit EOF */
994 if ((gzeof(gzfp) && SDDS_dataset->layout.depth != 0) || SDDS_dataset->layout.data_command_seen)
995 return (1);
996 return (0);
997}
998#endif
999
1000/**
1001 * Reads a page of an SDDS file. Usually called after SDDS_InitializeInput.
1002 *
1003 * @param SDDS_dataset Address of the SDDS_DATASET structure for the data set.
1004 * @return Page number on success, -1 if it is the end-of-file, 0 on error.
1005 */
1006int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset) {
1007#if SDDS_MPI_IO
1008 if (SDDS_dataset->parallel_io)
1009 return SDDS_MPI_ReadPage(SDDS_dataset);
1010#endif
1011 return SDDS_ReadPageSparse(SDDS_dataset, 0, 1, 0, 0);
1012}
1013
1014/**
1015 * Checks if the end of the SDDS dataset file has been reached.
1016 *
1017 * @param SDDS_dataset The SDDS dataset structure.
1018 * @return Returns 1 if the end of file has been reached, 0 if not, and 2 on error.
1019 */
1020int32_t SDDS_CheckEndOfFile(SDDS_DATASET *SDDS_dataset) {
1021 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_EndOfFile"))
1022 return (0);
1023 if (SDDS_dataset->layout.disconnected) {
1024 SDDS_SetError("Can't check status--file is disconnected (SDDS_EndOfFile)");
1025 return 2;
1026 }
1027#if defined(zLib)
1028 if (SDDS_dataset->layout.gzipFile) {
1029 if (!SDDS_dataset->layout.gzfp) {
1030 SDDS_SetError("Unable to check status--NULL file pointer (SDDS_EndOfFile)");
1031 return 2;
1032 }
1033 } else {
1034#endif
1035 if (SDDS_dataset->layout.lzmaFile) {
1036 if (!SDDS_dataset->layout.lzmafp) {
1037 SDDS_SetError("Unable to check status--NULL file pointer (SDDS_EndOfFile)");
1038 return 2;
1039 }
1040 } else {
1041 if (!SDDS_dataset->layout.fp) {
1042 SDDS_SetError("Unable to check status--NULL file pointer (SDDS_EndOfFile)");
1043 return 2;
1044 }
1045 }
1046#if defined(zLib)
1047 }
1048#endif
1049 if (SDDS_dataset->fBuffer.bufferSize && SDDS_dataset->fBuffer.bytesLeft) {
1050 return 0;
1051 }
1052
1053#if defined(zLib)
1054 if (SDDS_dataset->layout.gzipFile) {
1055 if (gzeof(SDDS_dataset->layout.gzfp))
1056 return 1;
1057 } else {
1058#endif
1059 if (SDDS_dataset->layout.lzmaFile) {
1060 if (lzma_eof(SDDS_dataset->layout.lzmafp))
1061 return 1;
1062 } else {
1063 if (feof(SDDS_dataset->layout.fp))
1064 return 1;
1065 }
1066#if defined(zLib)
1067 }
1068#endif
1069 return 0;
1070}
1071
1072/**
1073 * Reads a sparsed page of an SDDS file. Usually called after SDDS_InitializeInput.
1074 *
1075 * @param SDDS_dataset A pointer to an SDDS dataset.
1076 * @param mode Not used.
1077 * @param sparse_interval The column data can be sparsified over row intervals if this is greater than 1.
1078 * @param sparse_offset This is used to skip the initial rows of the column data.
1079 * @param sparse_statistics Not used.
1080 * @return Page number on success, -1 if it is the end-of-file, 0 on error.
1081 */
1082int32_t SDDS_ReadPageSparse(SDDS_DATASET *SDDS_dataset, uint32_t mode, int64_t sparse_interval, int64_t sparse_offset, int32_t sparse_statistics)
1083/* the mode argument is to support future expansion */
1084{
1085 int32_t retval;
1086 /* SDDS_LAYOUT layout_copy; */
1087
1088 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ReadPageSparse"))
1089 return (0);
1090 if (SDDS_dataset->layout.disconnected) {
1091 SDDS_SetError("Can't read page--file is disconnected (SDDS_ReadPageSparse)");
1092 return 0;
1093 }
1094#if defined(zLib)
1095 if (SDDS_dataset->layout.gzipFile) {
1096 if (!SDDS_dataset->layout.gzfp) {
1097 SDDS_SetError("Unable to read page--NULL file pointer (SDDS_ReadPageSparse)");
1098 return (0);
1099 }
1100 } else {
1101#endif
1102 if (SDDS_dataset->layout.lzmaFile) {
1103 if (!SDDS_dataset->layout.lzmafp) {
1104 SDDS_SetError("Unable to read page--NULL file pointer (SDDS_ReadPageSparse)");
1105 return (0);
1106 }
1107 } else {
1108 if (!SDDS_dataset->layout.fp) {
1109 SDDS_SetError("Unable to read page--NULL file pointer (SDDS_ReadPageSparse)");
1110 return (0);
1111 }
1112 }
1113#if defined(zLib)
1114 }
1115#endif
1116 if (SDDS_dataset->original_layout.data_mode.mode == SDDS_ASCII) {
1117 if ((retval = SDDS_ReadAsciiPage(SDDS_dataset, sparse_interval, sparse_offset, sparse_statistics)) < 1) {
1118 return (retval);
1119 }
1120 } else if (SDDS_dataset->original_layout.data_mode.mode == SDDS_BINARY) {
1121 if ((retval = SDDS_ReadBinaryPage(SDDS_dataset, sparse_interval, sparse_offset, sparse_statistics)) < 1) {
1122 return (retval);
1123 }
1124 } else {
1125 SDDS_SetError("Unable to read page--unrecognized data mode (SDDS_ReadPageSparse)");
1126 return (0);
1127 }
1128 if (!SDDS_dataset->layout.gzipFile && !SDDS_dataset->layout.lzmaFile && !SDDS_dataset->layout.popenUsed && SDDS_dataset->layout.filename && SDDS_dataset->pagecount_offset) {
1129 /* Data is not:
1130 1. from a gzip file
1131 2. from a file that is being internally decompressed by a command executed with popen()
1132 3. from a pipe set up externally (e.g., -pipe=in on commandline)
1133 and pagecount_offset has been allocate memory from SDDS_initializeInput()
1134 */
1135 if (SDDS_dataset->pagecount_offset[SDDS_dataset->pages_read] < SDDS_dataset->endOfFile_offset) {
1136 SDDS_dataset->pages_read++;
1137 if (!(SDDS_dataset->pagecount_offset = realloc(SDDS_dataset->pagecount_offset, sizeof(int64_t) * (SDDS_dataset->pages_read + 1)))) {
1138 SDDS_SetError("Unable to allocate memory for pagecount_offset (SDDS_ReadPageSparse)");
1139 exit(1);
1140 }
1141 SDDS_dataset->pagecount_offset[SDDS_dataset->pages_read] = ftell(SDDS_dataset->layout.fp);
1142 }
1143 } else {
1144 SDDS_dataset->pages_read++;
1145 }
1146 return (retval);
1147}
1148
1149/**
1150 * Reads the last specified number of rows from the SDDS dataset.
1151 *
1152 * @param SDDS_dataset The pointer to the SDDS dataset structure.
1153 * @param last_rows The number of rows to read from the end of the dataset.
1154 * @return Page number on success, -1 if it is the end-of-file, 0 on error.
1155 */
1156int32_t SDDS_ReadPageLastRows(SDDS_DATASET *SDDS_dataset, int64_t last_rows) {
1157 int32_t retval;
1158
1159 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ReadPageLastRows"))
1160 return (0);
1161 if (SDDS_dataset->layout.disconnected) {
1162 SDDS_SetError("Can't read page--file is disconnected (SDDS_ReadPageLastRows)");
1163 return 0;
1164 }
1165#if defined(zLib)
1166 if (SDDS_dataset->layout.gzipFile) {
1167 if (!SDDS_dataset->layout.gzfp) {
1168 SDDS_SetError("Unable to read page--NULL file pointer (SDDS_ReadPageLastRows)");
1169 return (0);
1170 }
1171 } else {
1172#endif
1173 if (SDDS_dataset->layout.lzmaFile) {
1174 if (!SDDS_dataset->layout.lzmafp) {
1175 SDDS_SetError("Unable to read page--NULL file pointer (SDDS_ReadPageLastRows)");
1176 return (0);
1177 }
1178 } else {
1179 if (!SDDS_dataset->layout.fp) {
1180 SDDS_SetError("Unable to read page--NULL file pointer (SDDS_ReadPageLastRows)");
1181 return (0);
1182 }
1183 }
1184#if defined(zLib)
1185 }
1186#endif
1187 if (SDDS_dataset->original_layout.data_mode.mode == SDDS_ASCII) {
1188 if ((retval = SDDS_ReadAsciiPageLastRows(SDDS_dataset, last_rows)) < 1) {
1189 return (retval);
1190 }
1191 } else if (SDDS_dataset->original_layout.data_mode.mode == SDDS_BINARY) {
1192 if ((retval = SDDS_ReadBinaryPageLastRows(SDDS_dataset, last_rows)) < 1) {
1193 return (retval);
1194 }
1195 } else {
1196 SDDS_SetError("Unable to read page--unrecognized data mode (SDDS_ReadPageLastRows)");
1197 return (0);
1198 }
1199 if (!SDDS_dataset->layout.gzipFile && !SDDS_dataset->layout.lzmaFile && !SDDS_dataset->layout.popenUsed && SDDS_dataset->layout.filename && SDDS_dataset->pagecount_offset) {
1200 /* Data is not:
1201 1. from a gzip file
1202 2. from a file that is being internally decompressed by a command executed with popen()
1203 3. from a pipe set up externally (e.g., -pipe=in on commandline)
1204 and pagecount_offset has been allocate memory from SDDS_initializeInput()
1205 */
1206 if (SDDS_dataset->pagecount_offset[SDDS_dataset->pages_read] < SDDS_dataset->endOfFile_offset) {
1207 SDDS_dataset->pages_read++;
1208 if (!(SDDS_dataset->pagecount_offset = realloc(SDDS_dataset->pagecount_offset, sizeof(int64_t) * (SDDS_dataset->pages_read + 1)))) {
1209 SDDS_SetError("Unable to allocate memory for pagecount_offset (SDDS_ReadPageLastRows)");
1210 exit(1);
1211 }
1212 SDDS_dataset->pagecount_offset[SDDS_dataset->pages_read] = ftell(SDDS_dataset->layout.fp);
1213 }
1214 } else {
1215 SDDS_dataset->pages_read++;
1216 }
1217 return (retval);
1218}
1219
1220/**
1221 * @brief Global variable to set a limit on the number of rows read.
1222 *
1223 * The default value is `INT64_MAX`, indicating no limit.
1224 */
1225static int64_t SDDS_RowLimit = INT64_MAX;
1226/**
1227 * Sets the row limit for the SDDS dataset.
1228 *
1229 * @param limit The maximum number of rows to read. If `limit <= 0`, the row limit is set to `INT64_MAX`.
1230 * @return The previous row limit value.
1231 */
1232int64_t SDDS_SetRowLimit(int64_t limit) {
1233 int64_t previous;
1234 previous = SDDS_RowLimit;
1235 if (limit <= 0)
1236 SDDS_RowLimit = INT64_MAX;
1237 else
1238 SDDS_RowLimit = limit;
1239 return previous;
1240}
1241
1242/**
1243 * Retrieves the current row limit for the SDDS dataset.
1244 *
1245 * @return The current row limit.
1246 */
1248 return SDDS_RowLimit;
1249}
1250
1251/**
1252 * @brief Sets the current page of the SDDS dataset to the specified page number.
1253 *
1254 * This function is used to navigate to a specific page of the SDDS dataset. It is only
1255 * supported for non-zip files and does not work for pipe input.
1256 *
1257 * @param SDDS_dataset The SDDS dataset to operate on.
1258 * @param page_number The page number to navigate to.
1259 * @return Returns 1 on success, 0 on failure.
1260 */
1261int32_t SDDS_GotoPage(SDDS_DATASET *SDDS_dataset, int32_t page_number) {
1262 int64_t offset;
1263
1264 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GotoPage"))
1265 return (0);
1266 if (SDDS_dataset->layout.disconnected) {
1267 SDDS_SetError("Can't go to page--file is disconnected (SDDS_GotoPage)");
1268 return 0;
1269 }
1270 if (SDDS_dataset->layout.popenUsed || !SDDS_dataset->layout.filename) {
1271 SDDS_SetError("Can't go to page of pipe is used (SDDS_GotoPage)");
1272 return 0;
1273 }
1274#if defined(zLib)
1275 if (SDDS_dataset->layout.gzipFile) {
1276 SDDS_SetError("Can not go to page of a gzip file (SDDS_GotoPage)");
1277 return (0);
1278 } else {
1279#endif
1280 if (SDDS_dataset->layout.lzmaFile) {
1281 SDDS_SetError("Can not go to page of an .lzma or .xz file (SDDS_GotoPage)");
1282 return (0);
1283 } else {
1284 if (!SDDS_dataset->layout.fp) {
1285 SDDS_SetError("Unable to go to page--NULL file pointer (SDDS_GotoPage)");
1286 return (0);
1287 }
1288 }
1289#if defined(zLib)
1290 }
1291#endif
1292 if (!SDDS_dataset->layout.filename) {
1293 SDDS_SetError("Can't go to page--NULL filename pointer (SDDS_GotoPage)");
1294 return 0;
1295 }
1296 if (SDDS_dataset->mode != SDDS_READMODE) {
1297 SDDS_SetError("Can't go to page--file mode has to be reading mode (SDDS_GotoPage)");
1298 return 0;
1299 }
1300 if (SDDS_dataset->fBuffer.bufferSize) {
1301 SDDS_SetError("Can't go to page--file buffering is turned on (SDDS_GotoPage)");
1302 return 0;
1303 }
1304 if (page_number < 1) {
1305 SDDS_SetError("The page_number can not be less than 1 (SDDS_GotoPage)");
1306 return (0);
1307 }
1308 if (page_number > SDDS_dataset->pages_read) {
1309 offset = SDDS_dataset->pagecount_offset[SDDS_dataset->pages_read] - ftell(SDDS_dataset->layout.fp);
1310 fseek(SDDS_dataset->layout.fp, offset, 1);
1311 SDDS_dataset->page_number = SDDS_dataset->pages_read;
1312 while (SDDS_dataset->pages_read < page_number) {
1313 if (SDDS_ReadPageSparse(SDDS_dataset, 0, 10000, 0, 0) <= 0) {
1314 SDDS_SetError("The page_number is greater than the total pages (SDDS_GotoPage)");
1315 return (0);
1316 }
1317 }
1318 } else {
1319 offset = SDDS_dataset->pagecount_offset[page_number - 1] - ftell(SDDS_dataset->layout.fp);
1320 fseek(SDDS_dataset->layout.fp, offset, 1); /*seek to the position from current offset */
1321 SDDS_dataset->page_number = page_number - 1;
1322 }
1323 return 1;
1324}
1325
1326/**
1327 * @brief Global variable to set the terminate mode for the SDDS dataset.
1328 *
1329 * Default value is 0.
1330 */
1331static int32_t terminateMode = 0;
1332
1333/**
1334 * Sets the terminate mode for the SDDS dataset.
1335 *
1336 * @param mode The terminate mode to set.
1337 */
1338void SDDS_SetTerminateMode(uint32_t mode) {
1339 terminateMode = mode;
1340}
1341
1342/**
1343 * Sets the column memory mode for the SDDS dataset.
1344 *
1345 * @param SDDS_dataset The SDDS dataset to operate on.
1346 * @param mode The column memory mode to set.
1347 */
1348void SDDS_SetColumnMemoryMode(SDDS_DATASET *SDDS_dataset, uint32_t mode) {
1349 SDDS_dataset->layout.data_mode.column_memory_mode = mode;
1350}
1351
1352/**
1353 * Retrieves the current column memory mode for the SDDS dataset.
1354 *
1355 * @param SDDS_dataset The SDDS dataset to query.
1356 * @return The current column memory mode.
1357 */
1359 return (SDDS_dataset->layout.data_mode.column_memory_mode);
1360}
1361
1362#include <signal.h>
1363
1364/**
1365 * Frees all allocated string data in the SDDS dataset.
1366 *
1367 * This function frees any strings allocated for parameters, arrays, and columns
1368 * within the SDDS dataset. It is typically called during termination to clean up
1369 * allocated memory.
1370 *
1371 * @param SDDS_dataset The SDDS dataset to free string data from.
1372 * @return Returns 1 on success, 0 on failure.
1373 */
1374int32_t SDDS_FreeStringData(SDDS_DATASET *SDDS_dataset) {
1375 SDDS_LAYOUT *layout;
1376 char **ptr;
1377 int64_t i, j;
1378 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_Terminate"))
1379 return (0);
1380 layout = &SDDS_dataset->original_layout;
1381
1382 if (SDDS_dataset->parameter) {
1383 for (i = 0; i < layout->n_parameters; i++) {
1384 if (layout->parameter_definition[i].type == SDDS_STRING) {
1385 free(*(char **)(SDDS_dataset->parameter[i]));
1386 *(char **)(SDDS_dataset->parameter[i]) = NULL;
1387 }
1388 }
1389 }
1390 if (SDDS_dataset->array) {
1391 for (i = 0; i < layout->n_arrays; i++) {
1392 if (layout->array_definition[i].type == SDDS_STRING) {
1393 for (j = 0; j < SDDS_dataset->array[i].elements; j++)
1394 if (((char **)SDDS_dataset->array[i].data)[j]) {
1395 free(((char **)SDDS_dataset->array[i].data)[j]);
1396 ((char **)SDDS_dataset->array[i].data)[j] = NULL;
1397 }
1398 }
1399 }
1400 }
1401 if (SDDS_dataset->data) {
1402 for (i = 0; i < layout->n_columns; i++)
1403 if (SDDS_dataset->data[i]) {
1404 if (layout->column_definition[i].type == SDDS_STRING) {
1405 ptr = (char **)SDDS_dataset->data[i];
1406 for (j = 0; j < SDDS_dataset->n_rows_allocated; j++, ptr++)
1407 if (*ptr) {
1408 free(*ptr);
1409 *ptr = NULL;
1410 }
1411 }
1412 }
1413 }
1414 return (1);
1415}
1416
1417/**
1418 * Frees the strings in the current table of the SDDS dataset.
1419 *
1420 * This function frees any strings stored in the data columns of the current table.
1421 * It does not free strings from parameters or arrays.
1422 *
1423 * @param SDDS_dataset The SDDS dataset to free table strings from.
1424 */
1426 int64_t i, j;
1427 char **ptr;
1428 /* free stored strings */
1429 if (!SDDS_dataset)
1430 return;
1431 for (i = 0; i < SDDS_dataset->layout.n_columns; i++)
1432 if (SDDS_dataset->layout.column_definition[i].type == SDDS_STRING) {
1433 ptr = (char **)SDDS_dataset->data[i];
1434 for (j = 0; j < SDDS_dataset->n_rows; j++, ptr++)
1435 if (*ptr) {
1436 free(*ptr);
1437 *ptr = NULL;
1438 }
1439 }
1440}
1441
1442/**
1443 * Closes an SDDS file and frees the related memory.
1444 *
1445 * @param SDDS_dataset A pointer to an SDDS dataset.
1446 * @return 1 on success, 0 on error.
1447 */
1448int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset) {
1449 SDDS_LAYOUT *layout;
1450 char **ptr;
1451 int64_t i, j;
1452 FILE *fp;
1453 char termBuffer[16384];
1454#if SDDS_MPI_IO
1455 if (SDDS_dataset->parallel_io)
1456 return SDDS_MPI_Terminate(SDDS_dataset);
1457#endif
1458 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_Terminate"))
1459 return (0);
1460 layout = &SDDS_dataset->original_layout;
1461
1462 fp = SDDS_dataset->layout.fp;
1463#if defined(zLib)
1464 if (SDDS_dataset->layout.gzipFile) {
1465 if (SDDS_dataset->layout.gzfp && layout->filename) {
1466 if ((SDDS_dataset->writing_page) && (SDDS_dataset->layout.data_mode.fixed_row_count)) {
1467 if (!SDDS_UpdateRowCount(SDDS_dataset))
1468 return (0);
1469 }
1470 gzclose(SDDS_dataset->layout.gzfp);
1471 }
1472 } else {
1473#endif
1474 if (SDDS_dataset->layout.lzmaFile) {
1475 if (SDDS_dataset->layout.lzmafp && layout->filename) {
1476 if ((SDDS_dataset->writing_page) && (SDDS_dataset->layout.data_mode.fixed_row_count)) {
1477 if (!SDDS_UpdateRowCount(SDDS_dataset))
1478 return (0);
1479 }
1480 lzma_close(SDDS_dataset->layout.lzmafp);
1481 }
1482 } else {
1483 if (fp && layout->filename) {
1484 if ((SDDS_dataset->writing_page) && (SDDS_dataset->layout.data_mode.fixed_row_count)) {
1485 if (!SDDS_UpdateRowCount(SDDS_dataset))
1486 return (0);
1487 }
1488 if (layout->popenUsed) {
1489 while (fread(termBuffer, sizeof(*termBuffer), 16384, fp)) {
1490 }
1491#if defined(vxWorks)
1492 fprintf(stderr, "pclose is not supported in vxWorks\n");
1493 exit(1);
1494#else
1495 pclose(fp);
1496#endif
1497 } else {
1498 fclose(fp);
1499 }
1500 }
1501 }
1502#if defined(zLib)
1503 }
1504#endif
1505
1506#if DEBUG
1507 fprintf(stderr, "Freeing data for file %s\n", SDDS_dataset->layout.filename ? SDDS_dataset->layout.filename : "NULL");
1508#endif
1509
1510 if (SDDS_dataset->pagecount_offset)
1511 free(SDDS_dataset->pagecount_offset);
1512 if (SDDS_dataset->row_flag)
1513 free(SDDS_dataset->row_flag);
1514 if (SDDS_dataset->column_order)
1515 free(SDDS_dataset->column_order);
1516 if (SDDS_dataset->column_flag)
1517 free(SDDS_dataset->column_flag);
1518 if (SDDS_dataset->fBuffer.buffer)
1519 free(SDDS_dataset->fBuffer.buffer);
1520#if DEBUG
1521 fprintf(stderr, "freeing parameter data...\n");
1522#endif
1523 if (SDDS_dataset->parameter) {
1524 for (i = 0; i < layout->n_parameters; i++) {
1525 if (layout->parameter_definition[i].type == SDDS_STRING && *(char **)(SDDS_dataset->parameter[i]))
1526 free(*(char **)(SDDS_dataset->parameter[i]));
1527 if (SDDS_dataset->parameter[i])
1528 free(SDDS_dataset->parameter[i]);
1529 }
1530 free(SDDS_dataset->parameter);
1531 }
1532#if DEBUG
1533 fprintf(stderr, "freeing array data...\n");
1534#endif
1535 if (SDDS_dataset->array) {
1536 for (i = 0; i < layout->n_arrays; i++) {
1537 if (layout->array_definition[i].type == SDDS_STRING && !(terminateMode & TERMINATE_DONT_FREE_ARRAY_STRINGS)) {
1538 for (j = 0; j < SDDS_dataset->array[i].elements; j++)
1539 if (((char **)SDDS_dataset->array[i].data)[j])
1540 free(((char **)SDDS_dataset->array[i].data)[j]);
1541 }
1542 /*
1543 if (SDDS_dataset->array[i].definition->type==SDDS_STRING &&
1544 !(terminateMode&TERMINATE_DONT_FREE_ARRAY_STRINGS)) {
1545 for (j=0; j<SDDS_dataset->array[i].elements; j++)
1546 if (((char**)SDDS_dataset->array[i].data)[j])
1547 free(((char**)SDDS_dataset->array[i].data)[j]);
1548 }
1549 */
1550 if (SDDS_dataset->array[i].data)
1551 free(SDDS_dataset->array[i].data);
1552 /* should free the subpointers too, but it would be a lot of trouble for little benefit: */
1553 if (SDDS_dataset->array[i].pointer && SDDS_dataset->array[i].definition->dimensions != 1)
1554 free(SDDS_dataset->array[i].pointer);
1555 if (SDDS_dataset->array[i].dimension)
1556 free(SDDS_dataset->array[i].dimension);
1557 /* don't touch this--it's done below */
1558 if (SDDS_dataset->array[i].definition && SDDS_dataset->array[i].definition->name) {
1559 if (SDDS_dataset->array[i].definition->name != layout->array_definition[i].name)
1560 SDDS_FreeArrayDefinition(SDDS_dataset->array[i].definition);
1561 }
1562 SDDS_dataset->array[i].definition = NULL;
1563 }
1564 free(SDDS_dataset->array);
1565 }
1566#if DEBUG
1567 fprintf(stderr, "freeing tabular data...\n");
1568#endif
1569 if (SDDS_dataset->data) {
1570 for (i = 0; i < layout->n_columns; i++)
1571 if (SDDS_dataset->data[i]) {
1572 if ((SDDS_dataset->column_track_memory == NULL) || (SDDS_dataset->column_track_memory[i])) {
1573 if (layout->column_definition[i].type == SDDS_STRING && !(terminateMode & TERMINATE_DONT_FREE_TABLE_STRINGS)) {
1574 ptr = (char **)SDDS_dataset->data[i];
1575 for (j = 0; j < SDDS_dataset->n_rows_allocated; j++, ptr++)
1576 if (*ptr)
1577 free(*ptr);
1578 }
1579 free(SDDS_dataset->data[i]);
1580 }
1581 }
1582 free(SDDS_dataset->data);
1583 }
1584 if (SDDS_dataset->column_track_memory)
1585 free(SDDS_dataset->column_track_memory);
1586#if DEBUG
1587 fprintf(stderr, "freeing layout data...\n");
1588#endif
1589 if (layout->description)
1590 free(layout->description);
1591 if (layout->contents == (&SDDS_dataset->layout)->contents)
1592 (&SDDS_dataset->layout)->contents = NULL;
1593 if (layout->contents)
1594 free(layout->contents);
1595 if (layout->filename)
1596 free(layout->filename);
1597 if (layout->column_definition) {
1598 for (i = 0; i < layout->n_columns; i++) {
1599 if (layout->column_index[i])
1600 free(layout->column_index[i]);
1601 if (layout->column_definition[i].name)
1602 free(layout->column_definition[i].name);
1603 if (layout->column_definition[i].symbol)
1604 free(layout->column_definition[i].symbol);
1605 if (layout->column_definition[i].units)
1606 free(layout->column_definition[i].units);
1607 if (layout->column_definition[i].description)
1608 free(layout->column_definition[i].description);
1609 if (layout->column_definition[i].format_string)
1610 free(layout->column_definition[i].format_string);
1611 }
1612 free(layout->column_definition);
1613 free(layout->column_index);
1614 }
1615 if (layout->parameter_definition) {
1616 for (i = 0; i < layout->n_parameters; i++) {
1617 if (layout->parameter_index[i])
1618 free(layout->parameter_index[i]);
1619 if (layout->parameter_definition[i].name)
1620 free(layout->parameter_definition[i].name);
1621 if (layout->parameter_definition[i].symbol)
1622 free(layout->parameter_definition[i].symbol);
1623 if (layout->parameter_definition[i].units)
1624 free(layout->parameter_definition[i].units);
1625 if (layout->parameter_definition[i].description)
1626 free(layout->parameter_definition[i].description);
1627 if (layout->parameter_definition[i].format_string)
1628 free(layout->parameter_definition[i].format_string);
1629 if (layout->parameter_definition[i].fixed_value)
1630 free(layout->parameter_definition[i].fixed_value);
1631 }
1632 free(layout->parameter_definition);
1633 free(layout->parameter_index);
1634 }
1635 if (layout->array_definition) {
1636 for (i = 0; i < layout->n_arrays; i++) {
1637 if (layout->array_index[i])
1638 free(layout->array_index[i]);
1639 if (layout->array_definition[i].name)
1640 free(layout->array_definition[i].name);
1641 if (layout->array_definition[i].symbol)
1642 free(layout->array_definition[i].symbol);
1643 if (layout->array_definition[i].units)
1644 free(layout->array_definition[i].units);
1645 if (layout->array_definition[i].description)
1646 free(layout->array_definition[i].description);
1647 if (layout->array_definition[i].format_string)
1648 free(layout->array_definition[i].format_string);
1649 if (layout->array_definition[i].group_name)
1650 free(layout->array_definition[i].group_name);
1651 }
1652 free(layout->array_definition);
1653 free(layout->array_index);
1654 }
1655 if (layout->associate_definition) {
1656 for (i = 0; i < layout->n_associates; i++) {
1657 if (layout->associate_definition[i].name)
1658 free(layout->associate_definition[i].name);
1659 if (layout->associate_definition[i].filename)
1660 free(layout->associate_definition[i].filename);
1661 if (layout->associate_definition[i].path)
1662 free(layout->associate_definition[i].path);
1663 if (layout->associate_definition[i].description)
1664 free(layout->associate_definition[i].description);
1665 if (layout->associate_definition[i].contents)
1666 free(layout->associate_definition[i].contents);
1667 }
1668 free(layout->associate_definition);
1669 }
1670 SDDS_ZeroMemory(&SDDS_dataset->original_layout, sizeof(SDDS_LAYOUT));
1671 layout = &SDDS_dataset->layout;
1672 if (layout->contents)
1673 free(layout->contents);
1674 if (layout->column_definition)
1675 free(layout->column_definition);
1676 if (layout->array_definition)
1677 free(layout->array_definition);
1678 if (layout->associate_definition)
1679 free(layout->associate_definition);
1680 if (layout->parameter_definition)
1681 free(layout->parameter_definition);
1682 if (layout->column_index)
1683 free(layout->column_index);
1684 if (layout->parameter_index)
1685 free(layout->parameter_index);
1686 if (layout->array_index)
1687 free(layout->array_index);
1688 SDDS_ZeroMemory(&SDDS_dataset->layout, sizeof(SDDS_LAYOUT));
1689 SDDS_ZeroMemory(SDDS_dataset, sizeof(SDDS_DATASET));
1690#if DEBUG
1691 fprintf(stderr, "done\n");
1692#endif
1693 return (1);
1694}
1695
1696/**
1697 * Updates the row count in the SDDS file for fixed row count mode.
1698 *
1699 * @param SDDS_dataset The SDDS dataset to update.
1700 * @return 1 on success, 0 on error.
1701 */
1702int32_t SDDS_UpdateRowCount(SDDS_DATASET *SDDS_dataset) {
1703 FILE *fp;
1704 SDDS_FILEBUFFER *fBuffer;
1705 int64_t offset, rows;
1706 int32_t rows32;
1707 char *outputEndianess = NULL;
1708
1709 if ((SDDS_dataset->layout.gzipFile) || (SDDS_dataset->layout.lzmaFile))
1710 return (1);
1711 if (!(fp = SDDS_dataset->layout.fp)) {
1712 SDDS_SetError("Unable to update page--file pointer is NULL (SDDS_UpdateRowCount)");
1713 return (0);
1714 }
1715#if DEBUG
1716 fprintf(stderr, "Updating rowcount in file %s with pointer %p\n", SDDS_dataset->layout.filename ? SDDS_dataset->layout.filename : "NULL", fp);
1717#endif
1718 fBuffer = &SDDS_dataset->fBuffer;
1719 if (!SDDS_FlushBuffer(fp, fBuffer)) {
1720 SDDS_SetError("Unable to write page--buffer flushing problem (SDDS_UpdateRowCount)");
1721 return (0);
1722 }
1723 offset = ftell(fp);
1724 if (SDDS_fseek(fp, SDDS_dataset->rowcount_offset, 0) == -1) {
1725 SDDS_SetError("Unable to update page--failure doing fseek (SDDS_UpdateRowCount)");
1726 return (0);
1727 }
1728 rows = SDDS_CountRowsOfInterest(SDDS_dataset) + SDDS_dataset->first_row_in_mem;
1729 if (SDDS_dataset->layout.data_mode.mode == SDDS_ASCII) {
1730 fprintf(fp, "%20" PRId64 "\n", rows);
1731 } else {
1732
1733 if (rows > INT32_MAX) {
1734 // Don't go over this limit because it has a different format
1735 SDDS_SetError("Unable to update page--failure writing number of rows (SDDS_UpdateRowCount)");
1736 return (0);
1737 }
1738 rows32 = (int32_t)rows;
1739 if ((outputEndianess = getenv("SDDS_OUTPUT_ENDIANESS"))) {
1740 if (((strncmp(outputEndianess, "big", 3) == 0) && (SDDS_IsBigEndianMachine() == 0)) || ((strncmp(outputEndianess, "little", 6) == 0) && (SDDS_IsBigEndianMachine() == 1)))
1741 SDDS_SwapLong(&rows32);
1742 }
1743 if (fwrite(&rows32, sizeof(rows32), 1, fp) != 1) {
1744 SDDS_SetError("Unable to update page--failure writing number of rows (SDDS_UpdateRowCount)");
1745 return (0);
1746 }
1747 }
1748 if (SDDS_fseek(fp, offset, 0) == -1) {
1749 SDDS_SetError("Unable to update page--failure doing fseek to end of page (SDDS_UpdateRowCount)");
1750 return (0);
1751 }
1752 return (1);
1753}
1754
1755/**
1756 * Sets the auto-read recovery mode for the SDDS dataset.
1757 *
1758 * @param SDDS_dataset The SDDS dataset to modify.
1759 * @param mode The mode to set (SDDS_AUTOREADRECOVER or SDDS_NOAUTOREADRECOVER).
1760 * @return 1 on success, 0 on error.
1761 */
1762int32_t SDDS_SetAutoReadRecovery(SDDS_DATASET *SDDS_dataset, uint32_t mode) {
1763 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetAutoReadRecovery"))
1764 return 0;
1765 if (mode & SDDS_AUTOREADRECOVER) {
1766 SDDS_dataset->autoRecover = 1;
1767 } else if (mode & SDDS_NOAUTOREADRECOVER) {
1768 SDDS_dataset->autoRecover = 0;
1769 } else {
1770 SDDS_SetError("Invalid Auto Read Recovery mode (SDDS_SetAutoReadRecovery).");
1771 return 0;
1772 }
1773 return 1;
1774}
1775
1776/**
1777 * Initializes the SDDS_DATASET structure for input from the search path.
1778 *
1779 * The search path is defined by calling `setSearchPath`. This function attempts to find the file
1780 * in the search path and initializes the SDDS dataset for input.
1781 *
1782 * @param SDDSin The SDDS_DATASET structure to be initialized.
1783 * @param file The name of the file to be opened for input.
1784 * @return 1 on success, 0 on failure.
1785 */
1787 char *filename;
1788 int32_t value;
1789 if (!(filename = findFileInSearchPath(file))) {
1790 char *s;
1791 if (!(s = SDDS_Malloc(sizeof(*s) * (strlen(file) + 100))))
1792 SDDS_SetError("file does not exist in search path (InitializeInputFromSearchPath)");
1793 else {
1794 sprintf(s, "file %s does not exist in search path (InitializeInputFromSearchPath)", file);
1795 SDDS_SetError(s);
1796 free(s);
1797 }
1798 return 0;
1799 }
1800 value = SDDS_InitializeInput(SDDSin, filename);
1801 free(filename);
1802 return value;
1803}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_ReadAsciiPageLastRows(SDDS_DATASET *SDDS_dataset, int64_t last_rows)
Reads the last specified number of rows from an ASCII page of an SDDS dataset.
int32_t SDDS_ReadAsciiPage(SDDS_DATASET *SDDS_dataset, int64_t sparse_interval, int64_t sparse_offset, int32_t sparse_statistics)
Reads the next SDDS ASCII page into memory with optional data sparsity and statistics.
int32_t SDDS_FlushBuffer(FILE *fp, SDDS_FILEBUFFER *fBuffer)
int32_t SDDS_ReadBinaryPage(SDDS_DATASET *SDDS_dataset, int64_t sparse_interval, int64_t sparse_offset, int32_t sparse_statistics)
Reads a binary page from an SDDS dataset.
void SDDS_SwapLong(int32_t *data)
Swaps the endianness of a 32-bit integer.
int32_t SDDS_fseek(FILE *fp, int64_t offset, int32_t dir)
Sets the file position indicator for a given file stream with retry logic.
int32_t SDDS_ReadBinaryPageLastRows(SDDS_DATASET *SDDS_dataset, int64_t last_rows)
Reads the last specified number of rows from a binary page of an SDDS dataset.
void SDDS_DeferSavingLayout(SDDS_DATASET *SDDS_dataset, int32_t mode)
Definition SDDS_copy.c:603
int32_t SDDS_SaveLayout(SDDS_DATASET *SDDS_dataset)
Definition SDDS_copy.c:615
char * SDDS_command[SDDS_NUM_COMMANDS]
Array of supported SDDS command names.
Definition SDDS_data.c:81
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_SetAutoReadRecovery(SDDS_DATASET *SDDS_dataset, uint32_t mode)
int32_t SDDS_ReadPageLastRows(SDDS_DATASET *SDDS_dataset, int64_t last_rows)
int64_t SDDS_SetRowLimit(int64_t limit)
int32_t SDDS_GetColumnMemoryMode(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_UpdateRowCount(SDDS_DATASET *SDDS_dataset)
void SDDS_SetTerminateMode(uint32_t mode)
int32_t SDDS_ReadLayout(SDDS_DATASET *SDDS_dataset, FILE *fp)
Definition SDDS_input.c:517
int64_t SDDS_GetRowLimit()
int32_t SDDS_ReadPageSparse(SDDS_DATASET *SDDS_dataset, uint32_t mode, int64_t sparse_interval, int64_t sparse_offset, int32_t sparse_statistics)
int32_t SDDS_FreeStringData(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_InitializeInputFromSearchPath(SDDS_DATASET *SDDSin, char *file)
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
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_GetNamelist(SDDS_DATASET *SDDS_dataset, char *buffer, int32_t buflen, FILE *fp)
Reads a namelist from a file into a buffer.
Definition SDDS_input.c:248
int32_t SDDS_InitializeHeaderlessInput(SDDS_DATASET *SDDS_dataset, char *filename)
Initializes the SDDS dataset for headerless input.
Definition SDDS_input.c:175
static int32_t terminateMode
Global variable to set the terminate mode for the SDDS dataset.
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
void SDDS_FreeTableStrings(SDDS_DATASET *SDDS_dataset)
static int64_t SDDS_RowLimit
Global variable to set a limit on the number of rows read.
int32_t SDDS_LZMAReadLayout(SDDS_DATASET *SDDS_dataset, struct lzmafile *lzmafp)
Definition SDDS_input.c:680
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_GotoPage(SDDS_DATASET *SDDS_dataset, int32_t page_number)
Sets the current page of the SDDS dataset to the specified page number.
int32_t SDDS_GetLZMANamelist(SDDS_DATASET *SDDS_dataset, char *buffer, int32_t buflen, struct lzmafile *lzmafp)
Reads a namelist from an LZMA-compressed file into a buffer.
Definition SDDS_input.c:344
int32_t SDDS_CheckEndOfFile(SDDS_DATASET *SDDS_dataset)
void SDDS_SetColumnMemoryMode(SDDS_DATASET *SDDS_dataset, uint32_t mode)
Internal definitions and function declarations for SDDS with LZMA support.
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_ProcessAssociateDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Process the associate definition section of the SDDS dataset.
char * fgetsLZMASkipComments(SDDS_DATASET *SDDS_dataset, char *s, int32_t slen, struct lzmafile *lzmafp, char skip_char)
Reads a line from a LZMA-compressed file while skipping comment lines.
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.
uint32_t SDDS_GetSpecialCommentsModes(SDDS_DATASET *SDDS_dataset)
Retrieves the current special comments modes set in the SDDS dataset.
int32_t SDDS_ProcessDescription(SDDS_DATASET *SDDS_dataset, char *s)
Process the description section of the SDDS dataset.
void SDDS_ResetSpecialCommentsModes(SDDS_DATASET *SDDS_dataset)
Resets the special comments modes in the SDDS dataset.
int32_t SDDS_ProcessColumnDefinition(SDDS_DATASET *SDDS_dataset, char *s)
Process the column definition section of the 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_ZeroMemory(void *mem, int64_t n_bytes)
Sets a block of memory to zero.
int32_t SDDS_FreeArrayDefinition(ARRAY_DEFINITION *source)
Frees memory allocated for an array definition.
char * fgetsSkipComments(SDDS_DATASET *SDDS_dataset, char *s, int32_t slen, FILE *fp, char skip_char)
Reads a line from a file while skipping comment lines.
int32_t SDDS_SetMemory(void *mem, int64_t n_elements, int32_t data_type,...)
Initializes a memory block with a sequence of values based on a specified data type.
int32_t SDDS_CheckDataset(SDDS_DATASET *SDDS_dataset, const char *caller)
Validates the SDDS dataset pointer.
Definition SDDS_utils.c:552
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:639
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
int32_t SDDS_IsBigEndianMachine()
Determines whether the current machine uses big-endian byte ordering.
int32_t SDDS_MPI_ReadPage(SDDS_DATASET *SDDS_dataset)
Reads a page from an SDDS dataset using MPI.
int32_t SDDS_MPI_Terminate(SDDS_DATASET *SDDS_dataset)
Terminates the SDDS dataset by freeing all allocated resources and closing MPI files.
#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