SDDSlib
Loading...
Searching...
No Matches
SDDS_output.c
Go to the documentation of this file.
1/**
2 * @file SDDS_output.c
3 * @brief This file contains the implementation of the SDDS output routines.
4 *
5 * This file provides functions for outputting data in the
6 * Self-Describing Data Sets (SDDS) format. It includes functions for
7 * creating and writing SDDS files, as well as functions for defining
8 * and appending data to the SDDS files.
9 *
10 * @copyright
11 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
12 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
13 *
14 * @license
15 * This file is distributed under the terms of the Software License Agreement
16 * found in the file LICENSE included with this distribution.
17 *
18 * @author M. Borland, C. Saunders, R. Soliday, H. Shang
19 */
20
21#include "SDDS.h"
22#include "SDDS_internal.h"
23#include "mdb.h"
24#include <ctype.h>
25
26#if defined(_WIN32)
27# include <fcntl.h>
28# include <io.h>
29# if defined(__BORLANDC__)
30# define _setmode(handle, amode) setmode(handle, amode)
31# endif
32#else
33# include <unistd.h>
34#endif
35
36#if SDDS_VERSION != 5
37# error "SDDS_VERSION does not match version of this file"
38#endif
39
40#undef DEBUG
41
42/* Allows "temporarily" closing a file. Use SDDS_ReconnectFile() to open it
43 * again in the same position. Updates the present page and flushes the
44 * table.
45 */
46
47#if SDDS_MPI_IO
48int32_t SDDS_MPI_DisconnectFile(SDDS_DATASET *SDDS_dataset);
49int32_t SDDS_MPI_ReconnectFile(SDDS_DATASET *SDDS_dataset);
50#endif
51
52/**
53 * @brief Disconnects the SDDS dataset from its associated file.
54 *
55 * This function terminates the connection between the SDDS dataset and the file it is currently linked to. It ensures that all pending data is flushed to the file, closes the file handle, and updates the dataset's internal state to reflect that it is no longer connected to any file.
56 *
57 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure to be disconnected.
58 *
59 * @return
60 * - @c 1 on successful disconnection.
61 * - @c 0 if an error occurred during disconnection. In this case, an error message is set internally.
62 *
63 * @note
64 * - If the dataset is already disconnected, this function will return an error.
65 * - This function is not thread-safe if the dataset is being accessed concurrently.
66 *
67 * @warning
68 * - Ensure that no further operations are performed on the dataset after disconnection unless it is reconnected.
69 */
70int32_t SDDS_DisconnectFile(SDDS_DATASET *SDDS_dataset) {
71#if SDDS_MPI_IO
72 if (SDDS_dataset->parallel_io)
73 return SDDS_MPI_DisconnectFile(SDDS_dataset);
74#endif
75 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DisconnectFile"))
76 return 0;
77 if (!SDDS_dataset->layout.filename) {
78 SDDS_SetError("Can't disconnect file. No filename given. (SDDS_DisconnectFile)");
79 return 0;
80 }
81 if (SDDS_dataset->layout.gzipFile) {
82 SDDS_SetError("Can't disconnect file because it is a gzip file. (SDDS_DisconnectFile)");
83 return 0;
84 }
85 if (SDDS_dataset->layout.lzmaFile) {
86 SDDS_SetError("Can't disconnect file because it is a lzma or xz file. (SDDS_DisconnectFile)");
87 return 0;
88 }
89 if (SDDS_dataset->layout.disconnected) {
90 SDDS_SetError("Can't disconnect file. Already disconnected. (SDDS_DisconnectFile)");
91 return 0;
92 }
93 if (SDDS_dataset->page_started && !SDDS_UpdatePage(SDDS_dataset, FLUSH_TABLE)) {
94 SDDS_SetError("Can't disconnect file. Problem updating page. (SDDS_DisconnectFile)");
95 return 0;
96 }
97 if (fclose(SDDS_dataset->layout.fp)) {
98 SDDS_SetError("Can't disconnect file. Problem closing file. (SDDS_DisconnectFile)");
99 return 0;
100 }
101 SDDS_dataset->layout.disconnected = 1;
102 return 1;
103}
104
105/**
106 * @brief Reconnects the SDDS dataset to its previously associated file.
107 *
108 * This function re-establishes the connection between the SDDS dataset and the file it was previously linked to before being disconnected. It opens the file in read/write mode, seeks to the appropriate position, and updates the dataset's internal state to reflect that it is connected.
109 *
110 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure to be reconnected.
111 *
112 * @return
113 * - @c 1 on successful reconnection.
114 * - @c 0 if an error occurred during reconnection. In this case, an error message is set internally.
115 *
116 * @pre
117 * - The dataset must have been previously disconnected using SDDS_DisconnectFile.
118 * - The dataset must have a valid filename set.
119 *
120 * @note
121 * - Reconnection will fail if the file is not accessible or if the dataset was not properly disconnected.
122 *
123 * @warning
124 * - Ensure that the file has not been modified externally in a way that could disrupt the dataset's state.
125 */
126int32_t SDDS_ReconnectFile(SDDS_DATASET *SDDS_dataset) {
127#if SDDS_MPI_IO
128 if (SDDS_dataset->parallel_io)
129 return SDDS_MPI_ReconnectFile(SDDS_dataset);
130#endif
131 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ReconnectFile"))
132 return 0;
133 if (!SDDS_dataset->layout.disconnected || !SDDS_dataset->layout.filename) {
134 SDDS_SetError("Can't reconnect file. Not disconnected or missing filename. (SDDS_ReconnectFile)");
135 return 0;
136 }
137 if (!(SDDS_dataset->layout.fp = fopen(SDDS_dataset->layout.filename, FOPEN_READ_AND_WRITE_MODE))) {
138 char s[1024];
139 sprintf(s, "Unable to open file %s (SDDS_ReconnectFile)", SDDS_dataset->layout.filename);
140 SDDS_SetError(s);
141 return 0;
142 }
143 if (fseek(SDDS_dataset->layout.fp, 0, 2) == -1) {
144 SDDS_SetError("Can't reconnect file. Fseek failed. (SDDS_ReconnectFile)");
145 return 0;
146 }
147 SDDS_dataset->original_layout.fp = SDDS_dataset->layout.fp;
148 SDDS_dataset->layout.disconnected = 0;
149 return 1;
150}
151
152/**
153 * @brief Disconnects the input file from the SDDS dataset.
154 *
155 * This function severs the connection between the SDDS dataset and its input file. It closes the file handle, updates the dataset's internal state to indicate disconnection, and returns the current file position before closing. After disconnection, the dataset cannot read further data from the input file until it is reconnected.
156 *
157 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure whose input file is to be disconnected.
158 *
159 * @return
160 * - On success, returns the current file position (as obtained by @c ftell) before disconnection.
161 * - On failure, returns @c -1 and sets an internal error message.
162 *
163 * @note
164 * - This function cannot disconnect compressed input files (gzip, lzma, xz).
165 * - Attempting to disconnect an already disconnected dataset will result in an error.
166 *
167 * @warning
168 * - Ensure that no further read operations are performed on the dataset after disconnection unless it is reconnected.
169 */
171 long position;
172#if SDDS_MPI_IO
173 if (SDDS_dataset->parallel_io) {
174 SDDS_SetError("Error: MPI mode not supported yet in SDDS_DisconnectInputFile");
175 return -1;
176 }
177#endif
178 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DisconnectInputFile"))
179 return -1;
180 if (!SDDS_dataset->layout.filename) {
181 SDDS_SetError("Can't disconnect file. No filename given. (SDDS_DisconnectInputFile)");
182 return -1;
183 }
184 if (SDDS_dataset->layout.gzipFile) {
185 SDDS_SetError("Can't disconnect file because it is a gzip file. (SDDS_DisconnectInputFile)");
186 return -1;
187 }
188 if (SDDS_dataset->layout.lzmaFile) {
189 SDDS_SetError("Can't disconnect file because it is a lzma or xz file. (SDDS_DisconnectInputFile)");
190 return -1;
191 }
192 if (SDDS_dataset->layout.disconnected) {
193 SDDS_SetError("Can't disconnect file. Already disconnected. (SDDS_DisconnectInputFile)");
194 return -1;
195 }
196 position = ftell(SDDS_dataset->layout.fp);
197 if (fclose(SDDS_dataset->layout.fp)) {
198 SDDS_SetError("Can't disconnect file. Problem closing file. (SDDS_DisconnectInputFile)");
199 return -1;
200 }
201 SDDS_dataset->layout.disconnected = 1;
202 return position;
203}
204
205/**
206 * @brief Reconnects the input file for the SDDS dataset at a specified position.
207 *
208 * This function re-establishes the connection between the SDDS dataset and its input file, positioning the file pointer at the specified byte offset. This allows the dataset to resume reading from a specific location within the input file.
209 *
210 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure to reconnect.
211 * @param[in] position The byte offset position in the input file where reconnection should occur.
212 *
213 * @return
214 * - @c 1 on successful reconnection.
215 * - @c 0 on failure. In this case, an internal error message is set.
216 *
217 * @pre
218 * - The dataset must have been previously disconnected using SDDS_DisconnectInputFile.
219 * - The dataset must have a valid filename set.
220 * - The specified position must be valid within the input file.
221 *
222 * @note
223 * - Reconnection will fail if the input file is compressed (gzip, lzma, xz).
224 * - The function seeks to the specified position after opening the file.
225 *
226 * @warning
227 * - Ensure that the specified position does not disrupt the dataset's data integrity.
228 */
229int32_t SDDS_ReconnectInputFile(SDDS_DATASET *SDDS_dataset, long position) {
230#if SDDS_MPI_IO
231 if (SDDS_dataset->parallel_io) {
232 SDDS_SetError("Error: MPI mode not supported yet in SDDS_ReconnectInputFile");
233 return 0;
234 }
235#endif
236 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_ReconnectInputFile"))
237 return 0;
238 if (!SDDS_dataset->layout.disconnected || !SDDS_dataset->layout.filename) {
239 SDDS_SetError("Can't reconnect file. Not disconnected or missing filename. (SDDS_ReconnectInputFile)");
240 return 0;
241 }
242 if (!(SDDS_dataset->layout.fp = fopen(SDDS_dataset->layout.filename, FOPEN_READ_MODE))) {
243 char s[1024];
244 sprintf(s, "Unable to open file %s (SDDS_ReconnectInputFile)", SDDS_dataset->layout.filename);
245 SDDS_SetError(s);
246 return 0;
247 }
248 if (fseek(SDDS_dataset->layout.fp, position, SEEK_SET) == -1) {
249 SDDS_SetError("Can't reconnect file. Fseek failed. (SDDS_ReconnectInputFile)");
250 return 0;
251 }
252 SDDS_dataset->original_layout.fp = SDDS_dataset->layout.fp;
253 SDDS_dataset->layout.disconnected = 0;
254 return 1;
255}
256
257/* appends to a file by adding a new page */
258
259/**
260 * @brief Initializes the SDDS dataset for appending data by adding a new page to an existing file.
261 *
262 * This function prepares the SDDS dataset for appending additional data to an existing SDDS file by initializing necessary data structures, verifying file integrity, and setting up for the addition of a new data page. It ensures that the file is writable, not compressed, and properly locked to prevent concurrent modifications.
263 *
264 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure to be initialized for appending.
265 * @param[in] filename The name of the existing SDDS file to which data will be appended. If @c NULL, data will be appended to standard input.
266 *
267 * @return
268 * - @c 1 on successful initialization.
269 * - @c 0 on error. In this case, an internal error message is set describing the failure.
270 *
271 * @pre
272 * - The specified file must exist and be a valid SDDS file.
273 * - The file must not be compressed (gzip, lzma, xz) and must be accessible for read and write operations.
274 *
275 * @post
276 * - The dataset is ready to append data as a new page.
277 * - The file is locked to prevent concurrent writes.
278 *
279 * @note
280 * - If @c filename is @c NULL, the dataset will append data from standard input.
281 * - The function sets internal flags indicating whether the file was previously empty or had existing data.
282 *
283 * @warning
284 * - Appending to a compressed file is not supported and will result in an error.
285 * - Ensure that no other processes are accessing the file simultaneously to avoid conflicts.
286 */
287int32_t SDDS_InitializeAppend(SDDS_DATASET *SDDS_dataset, const char *filename) {
288 /* char *ptr, *datafile, *headerfile; */
289 char s[SDDS_MAXLINE];
290 int64_t endOfLayoutOffset, endOfFileOffset;
291 char *extension;
292
293 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_InitializeAppend"))
294 return 0;
295 if (!SDDS_ZeroMemory((void *)SDDS_dataset, sizeof(SDDS_DATASET))) {
296 sprintf(s, "Unable to initialize input for file %s--can't zero SDDS_DATASET structure (SDDS_InitializeAppend)", filename);
297 SDDS_SetError(s);
298 return 0;
299 }
300 SDDS_dataset->layout.popenUsed = SDDS_dataset->layout.gzipFile = SDDS_dataset->layout.lzmaFile = SDDS_dataset->layout.disconnected = 0;
301 SDDS_dataset->layout.depth = SDDS_dataset->layout.data_command_seen = SDDS_dataset->layout.commentFlags = SDDS_dataset->deferSavingLayout = 0;
302 if (!filename)
303 SDDS_dataset->layout.filename = NULL;
304 else if (!SDDS_CopyString(&SDDS_dataset->layout.filename, filename)) {
305 sprintf(s, "Memory allocation failure initializing file %s (SDDS_InitializeAppend)", filename);
306 SDDS_SetError(s);
307 return 0;
308 } else if ((extension = strrchr(filename, '.')) && ((strcmp(extension, ".gz") == 0) || (strcmp(extension, ".lzma") == 0) || (strcmp(extension, ".xz") == 0))) {
309 sprintf(s, "Cannot append to a compressed file %s (SDDS_InitializeAppend)", filename);
310 SDDS_SetError(s);
311 return 0;
312 }
313
314 SDDS_dataset->layout.popenUsed = 0;
315 if (!filename) {
316#if defined(_WIN32)
317 if (_setmode(_fileno(stdin), _O_BINARY) == -1) {
318 sprintf(s, "unable to set stdin to binary mode");
319 SDDS_SetError(s);
320 return 0;
321 }
322#endif
323 SDDS_dataset->layout.fp = stdin;
324 } else {
325 if (SDDS_FileIsLocked(filename)) {
326 sprintf(s, "unable to open file %s for appending--file is locked (SDDS_InitializeAppend)", filename);
327 SDDS_SetError(s);
328 return 0;
329 }
330 if (!(SDDS_dataset->layout.fp = fopen(filename, FOPEN_READ_AND_WRITE_MODE))) {
331 sprintf(s, "Unable to open file %s for appending (SDDS_InitializeAppend)", filename);
332 SDDS_SetError(s);
333 return 0;
334 }
335 if (!SDDS_LockFile(SDDS_dataset->layout.fp, filename, "SDDS_InitializeAppend"))
336 return 0;
337 }
338
339 if (!SDDS_ReadLayout(SDDS_dataset, SDDS_dataset->layout.fp))
340 return 0;
341 endOfLayoutOffset = ftell(SDDS_dataset->layout.fp);
342 if (SDDS_dataset->layout.n_columns &&
343 (!(SDDS_dataset->column_flag = (int32_t *)SDDS_Malloc(sizeof(int32_t) * SDDS_dataset->layout.n_columns)) ||
344 !(SDDS_dataset->column_order = (int32_t *)SDDS_Malloc(sizeof(int32_t) * SDDS_dataset->layout.n_columns)) ||
345 !SDDS_SetMemory(SDDS_dataset->column_flag, SDDS_dataset->layout.n_columns, SDDS_LONG, (int32_t)1, (int32_t)0) ||
346 !SDDS_SetMemory(SDDS_dataset->column_order, SDDS_dataset->layout.n_columns, SDDS_LONG, (int32_t)0, (int32_t)1))) {
347 SDDS_SetError("Unable to initialize input--memory allocation failure (SDDS_InitializeAppend)");
348 return 0;
349 }
350 if (fseek(SDDS_dataset->layout.fp, 0, 2) == -1) {
351 SDDS_SetError("Unable to initialize append--seek failure (SDDS_InitializeAppend)");
352 return 0;
353 }
354 endOfFileOffset = ftell(SDDS_dataset->layout.fp);
355 if (endOfFileOffset == endOfLayoutOffset)
356 SDDS_dataset->file_had_data = 0; /* appending to empty file */
357 else
358 SDDS_dataset->file_had_data = 1; /* appending to nonempty file */
359 SDDS_dataset->layout.layout_written = 1; /* its already in the file */
360 SDDS_dataset->mode = SDDS_WRITEMODE; /*writing */
361 return 1;
362}
363
364/**
365 * @brief Initializes the SDDS dataset for appending data to the last page of an existing file.
366 *
367 * This function sets up the SDDS dataset to append additional data rows to the last page of an existing SDDS file. It reads the existing file layout, determines the current state of data (including row counts), and prepares internal data structures to accommodate new data. The function also handles file locking, buffer management, and ensures that the file is ready for efficient data appending based on the specified update interval.
368 *
369 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure to be initialized for appending.
370 * @param[in] filename The name of the existing SDDS file to which data will be appended. If @c NULL, data will be appended to standard input.
371 * @param[in] updateInterval The number of rows to write before the dataset reallocates memory or flushes data. This parameter controls the frequency of memory allocation and disk I/O operations during the append process.
372 * @param[out] rowsPresentReturn Pointer to an @c int64_t variable where the function will store the number of rows present in the dataset after initialization. This provides information on the current dataset size.
373 *
374 * @return
375 * - @c 1 on successful initialization.
376 * - @c 0 on error. In this case, an internal error message is set detailing the issue.
377 *
378 * @pre
379 * - The specified file must exist and be a valid SDDS file.
380 * - The file must not be compressed (gzip, lzma, xz) and must be accessible for read and write operations.
381 *
382 * @post
383 * - The dataset is configured to append data to the last page of the file.
384 * - Internal structures are initialized to track row counts and manage memory efficiently based on the update interval.
385 * - The file is locked to prevent concurrent modifications.
386 * - @c rowsPresentReturn is updated with the current number of rows in the dataset.
387 *
388 * @note
389 * - If @c filename is @c NULL, data will be appended from standard input.
390 * - The function sets internal flags indicating whether the file already contained data prior to appending.
391 *
392 * @warning
393 * - Appending to a compressed file is not supported and will result in an error.
394 * - Ensure that no other processes are accessing the file simultaneously to avoid conflicts.
395 */
396int32_t SDDS_InitializeAppendToPage(SDDS_DATASET *SDDS_dataset, const char *filename, int64_t updateInterval, int64_t *rowsPresentReturn) {
397 /* char *ptr, *datafile, *headerfile; */
398 char s[SDDS_MAXLINE];
399 int64_t endOfLayoutOffset, endOfFileOffset, rowCountOffset, offset;
400 int32_t rowsPresent32;
401 int64_t rowsPresent;
402 char *extension;
403 int32_t previousBufferSize;
404
405 *rowsPresentReturn = -1;
406 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_InitializeAppendToPage"))
407 return 0;
408 if (!SDDS_ZeroMemory((void *)SDDS_dataset, sizeof(SDDS_DATASET))) {
409 sprintf(s, "Unable to initialize input for file %s--can't zero SDDS_DATASET structure (SDDS_InitializeAppendToPage)", filename);
410 SDDS_SetError(s);
411 return 0;
412 }
413 SDDS_dataset->layout.popenUsed = SDDS_dataset->layout.gzipFile = SDDS_dataset->layout.lzmaFile = SDDS_dataset->layout.disconnected = 0;
414 SDDS_dataset->layout.depth = SDDS_dataset->layout.data_command_seen = SDDS_dataset->layout.commentFlags = SDDS_dataset->deferSavingLayout = 0;
415 if (!filename)
416 SDDS_dataset->layout.filename = NULL;
417 else if (!SDDS_CopyString(&SDDS_dataset->layout.filename, filename)) {
418 sprintf(s, "Memory allocation failure initializing file %s (SDDS_InitializeAppendToPage)", filename);
419 SDDS_SetError(s);
420 return 0;
421 } else if ((extension = strrchr(filename, '.')) && ((strcmp(extension, ".gz") == 0) || (strcmp(extension, ".lzma") == 0) || (strcmp(extension, ".xz") == 0))) {
422 sprintf(s, "Cannot append to a compressed file %s (SDDS_InitializeAppendToPage)", filename);
423 SDDS_SetError(s);
424 return 0;
425 }
426
427 if (!filename) {
428#if defined(_WIN32)
429 if (_setmode(_fileno(stdin), _O_BINARY) == -1) {
430 sprintf(s, "unable to set stdin to binary mode");
431 SDDS_SetError(s);
432 return 0;
433 }
434#endif
435 SDDS_dataset->layout.fp = stdin;
436 } else {
437 if (SDDS_FileIsLocked(filename)) {
438 sprintf(s, "unable to open file %s for appending--file is locked (SDDS_InitializeAppendToPage)", filename);
439 SDDS_SetError(s);
440 return 0;
441 }
442 if (!(SDDS_dataset->layout.fp = fopen(filename, FOPEN_READ_AND_WRITE_MODE))) {
443 sprintf(s, "Unable to open file %s for appending (SDDS_InitializeAppendToPage)", filename);
444 SDDS_SetError(s);
445 return 0;
446 }
447 if (!SDDS_LockFile(SDDS_dataset->layout.fp, filename, "SDDS_InitializeAppendToPage")) {
448 return 0;
449 }
450 }
451
452 if (!SDDS_ReadLayout(SDDS_dataset, SDDS_dataset->layout.fp)) {
453 return 0;
454 }
455 endOfLayoutOffset = ftell(SDDS_dataset->layout.fp);
456 if (SDDS_dataset->layout.n_columns &&
457 (!(SDDS_dataset->column_flag = (int32_t *)SDDS_Malloc(sizeof(int32_t) * SDDS_dataset->layout.n_columns)) ||
458 !(SDDS_dataset->column_order = (int32_t *)SDDS_Malloc(sizeof(int32_t) * SDDS_dataset->layout.n_columns)) ||
459 !SDDS_SetMemory(SDDS_dataset->column_flag, SDDS_dataset->layout.n_columns, SDDS_LONG, (int32_t)1, (int32_t)0) ||
460 !SDDS_SetMemory(SDDS_dataset->column_order, SDDS_dataset->layout.n_columns, SDDS_LONG, (int32_t)0, (int32_t)1))) {
461 SDDS_SetError("Unable to initialize input--memory allocation failure (SDDS_InitializeAppendToPage)");
462 return 0;
463 }
464 rowCountOffset = -1;
465 rowsPresent = 0;
466#ifdef DEBUG
467 fprintf(stderr, "Data mode is %s\n", SDDS_data_mode[SDDS_dataset->layout.data_mode.mode - 1]);
468#endif
469 SDDS_dataset->pagecount_offset = NULL;
470 previousBufferSize = SDDS_SetDefaultIOBufferSize(0);
471 if (!SDDS_dataset->layout.data_mode.no_row_counts) {
472 /* read pages to get to the last page */
473 while (SDDS_ReadPageSparse(SDDS_dataset, 0, 10000, 0, 0) > 0) {
474 rowCountOffset = SDDS_dataset->rowcount_offset;
475 offset = ftell(SDDS_dataset->layout.fp);
476 fseek(SDDS_dataset->layout.fp, rowCountOffset, 0);
477
478 if (SDDS_dataset->layout.data_mode.mode == SDDS_BINARY) {
479 fread(&rowsPresent32, sizeof(rowsPresent32), 1, SDDS_dataset->layout.fp);
480 if (SDDS_dataset->swapByteOrder) {
481 SDDS_SwapLong(&rowsPresent32);
482 }
483 if (rowsPresent32 == INT32_MIN) {
484 fread(&rowsPresent, sizeof(rowsPresent), 1, SDDS_dataset->layout.fp);
485 if (SDDS_dataset->swapByteOrder) {
486 SDDS_SwapLong64(&rowsPresent);
487 }
488 } else {
489 rowsPresent = rowsPresent32;
490 }
491 } else {
492 char buffer[30];
493 if (!fgets(buffer, 30, SDDS_dataset->layout.fp) || strlen(buffer) != 21 || sscanf(buffer, "%" SCNd64, &rowsPresent) != 1) {
494#ifdef DEBUG
495 fprintf(stderr, "buffer for row count data: >%s<\n", buffer);
496#endif
497 SDDS_SetError("Unable to initialize input--row count not present or not correct length (SDDS_InitializeAppendToPage)");
498 SDDS_SetDefaultIOBufferSize(previousBufferSize);
499 return 0;
500 }
501 }
502 fseek(SDDS_dataset->layout.fp, offset, 0);
503#ifdef DEBUG
504 fprintf(stderr, "%" PRId64 " rows present\n", rowsPresent);
505#endif
506 }
507 if (rowCountOffset == -1) {
508 SDDS_SetDefaultIOBufferSize(previousBufferSize);
509 SDDS_SetError("Unable to initialize input--problem finding row count offset (SDDS_InitializeAppendToPage)");
510 return 0;
511 }
512 }
513 SDDS_SetDefaultIOBufferSize(previousBufferSize);
514 SDDS_dataset->fBuffer.bytesLeft = SDDS_dataset->fBuffer.bufferSize;
515
516#ifdef DEBUG
517 fprintf(stderr, "Starting page with %" PRId64 " rows\n", updateInterval);
518#endif
519 if (!SDDS_StartPage(SDDS_dataset, updateInterval)) {
520 SDDS_SetError("Unable to initialize input--problem starting page (SDDS_InitializeAppendToPage)");
521 return 0;
522 }
523
524 /* seek to the end of the file */
525 if (fseek(SDDS_dataset->layout.fp, 0, 2) == -1) {
526 SDDS_SetError("Unable to initialize append--seek failure (SDDS_InitializeAppendToPage)");
527 return 0;
528 }
529 endOfFileOffset = ftell(SDDS_dataset->layout.fp);
530 if (endOfFileOffset == endOfLayoutOffset)
531 SDDS_dataset->file_had_data = 0; /* appending to empty file */
532 else {
533 SDDS_dataset->file_had_data = 1; /* appending to nonempty file */
534 if (rowCountOffset != -1) {
535 SDDS_dataset->rowcount_offset = rowCountOffset;
536 SDDS_dataset->n_rows_written = rowsPresent;
537 SDDS_dataset->first_row_in_mem = rowsPresent;
538 SDDS_dataset->last_row_written = -1;
539 *rowsPresentReturn = rowsPresent;
540 SDDS_dataset->writing_page = 1;
541 }
542 }
543#ifdef DEBUG
544 fprintf(stderr, "rowcount_offset = %" PRId64 ", n_rows_written = %" PRId64 ", first_row_in_mem = %" PRId64 ", last_row_written = %" PRId64 "\n", SDDS_dataset->rowcount_offset, SDDS_dataset->n_rows_written, SDDS_dataset->first_row_in_mem, SDDS_dataset->last_row_written);
545#endif
546 SDDS_dataset->page_number = 1;
547 SDDS_dataset->layout.layout_written = 1; /* its already in the file */
548 SDDS_dataset->mode = SDDS_WRITEMODE; /*writing */
549 return 1;
550}
551
552/**
553 * @brief Initializes the SDDS output dataset.
554 *
555 * This function sets up the SDDS dataset for output operations by initializing the necessary structures,
556 * configuring the data mode (ASCII, Binary, or Parallel), handling file opening (including compressed files),
557 * and setting dataset metadata such as description and contents. It ensures that the dataset is ready
558 * for writing data according to the specified parameters.
559 *
560 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure to be initialized for output.
561 * @param[in] data_mode The data mode for the output dataset. Acceptable values are:
562 * - @c SDDS_ASCII: ASCII text format.
563 * - @c SDDS_BINARY: Binary format.
564 * - @c SDDS_PARALLEL: Parallel processing mode.
565 * @param[in] lines_per_row The number of lines per row in the output dataset. This parameter is used
566 * only for ASCII output and is typically set to 1.
567 * @param[in] description A string containing the description of the output dataset. Pass @c NULL
568 * if no description is desired.
569 * @param[in] contents A string detailing the contents of the output dataset. Pass @c NULL if no contents are desired.
570 * @param[in] filename The name of the file to which the dataset will be written. If @c NULL, the dataset
571 * will be written to standard output.
572 *
573 * @return
574 * - @c 1 on successful initialization.
575 * - @c 0 if an error occurred during initialization. In this case, an error message is set internally.
576 *
577 * @pre
578 * - The @c SDDS_dataset pointer must be valid and point to a properly allocated SDDS_DATASET structure.
579 *
580 * @post
581 * - The dataset is configured for output according to the specified parameters.
582 * - The output file is opened and locked if a filename is provided.
583 * - The dataset's internal state reflects the initialization status.
584 *
585 * @note
586 * - When using compressed file formats (e.g., .gz, .lzma, .xz), the output mode is forced to binary.
587 * - Environment variable @c SDDS_OUTPUT_ENDIANESS can be set to "big" or "little" to declare the byte order.
588 * - For ASCII output, ensure that @c lines_per_row is set appropriately to match the data structure.
589 *
590 * @warning
591 * - Appending to compressed files is not supported and will result in an error.
592 * - Ensure that the specified file is not locked by another process to avoid initialization failures.
593 * - Changing data mode after initialization is not supported and may lead to undefined behavior.
594 */
595int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename) {
596 char s[SDDS_MAXLINE];
597 char *extension;
598 char *outputEndianess = NULL;
599
600 if (data_mode == SDDS_PARALLEL)
601 return SDDS_Parallel_InitializeOutput(SDDS_dataset, description, contents, filename);
602
603 if (sizeof(gzFile) != sizeof(void *)) {
604 SDDS_SetError("gzFile is not the same size as void *, possible corruption of the SDDS_LAYOUT structure");
605 return (0);
606 }
607 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_InitializeOutput"))
608 return 0;
609 if (!SDDS_ZeroMemory((void *)SDDS_dataset, sizeof(SDDS_DATASET))) {
610 sprintf(s, "Unable to initialize output for file %s--can't zero SDDS_DATASET structure (SDDS_InitializeOutput)", filename);
611 SDDS_SetError(s);
612 return 0;
613 }
614 SDDS_dataset->layout.popenUsed = SDDS_dataset->layout.gzipFile = SDDS_dataset->layout.lzmaFile = SDDS_dataset->layout.disconnected = 0;
615 SDDS_dataset->layout.depth = SDDS_dataset->layout.data_command_seen = SDDS_dataset->layout.commentFlags = SDDS_dataset->deferSavingLayout = 0;
616 if (!filename) {
617#if defined(_WIN32)
618 if (_setmode(_fileno(stdout), _O_BINARY) == -1) {
619 sprintf(s, "unable to set stdout to binary mode");
620 SDDS_SetError(s);
621 return 0;
622 }
623#endif
624 SDDS_dataset->layout.fp = stdout;
625 } else {
626 if (SDDS_FileIsLocked(filename)) {
627 sprintf(s, "unable to open file %s for writing--file is locked (SDDS_InitializeOutput)", filename);
628 SDDS_SetError(s);
629 return 0;
630 }
631 if ((extension = strrchr(filename, '.')) && ((strcmp(extension, ".xz") == 0) || (strcmp(extension, ".lzma") == 0))) {
632 SDDS_dataset->layout.lzmaFile = 1;
633 data_mode = SDDS_BINARY; /* force binary mode for output lzma files. The reading of ascii lzma files is flaky because of the lzma_gets command, plus the output files will be much smaller */
634 if (!(SDDS_dataset->layout.lzmafp = lzma_open(filename, FOPEN_WRITE_MODE))) {
635 sprintf(s, "Unable to open file %s for writing (SDDS_InitializeOutput)", filename);
636 SDDS_SetError(s);
637 return 0;
638 }
639 SDDS_dataset->layout.fp = SDDS_dataset->layout.lzmafp->fp;
640 } else {
641 if (!(SDDS_dataset->layout.fp = fopen(filename, FOPEN_WRITE_MODE))) {
642 sprintf(s, "Unable to open file %s for writing (SDDS_InitializeOutput)", filename);
643 SDDS_SetError(s);
644 return 0;
645 }
646 }
647 if (!SDDS_LockFile(SDDS_dataset->layout.fp, filename, "SDDS_InitializeOutput"))
648 return 0;
649#if defined(zLib)
650 if ((extension = strrchr(filename, '.')) && (strcmp(extension, ".gz") == 0)) {
651 SDDS_dataset->layout.gzipFile = 1;
652 if ((SDDS_dataset->layout.gzfp = gzdopen(fileno(SDDS_dataset->layout.fp), FOPEN_WRITE_MODE)) == NULL) {
653 sprintf(s, "Unable to open compressed file %s for writing (SDDS_InitializeOutput)", filename);
654 SDDS_SetError(s);
655 return 0;
656 }
657 }
658#endif
659 }
660 SDDS_dataset->page_number = SDDS_dataset->page_started = 0;
661 SDDS_dataset->file_had_data = SDDS_dataset->layout.layout_written = 0;
662 if (!filename)
663 SDDS_dataset->layout.filename = NULL;
664 else if (!SDDS_CopyString(&SDDS_dataset->layout.filename, filename)) {
665 sprintf(s, "Memory allocation failure initializing file %s (SDDS_InitializeOutput)", filename);
666 SDDS_SetError(s);
667 return 0;
668 }
669 if ((outputEndianess = getenv("SDDS_OUTPUT_ENDIANESS"))) {
670 if (strncmp(outputEndianess, "big", 3) == 0)
671 SDDS_dataset->layout.byteOrderDeclared = SDDS_BIGENDIAN;
672 else if (strncmp(outputEndianess, "little", 6) == 0)
673 SDDS_dataset->layout.byteOrderDeclared = SDDS_LITTLEENDIAN;
674 } else {
675 SDDS_dataset->layout.byteOrderDeclared = SDDS_IsBigEndianMachine() ? SDDS_BIGENDIAN : SDDS_LITTLEENDIAN;
676 }
677
678 if (data_mode < 0 || data_mode > SDDS_NUM_DATA_MODES) {
679 sprintf(s, "Invalid data mode for file %s (SDDS_InitializeOutput)", filename ? filename : "stdout");
680 SDDS_SetError(s);
681 return 0;
682 }
683 if (data_mode == SDDS_ASCII && lines_per_row <= 0) {
684 sprintf(s, "Invalid number of lines per row for file %s (SDDS_InitializeOutput)", filename ? filename : "stdout");
685 SDDS_SetError(s);
686 return 0;
687 }
688 SDDS_dataset->layout.version = SDDS_VERSION;
689 SDDS_dataset->layout.data_mode.mode = data_mode;
690 SDDS_dataset->layout.data_mode.lines_per_row = lines_per_row;
691 SDDS_dataset->layout.data_mode.no_row_counts = 0;
692 SDDS_dataset->layout.data_mode.fixed_row_count = 0;
693 SDDS_dataset->layout.data_mode.fsync_data = 0;
694 SDDS_dataset->layout.data_mode.column_memory_mode = DEFAULT_COLUMN_MEMORY_MODE;
695 /*This is only temporary, soon the default will be column major order */
696 SDDS_dataset->layout.data_mode.column_major = 0;
697 if (description && !SDDS_CopyString(&SDDS_dataset->layout.description, description)) {
698 sprintf(s, "Memory allocation failure initializing file %s (SDDS_InitializeOutput)", filename ? filename : "stdout");
699 SDDS_SetError(s);
700 return 0;
701 }
702 if (contents && !SDDS_CopyString(&SDDS_dataset->layout.contents, contents)) {
703 sprintf(s, "Memory allocation failure initializing file %s (SDDS_InitializeOutput)", filename ? filename : "stdout");
704 SDDS_SetError(s);
705 return 0;
706 }
707 SDDS_dataset->mode = SDDS_WRITEMODE; /*writing */
708 SDDS_dataset->pagecount_offset = NULL;
709 SDDS_dataset->parallel_io = 0;
710 return (1);
711}
712
713/**
714 * @brief Initializes the SDDS output dataset for parallel processing.
715 *
716 * This function configures the SDDS dataset for parallel output operations. It sets the dataset's
717 * description, contents, and filename, ensuring that the output is in binary mode as parallel
718 * processing with compressed files is not supported. The function initializes necessary structures
719 * and prepares the dataset for efficient parallel data writing.
720 *
721 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure to be initialized for parallel output.
722 * @param[in] description A string containing the description of the dataset. Pass @c NULL if no description is desired.
723 * @param[in] contents A string detailing the contents of the dataset. Pass @c NULL if no contents are desired.
724 * @param[in] filename The name of the file to which the dataset will be written. If @c NULL, the dataset
725 * will be written to standard output.
726 *
727 * @return
728 * - @c 1 on successful initialization.
729 * - @c 0 if an error occurred during initialization. In this case, an error message is set internally.
730 *
731 * @pre
732 * - The @c SDDS_dataset pointer must be valid and point to a properly allocated SDDS_DATASET structure.
733 * - The dataset memory should have been zeroed prior to calling this function (handled externally).
734 *
735 * @post
736 * - The dataset is configured for parallel binary output.
737 * - The dataset's internal state reflects the initialization status.
738 *
739 * @note
740 * - Parallel output does not support compressed file formats.
741 * - The output mode is set to binary regardless of the specified data mode.
742 * - Environment variable @c SDDS_OUTPUT_ENDIANESS can be set to "big" or "little" to declare the byte order.
743 *
744 * @warning
745 * - Attempting to use parallel initialization with compressed files will result in an error.
746 * - Ensure that no other processes are accessing the file simultaneously to prevent initialization failures.
747 */
748int32_t SDDS_Parallel_InitializeOutput(SDDS_DATASET *SDDS_dataset, const char *description, const char *contents, const char *filename) {
749 /* SDDS_DATASET *SDDS_dataset; */
750 char s[SDDS_MAXLINE];
751 char *outputEndianess = NULL;
752
753 /* SDDS_dataset = &(MPI_dataset->sdds_dataset); */
754 if (sizeof(gzFile) != sizeof(void *)) {
755 SDDS_SetError("gzFile is not the same size as void *, possible corruption of the SDDS_LAYOUT structure");
756 return (0);
757 }
758 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_InitializeOutput"))
759 return 0;
760 /* if (!SDDS_ZeroMemory((void *)SDDS_dataset, sizeof(SDDS_DATASET))) {
761 sprintf(s,
762 "Unable to initialize output for file %s--can't zero SDDS_DATASET structure (SDDS_InitializeOutput)",
763 filename);
764 SDDS_SetError(s);
765 return 0;
766 } */
767 /*the sdds dataset memory has been zeroed in the SDDS_MPI_Setup */
768 SDDS_dataset->layout.popenUsed = SDDS_dataset->layout.gzipFile = SDDS_dataset->layout.lzmaFile = SDDS_dataset->layout.disconnected = 0;
769 SDDS_dataset->layout.depth = SDDS_dataset->layout.data_command_seen = SDDS_dataset->layout.commentFlags = SDDS_dataset->deferSavingLayout = 0;
770 SDDS_dataset->layout.fp = NULL;
771
772 SDDS_dataset->page_number = SDDS_dataset->page_started = 0;
773 SDDS_dataset->file_had_data = SDDS_dataset->layout.layout_written = 0;
774 if (!filename)
775 SDDS_dataset->layout.filename = NULL;
776 else if (!SDDS_CopyString(&SDDS_dataset->layout.filename, filename)) {
777 sprintf(s, "Memory allocation failure initializing file %s (SDDS_InitializeOutput)", filename);
778 SDDS_SetError(s);
779 return 0;
780 }
781 if ((outputEndianess = getenv("SDDS_OUTPUT_ENDIANESS"))) {
782 if (strncmp(outputEndianess, "big", 3) == 0)
783 SDDS_dataset->layout.byteOrderDeclared = SDDS_BIGENDIAN;
784 else if (strncmp(outputEndianess, "little", 6) == 0)
785 SDDS_dataset->layout.byteOrderDeclared = SDDS_LITTLEENDIAN;
786 } else {
787 SDDS_dataset->layout.byteOrderDeclared = SDDS_IsBigEndianMachine() ? SDDS_BIGENDIAN : SDDS_LITTLEENDIAN;
788 }
789 /* set big-endian for binary files, since it is the only type of MPI binary file.
790 SDDS_dataset->layout.byteOrderDeclared = SDDS_BIGENDIAN; */
791 SDDS_dataset->layout.version = SDDS_VERSION;
792 /* it turned out that hard to write ascii file in parallel, fixed it as SDDS_BINARY */
793 SDDS_dataset->layout.data_mode.mode = SDDS_BINARY;
794 SDDS_dataset->layout.data_mode.lines_per_row = 0;
795 SDDS_dataset->layout.data_mode.no_row_counts = 0;
796 SDDS_dataset->layout.data_mode.fixed_row_count = 0;
797 SDDS_dataset->layout.data_mode.fsync_data = 0;
798 SDDS_dataset->layout.data_mode.column_memory_mode = DEFAULT_COLUMN_MEMORY_MODE;
799 /*This is only temporary, soon the default will be column major order */
800 SDDS_dataset->layout.data_mode.column_major = 0;
801 if (description && !SDDS_CopyString(&SDDS_dataset->layout.description, description)) {
802 sprintf(s, "Memory allocation failure initializing file %s (SDDS_InitializeOutput)", filename ? filename : "stdout");
803 SDDS_SetError(s);
804 return 0;
805 }
806 if (contents && !SDDS_CopyString(&SDDS_dataset->layout.contents, contents)) {
807 sprintf(s, "Memory allocation failure initializing file %s (SDDS_InitializeOutput)", filename ? filename : "stdout");
808 SDDS_SetError(s);
809 return 0;
810 }
811 SDDS_dataset->layout.n_parameters = SDDS_dataset->layout.n_columns = SDDS_dataset->layout.n_arrays = SDDS_dataset->layout.n_associates = 0;
812 SDDS_dataset->mode = SDDS_WRITEMODE; /*writing */
813 SDDS_dataset->pagecount_offset = NULL;
814 SDDS_dataset->parallel_io = 1;
815 return (1);
816}
817
818/**
819 * @brief Sets the flag to enable or disable row counts in the SDDS dataset.
820 *
821 * This function configures the SDDS dataset to either include or exclude row counts in the output.
822 * Row counts provide metadata about the number of rows written, which can be useful for data integrity
823 * and validation. Disabling row counts can improve performance when such metadata is unnecessary.
824 *
825 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure to be configured.
826 * @param[in] value The flag value to set:
827 * - @c 0: Enable row counts (default behavior).
828 * - Non-zero: Disable row counts.
829 *
830 * @return
831 * - @c 1 on successful configuration.
832 * - @c 0 if an error occurred (e.g., attempting to change the flag after the layout has been written).
833 *
834 * @pre
835 * - The @c SDDS_dataset must be initialized and not have written the layout yet.
836 *
837 * @post
838 * - The dataset's configuration reflects the specified row count setting.
839 *
840 * @note
841 * - Changing the row count setting affects how data rows are managed and stored in the output file.
842 *
843 * @warning
844 * - This function cannot be called after the dataset layout has been written to the file or if the dataset is in read mode.
845 * - Disabling row counts may complicate data validation and integrity checks.
846 */
847int32_t SDDS_SetNoRowCounts(SDDS_DATASET *SDDS_dataset, int32_t value) {
848 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetNoRowCounts"))
849 return 0;
850 if (SDDS_dataset->layout.layout_written) {
851 SDDS_SetError("Can't change no_row_counts after writing the layout, or for a file you are reading.");
852 return 0;
853 }
854 SDDS_dataset->layout.data_mode.no_row_counts = value ? 1 : 0;
855 return 1;
856}
857
858/**
859 * @brief Writes the SDDS layout header to the output file.
860 *
861 * This function serializes and writes the layout information of the SDDS dataset to the output file.
862 * The layout defines the structure of the data tables, including parameters, arrays, columns, and
863 * associates. The function handles different file types, including standard, gzip-compressed, and
864 * LZMA-compressed files, and ensures that the layout is written in the correct byte order and format
865 * based on the dataset's configuration.
866 *
867 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure whose layout is to be written.
868 *
869 * @return
870 * - @c 1 on successful writing of the layout.
871 * - @c 0 if an error occurred during the writing process. An internal error message is set in this case.
872 *
873 * @pre
874 * - The dataset must be initialized and configured for output.
875 * - The layout must have been saved internally using SDDS_SaveLayout before calling this function.
876 * - The dataset must not be disconnected from the output file.
877 * - The layout must not have been previously written to the file.
878 *
879 * @post
880 * - The layout header is written to the output file in the appropriate format.
881 * - The dataset's internal state is updated to reflect that the layout has been written.
882 *
883 * @note
884 * - The function automatically determines the layout version based on the data types used in parameters, arrays, and columns.
885 * - Environment variable @c SDDS_OUTPUT_ENDIANESS can influence the byte order declared in the layout.
886 * - The function handles both binary and ASCII modes, adjusting the layout accordingly.
887 *
888 * @warning
889 * - Attempting to write the layout after it has already been written will result in an error.
890 * - The function does not support writing layouts to disconnected files.
891 * - Ensure that the output file is properly opened and writable before calling this function.
892 */
893int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset) {
894 SDDS_LAYOUT *layout;
895#if defined(zLib)
896 gzFile gzfp;
897#endif
898 FILE *fp;
899 struct lzmafile *lzmafp;
900 int64_t i;
901 char *outputEndianess = NULL;
902
903#if SDDS_MPI_IO
904 if (SDDS_dataset->parallel_io)
905 return SDDS_MPI_WriteLayout(SDDS_dataset);
906#endif
907 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_WriteLayout"))
908 return 0;
909
910 if (!SDDS_SaveLayout(SDDS_dataset))
911 return 0;
912
913 layout = &SDDS_dataset->layout;
914
915 if (SDDS_dataset->layout.disconnected) {
916 SDDS_SetError("Can't write layout--file is disconnected (SDDS_WriteLayout)");
917 return 0;
918 }
919
920 if (layout->layout_written) {
921 SDDS_SetError("Can't write layout--already written to file (SDDS_WriteLayout)");
922 return 0;
923 }
924
925 if ((outputEndianess = getenv("SDDS_OUTPUT_ENDIANESS"))) {
926 if (strncmp(outputEndianess, "big", 3) == 0)
927 layout->byteOrderDeclared = SDDS_BIGENDIAN;
928 else if (strncmp(outputEndianess, "little", 6) == 0)
929 layout->byteOrderDeclared = SDDS_LITTLEENDIAN;
930 }
931
932 if (!layout->byteOrderDeclared)
933 layout->byteOrderDeclared = SDDS_IsBigEndianMachine() ? SDDS_BIGENDIAN : SDDS_LITTLEENDIAN;
934
935 layout->version = 1;
936 for (i = 0; i < layout->n_parameters; i++) {
937 if ((layout->parameter_definition[i].type == SDDS_ULONG) || (layout->parameter_definition[i].type == SDDS_USHORT)) {
938 layout->version = 2;
939 break;
940 }
941 }
942 for (i = 0; i < layout->n_arrays; i++) {
943 if ((layout->array_definition[i].type == SDDS_ULONG) || (layout->array_definition[i].type == SDDS_USHORT)) {
944 layout->version = 2;
945 break;
946 }
947 }
948 for (i = 0; i < layout->n_columns; i++) {
949 if ((layout->column_definition[i].type == SDDS_ULONG) || (layout->column_definition[i].type == SDDS_USHORT)) {
950 layout->version = 2;
951 break;
952 }
953 }
954 if ((layout->data_mode.column_major) && (layout->data_mode.mode == SDDS_BINARY)) {
955 layout->version = 3;
956 }
957 for (i = 0; i < layout->n_parameters; i++) {
958 if (layout->parameter_definition[i].type == SDDS_LONGDOUBLE) {
959 layout->version = 4;
960 break;
961 }
962 }
963 for (i = 0; i < layout->n_arrays; i++) {
964 if (layout->array_definition[i].type == SDDS_LONGDOUBLE) {
965 layout->version = 4;
966 break;
967 }
968 }
969 for (i = 0; i < layout->n_columns; i++) {
970 if (layout->column_definition[i].type == SDDS_LONGDOUBLE) {
971 layout->version = 4;
972 break;
973 }
974 }
975 if ((LDBL_DIG != 18) && (layout->version == 4)) {
976 if (getenv("SDDS_LONGDOUBLE_64BITS") == NULL) {
977 SDDS_SetError("Error: Operating system does not support 80bit float variables used by SDDS_LONGDOUBLE (SDDS_WriteLayout)\nSet SDDS_LONGDOUBLE_64BITS environment variable to read old files that used 64bit float variables for SDDS_LONGDOUBLE");
978 return 0;
979 }
980 }
981 for (i = 0; i < layout->n_parameters; i++) {
982 if ((layout->parameter_definition[i].type == SDDS_ULONG64) || (layout->parameter_definition[i].type == SDDS_LONG64)) {
983 layout->version = 5;
984 break;
985 }
986 }
987 for (i = 0; i < layout->n_arrays; i++) {
988 if ((layout->array_definition[i].type == SDDS_ULONG64) || (layout->array_definition[i].type == SDDS_LONG64)) {
989 layout->version = 5;
990 break;
991 }
992 }
993 for (i = 0; i < layout->n_columns; i++) {
994 if ((layout->column_definition[i].type == SDDS_ULONG64) || (layout->column_definition[i].type == SDDS_LONG64)) {
995 layout->version = 5;
996 break;
997 }
998 }
999
1000 // force layout version 5 because the row and column indexes are now 64bit long integers
1001 // layout->version = 5;
1002
1003#if defined(zLib)
1004 if (SDDS_dataset->layout.gzipFile) {
1005 if (!(gzfp = layout->gzfp)) {
1006 SDDS_SetError("Can't write SDDS layout--file pointer is NULL (SDDS_WriteLayout)");
1007 return 0;
1008 }
1009
1010 /* write out the layout data */
1011 if (!SDDS_GZipWriteVersion(layout->version, gzfp)) {
1012 SDDS_SetError("Can't write SDDS layout--error writing version (SDDS_WriteLayout)");
1013 return 0;
1014 }
1015 if (layout->version < 3) {
1016 if (SDDS_dataset->layout.data_mode.mode == SDDS_BINARY) {
1017 if (layout->byteOrderDeclared == SDDS_BIGENDIAN)
1018 gzprintf(gzfp, "!# big-endian\n");
1019 else
1020 gzprintf(gzfp, "!# little-endian\n");
1021 }
1022 if (SDDS_dataset->layout.data_mode.fixed_row_count) {
1023 gzprintf(gzfp, "!# fixed-rowcount\n");
1024 }
1025 }
1026 if (!SDDS_GZipWriteDescription(layout->description, layout->contents, gzfp)) {
1027 SDDS_SetError("Can't write SDDS layout--error writing description (SDDS_WriteLayout)");
1028 return 0;
1029 }
1030
1031 for (i = 0; i < layout->n_parameters; i++)
1032 if (!SDDS_GZipWriteParameterDefinition(layout->parameter_definition + i, gzfp)) {
1033 SDDS_SetError("Unable to write layout--error writing parameter definition (SDDS_WriteLayout)");
1034 return 0;
1035 }
1036
1037 for (i = 0; i < layout->n_arrays; i++)
1038 if (!SDDS_GZipWriteArrayDefinition(layout->array_definition + i, gzfp)) {
1039 SDDS_SetError("Unable to write layout--error writing array definition (SDDS_WriteLayout)");
1040 return 0;
1041 }
1042
1043 for (i = 0; i < layout->n_columns; i++)
1044 if (!SDDS_GZipWriteColumnDefinition(layout->column_definition + i, gzfp)) {
1045 SDDS_SetError("Unable to write layout--error writing column definition (SDDS_WriteLayout)");
1046 return 0;
1047 }
1048
1049# if RW_ASSOCIATES != 0
1050 for (i = 0; i < layout->n_associates; i++)
1051 if (!SDDS_GZipWriteAssociateDefinition(layout->associate_definition + i, gzfp)) {
1052 SDDS_SetError("Unable to write layout--error writing associated file data (SDDS_WriteLayout)");
1053 return 0;
1054 }
1055# endif
1056
1057 if (!SDDS_GZipWriteDataMode(layout, gzfp)) {
1058 SDDS_SetError("Unable to write layout--error writing data mode (SDDS_WriteLayout)");
1059 return 0;
1060 }
1061
1062 layout->layout_written = 1;
1063 /*gzflush(gzfp, Z_FULL_FLUSH); */
1064 } else {
1065#endif
1066 if (SDDS_dataset->layout.lzmaFile) {
1067 if (!(lzmafp = layout->lzmafp)) {
1068 SDDS_SetError("Can't write SDDS layout--file pointer is NULL (SDDS_WriteLayout)");
1069 return 0;
1070 }
1071
1072 /* write out the layout data */
1073 if (!SDDS_LZMAWriteVersion(layout->version, lzmafp)) {
1074 SDDS_SetError("Can't write SDDS layout--error writing version (SDDS_WriteLayout)");
1075 return 0;
1076 }
1077 if (layout->version < 3) {
1078 if (SDDS_dataset->layout.data_mode.mode == SDDS_BINARY) {
1079 if (layout->byteOrderDeclared == SDDS_BIGENDIAN)
1080 lzma_printf(lzmafp, "!# big-endian\n");
1081 else
1082 lzma_printf(lzmafp, "!# little-endian\n");
1083 }
1084 if (SDDS_dataset->layout.data_mode.fixed_row_count) {
1085 lzma_printf(lzmafp, "!# fixed-rowcount\n");
1086 }
1087 }
1088 if (!SDDS_LZMAWriteDescription(layout->description, layout->contents, lzmafp)) {
1089 SDDS_SetError("Can't write SDDS layout--error writing description (SDDS_WriteLayout)");
1090 return 0;
1091 }
1092 for (i = 0; i < layout->n_parameters; i++)
1093 if (!SDDS_LZMAWriteParameterDefinition(layout->parameter_definition + i, lzmafp)) {
1094 SDDS_SetError("Unable to write layout--error writing parameter definition (SDDS_WriteLayout)");
1095 return 0;
1096 }
1097 for (i = 0; i < layout->n_arrays; i++)
1098 if (!SDDS_LZMAWriteArrayDefinition(layout->array_definition + i, lzmafp)) {
1099 SDDS_SetError("Unable to write layout--error writing array definition (SDDS_WriteLayout)");
1100 return 0;
1101 }
1102 for (i = 0; i < layout->n_columns; i++)
1103 if (!SDDS_LZMAWriteColumnDefinition(layout->column_definition + i, lzmafp)) {
1104 SDDS_SetError("Unable to write layout--error writing column definition (SDDS_WriteLayout)");
1105 return 0;
1106 }
1107
1108#if RW_ASSOCIATES != 0
1109 for (i = 0; i < layout->n_associates; i++)
1110 if (!SDDS_LZMAWriteAssociateDefinition(layout->associate_definition + i, lzmafp)) {
1111 SDDS_SetError("Unable to write layout--error writing associated file data (SDDS_WriteLayout)");
1112 return 0;
1113 }
1114#endif
1115
1116 if (!SDDS_LZMAWriteDataMode(layout, lzmafp)) {
1117 SDDS_SetError("Unable to write layout--error writing data mode (SDDS_WriteLayout)");
1118 return 0;
1119 }
1120
1121 layout->layout_written = 1;
1122 } else {
1123
1124 if (!(fp = layout->fp)) {
1125 SDDS_SetError("Can't write SDDS layout--file pointer is NULL (SDDS_WriteLayout)");
1126 return 0;
1127 }
1128
1129 /* write out the layout data */
1130 if (!SDDS_WriteVersion(layout->version, fp)) {
1131 SDDS_SetError("Can't write SDDS layout--error writing version (SDDS_WriteLayout)");
1132 return 0;
1133 }
1134 if (layout->version < 3) {
1135 if (SDDS_dataset->layout.data_mode.mode == SDDS_BINARY) {
1136 if (layout->byteOrderDeclared == SDDS_BIGENDIAN)
1137 fprintf(fp, "!# big-endian\n");
1138 else
1139 fprintf(fp, "!# little-endian\n");
1140 }
1141 if (SDDS_dataset->layout.data_mode.fixed_row_count) {
1142 fprintf(fp, "!# fixed-rowcount\n");
1143 }
1144 }
1145 if (!SDDS_WriteDescription(layout->description, layout->contents, fp)) {
1146 SDDS_SetError("Can't write SDDS layout--error writing description (SDDS_WriteLayout)");
1147 return 0;
1148 }
1149
1150 for (i = 0; i < layout->n_parameters; i++)
1151 if (!SDDS_WriteParameterDefinition(layout->parameter_definition + i, fp)) {
1152 SDDS_SetError("Unable to write layout--error writing parameter definition (SDDS_WriteLayout)");
1153 return 0;
1154 }
1155
1156 for (i = 0; i < layout->n_arrays; i++)
1157 if (!SDDS_WriteArrayDefinition(layout->array_definition + i, fp)) {
1158 SDDS_SetError("Unable to write layout--error writing array definition (SDDS_WriteLayout)");
1159 return 0;
1160 }
1161
1162 for (i = 0; i < layout->n_columns; i++)
1163 if (!SDDS_WriteColumnDefinition(layout->column_definition + i, fp)) {
1164 SDDS_SetError("Unable to write layout--error writing column definition (SDDS_WriteLayout)");
1165 return 0;
1166 }
1167
1168#if RW_ASSOCIATES != 0
1169 for (i = 0; i < layout->n_associates; i++)
1170 if (!SDDS_WriteAssociateDefinition(layout->associate_definition + i, fp)) {
1171 SDDS_SetError("Unable to write layout--error writing associated file data (SDDS_WriteLayout)");
1172 return 0;
1173 }
1174#endif
1175
1176 if (!SDDS_WriteDataMode(layout, fp)) {
1177 SDDS_SetError("Unable to write layout--error writing data mode (SDDS_WriteLayout)");
1178 return 0;
1179 }
1180
1181 layout->layout_written = 1;
1182 fflush(fp);
1183 }
1184#if defined(zLib)
1185 }
1186#endif
1187 if (SDDS_SyncDataSet(SDDS_dataset) != 0)
1188 return 0;
1189 return (1);
1190}
1191
1192/**
1193 * @brief Writes the current data table to the output file.
1194 *
1195 * This function serializes and writes the current data table of the SDDS dataset to the output file.
1196 * It must be preceded by a call to @c SDDS_WriteLayout to ensure that the dataset layout is properly defined
1197 * in the output file. Depending on the data mode (ASCII or Binary), the function delegates the writing
1198 * process to the appropriate handler.
1199 *
1200 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1201 *
1202 * @return
1203 * - @c 1 on successful writing of the data table.
1204 * - @c 0 if an error occurred during the write process. An error message is set internally in this case.
1205 *
1206 * @pre
1207 * - The dataset must be initialized and configured for output.
1208 * - @c SDDS_WriteLayout must have been called successfully before writing any pages.
1209 *
1210 * @post
1211 * - The current data table is written to the output file.
1212 * - The dataset state is synchronized with the file to ensure data integrity.
1213 *
1214 * @note
1215 * - The function supports parallel I/O modes if enabled.
1216 * - Ensure that the dataset is not disconnected from the output file before calling this function.
1217 *
1218 * @warning
1219 * - Attempting to write a page without defining the layout first will result in an error.
1220 * - Concurrent access to the dataset while writing pages may lead to undefined behavior.
1221 */
1222int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset) {
1223 int32_t result;
1224#if SDDS_MPI_IO
1225 if (SDDS_dataset->parallel_io)
1226 return SDDS_MPI_WritePage(SDDS_dataset);
1227#endif
1228 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_WritePage"))
1229 return 0;
1230 if (!SDDS_dataset->layout.layout_written) {
1231 SDDS_SetError("Unable to write page--layout not written (SDDS_WritePage)");
1232 return 0;
1233 }
1234 if (SDDS_dataset->layout.disconnected) {
1235 SDDS_SetError("Can't write page--file is disconnected (SDDS_WritePage)");
1236 return 0;
1237 }
1238 if (SDDS_dataset->layout.data_mode.mode == SDDS_ASCII)
1239 result = SDDS_WriteAsciiPage(SDDS_dataset);
1240 else if (SDDS_dataset->layout.data_mode.mode == SDDS_BINARY)
1241 result = SDDS_WriteBinaryPage(SDDS_dataset);
1242 else {
1243 SDDS_SetError("Unable to write page--unknown data mode (SDDS_WritePage)");
1244 return 0;
1245 }
1246 if (result == 1)
1247 if (SDDS_SyncDataSet(SDDS_dataset) != 0)
1248 return 0;
1249 return (result);
1250}
1251
1252/**
1253 * @brief Updates the current page of the SDDS dataset.
1254 *
1255 * This function finalizes and writes the current page of the SDDS dataset based on the specified mode.
1256 * The mode can be either @c FLUSH_TABLE, indicating that the current page is complete and should be written to disk,
1257 * or @c 0 for other update operations. Depending on the data mode (ASCII or Binary), the function delegates
1258 * the update process to the appropriate handler.
1259 *
1260 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1261 * @param[in] mode The update mode, which can be:
1262 * - @c FLUSH_TABLE: Indicates that the current page is complete and should be written to disk.
1263 * - @c 0: Represents a standard update without flushing the table.
1264 *
1265 * @return
1266 * - @c 1 on successful update of the current page.
1267 * - @c 0 if an error occurred during the update process. An error message is set internally in this case.
1268 *
1269 * @pre
1270 * - The dataset must be initialized and configured for output.
1271 * - A page must have been started before calling this function.
1272 *
1273 * @post
1274 * - The current page is updated and, if specified, written to the output file.
1275 * - The dataset state is synchronized with the file to ensure data integrity.
1276 *
1277 * @note
1278 * - The function supports parallel I/O modes if enabled.
1279 * - The @c FLUSH_TABLE mode ensures that all buffered data is written to the disk, which can be useful for data integrity.
1280 *
1281 * @warning
1282 * - Attempting to update a page without starting one will result in an error.
1283 * - Concurrent access to the dataset while updating pages may lead to undefined behavior.
1284 */
1285int32_t SDDS_UpdatePage(SDDS_DATASET *SDDS_dataset, uint32_t mode) {
1286 int32_t result;
1287 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_UpdatePage"))
1288 return 0;
1289 if (SDDS_dataset->layout.disconnected) {
1290 SDDS_SetError("Can't write page--file is disconnected (SDDS_UpdatePage)");
1291 return 0;
1292 }
1293 if (SDDS_dataset->page_started == 0) {
1294 SDDS_SetError("Can't update page--no page started (SDDS_UpdatePage)");
1295 return 0;
1296 }
1297 if (SDDS_dataset->layout.data_mode.mode == SDDS_ASCII)
1298 result = SDDS_UpdateAsciiPage(SDDS_dataset, mode);
1299 else if (SDDS_dataset->layout.data_mode.mode == SDDS_BINARY)
1300 result = SDDS_UpdateBinaryPage(SDDS_dataset, mode);
1301 else {
1302 SDDS_SetError("Unable to update page--unknown data mode (SDDS_UpdatePage)");
1303 return 0;
1304 }
1305 if (result == 1)
1306 if (SDDS_SyncDataSet(SDDS_dataset) != 0)
1307 return 0;
1308 return (result);
1309}
1310
1311/**
1312 * @brief Synchronizes the SDDS dataset with the disk by flushing buffered data.
1313 *
1314 * This function attempts to ensure that any buffered data associated with the SDDS dataset is written
1315 * to the disk using the @c fsync system call. However, on certain platforms such as VxWorks, Windows,
1316 * Linux, and macOS, this functionality is not implemented and the function simply returns success.
1317 * This behavior should be considered when relying on data synchronization across different operating systems.
1318 *
1319 * @param[in] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1320 *
1321 * @return
1322 * - @c 0 on success, indicating that data synchronization is either not needed or was successful.
1323 * - A negative value (e.g., @c -1) on failure to synchronize the data, with an error message set internally.
1324 *
1325 * @note
1326 * - On unsupported platforms, the function does not perform any synchronization and returns success.
1327 * - The synchronization behavior depends on the operating system and its support for the @c fsync system call.
1328 *
1329 * @warning
1330 * - On platforms where synchronization is not implemented, relying on this function for data integrity is not possible.
1331 * - Ensure that critical data is handled appropriately, considering the limitations of the target operating system.
1332 */
1333int32_t SDDS_SyncDataSet(SDDS_DATASET *SDDS_dataset) {
1334#if defined(vxWorks) || defined(_WIN32) || defined(linux) || defined(__APPLE__)
1335 return (0);
1336#else
1337 if (!(SDDS_dataset->layout.fp)) {
1338 SDDS_SetError("Unable to sync file--file pointer is NULL (SDDS_SyncDataSet)");
1339 return (-1);
1340 }
1341 if (SDDS_dataset->layout.data_mode.fsync_data == 0)
1342 return (0);
1343 if (fsync(fileno(SDDS_dataset->layout.fp)) == 0)
1344 return (0);
1345 /*
1346 SDDS_SetError("Unable to sync file (SDDS_SyncDataSet)");
1347 return(-1);
1348 */
1349 /* This error should not be fatal */
1350 return (0);
1351#endif
1352}
1353
1354/**
1355 * @brief Defines a data parameter with a fixed numerical value.
1356 *
1357 * This function processes the definition of a data parameter within the SDDS dataset. It allows
1358 * the specification of a fixed numerical value for the parameter, which remains constant across
1359 * all data entries. The function validates the parameter name, type, and format string before
1360 * defining the parameter in the dataset.
1361 *
1362 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1363 * @param[in] name A NULL-terminated string specifying the name of the parameter. This name must be unique within the dataset.
1364 * @param[in] symbol A NULL-terminated string specifying the symbol for the parameter. Pass @c NULL if no symbol is desired.
1365 * @param[in] units A NULL-terminated string specifying the units of the parameter. Pass @c NULL if no units are desired.
1366 * @param[in] description A NULL-terminated string providing a description of the parameter. Pass @c NULL if no description is desired.
1367 * @param[in] format_string A NULL-terminated string specifying the printf-style format for ASCII output. If @c NULL is passed, a default format is selected based on the parameter type.
1368 * @param[in] type An integer representing the data type of the parameter. Must be one of the following:
1369 * - @c SDDS_LONGDOUBLE
1370 * - @c SDDS_DOUBLE
1371 * - @c SDDS_FLOAT
1372 * - @c SDDS_LONG
1373 * - @c SDDS_ULONG
1374 * - @c SDDS_SHORT
1375 * - @c SDDS_USHORT
1376 * - @c SDDS_CHARACTER
1377 * - @c SDDS_STRING
1378 * @param[in] fixed_value A pointer to the numerical value that remains constant for this parameter across all data entries. This value is used to initialize the parameter's fixed value.
1379 *
1380 * @return
1381 * - On success, returns the index of the newly defined parameter within the dataset.
1382 * - Returns @c -1 on failure, with an error message set internally.
1383 *
1384 * @pre
1385 * - The dataset must be initialized and configured for output.
1386 * - The parameter name must be unique and valid.
1387 * - The fixed value must be non-NULL for numerical types and should be prepared appropriately.
1388 *
1389 * @post
1390 * - The parameter is defined within the dataset with the specified attributes and fixed value.
1391 * - The dataset's internal structures are updated to include the new parameter.
1392 *
1393 * @note
1394 * - For string-type parameters, the fixed value should be a NULL-terminated string.
1395 * - The function internally converts the fixed numerical value to a string representation if the parameter type is not @c SDDS_STRING.
1396 *
1397 * @warning
1398 * - Defining a parameter with an invalid type or format string will result in an error.
1399 * - Passing a NULL fixed value for non-string types will result in an error.
1400 */
1401int32_t SDDS_DefineParameter1(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, void *fixed_value) {
1402 char buffer[SDDS_MAXLINE];
1403 if (!SDDS_IsValidName(name, "parameter"))
1404 return -1;
1405 if (!fixed_value || type == SDDS_STRING)
1406 return SDDS_DefineParameter(SDDS_dataset, name, symbol, units, description, format_string, type, fixed_value);
1407 if (type <= 0 || type > SDDS_NUM_TYPES) {
1408 SDDS_SetError("Unknown data type (SDDS_DefineParameter1)");
1409 return (-1);
1410 }
1411 buffer[SDDS_MAXLINE - 1] = 0;
1412 if (!SDDS_SprintTypedValue(fixed_value, 0, type, format_string, buffer, 0) || buffer[SDDS_MAXLINE - 1] != 0) {
1413 SDDS_SetError("Unable to define fixed value for parameter (SDDS_DefineParameter1)");
1414 return (-1);
1415 }
1416 return SDDS_DefineParameter(SDDS_dataset, name, symbol, units, description, format_string, type, buffer);
1417}
1418
1419/**
1420 * @brief Defines a data parameter with a fixed string value.
1421 *
1422 * This function processes the definition of a data parameter within the SDDS dataset. It allows
1423 * the specification of a fixed string value for the parameter, which remains constant across
1424 * all data entries. The function validates the parameter name, type, and format string before
1425 * defining the parameter in the dataset.
1426 *
1427 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1428 * @param[in] name A NULL-terminated string specifying the name of the parameter. This name must be unique within the dataset.
1429 * @param[in] symbol A NULL-terminated string specifying the symbol for the parameter. Pass @c NULL if no symbol is desired.
1430 * @param[in] units A NULL-terminated string specifying the units of the parameter. Pass @c NULL if no units are desired.
1431 * @param[in] description A NULL-terminated string providing a description of the parameter. Pass @c NULL if no description is desired.
1432 * @param[in] format_string A NULL-terminated string specifying the printf-style format for ASCII output. If @c NULL is passed, a default format is selected based on the parameter type.
1433 * @param[in] type An integer representing the data type of the parameter. Must be one of the following:
1434 * - @c SDDS_LONGDOUBLE
1435 * - @c SDDS_DOUBLE
1436 * - @c SDDS_FLOAT
1437 * - @c SDDS_LONG
1438 * - @c SDDS_ULONG
1439 * - @c SDDS_SHORT
1440 * - @c SDDS_USHORT
1441 * - @c SDDS_CHARACTER
1442 * - @c SDDS_STRING
1443 * @param[in] fixed_value A NULL-terminated string specifying the fixed value of the parameter. For non-string types, this string should be formatted appropriately using functions like @c sprintf.
1444 *
1445 * @return
1446 * - On success, returns the index of the newly defined parameter within the dataset.
1447 * - Returns @c -1 on failure, with an error message set internally.
1448 *
1449 * @pre
1450 * - The dataset must be initialized and configured for output.
1451 * - The parameter name must be unique and valid.
1452 * - The fixed value must be a valid string representation for the specified parameter type.
1453 *
1454 * @post
1455 * - The parameter is defined within the dataset with the specified attributes and fixed value.
1456 * - The dataset's internal structures are updated to include the new parameter.
1457 *
1458 * @note
1459 * - For numerical parameter types, the fixed value string should represent the numerical value correctly.
1460 * - The function internally handles the conversion of the fixed value string to the appropriate type based on the parameter's data type.
1461 *
1462 * @warning
1463 * - Defining a parameter with an invalid type or format string will result in an error.
1464 * - Passing an improperly formatted fixed value string for the specified type may lead to unexpected behavior.
1465 */
1466int32_t SDDS_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value) {
1467 SDDS_LAYOUT *layout;
1468 PARAMETER_DEFINITION *definition;
1469 char s[SDDS_MAXLINE];
1470 SORTED_INDEX *new_indexed_parameter;
1471 int32_t index, duplicate;
1472
1473 if (!SDDS_IsValidName(name, "parameter"))
1474 return -1;
1475 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DefineParameter"))
1476 return (-1);
1477 if (!name) {
1478 SDDS_SetError("NULL name not allowed for parameter definition");
1479 return (-1);
1480 }
1481 layout = &SDDS_dataset->layout;
1482 if (!(layout->parameter_definition =
1483 SDDS_Realloc(layout->parameter_definition, sizeof(*layout->parameter_definition) * (layout->n_parameters + 1))) ||
1484 !(layout->parameter_index = SDDS_Realloc(layout->parameter_index, sizeof(*layout->parameter_index) * (layout->n_parameters + 1))) || !(new_indexed_parameter = (SORTED_INDEX *)SDDS_Malloc(sizeof(*new_indexed_parameter)))) {
1485 SDDS_SetError("Memory allocation failure (SDDS_DefineParameter)");
1486 return (-1);
1487 }
1488 if (!SDDS_CopyString(&new_indexed_parameter->name, name))
1489 return -1;
1490 index = binaryInsert((void **)layout->parameter_index, layout->n_parameters, new_indexed_parameter, SDDS_CompareIndexedNames, &duplicate);
1491 if (duplicate) {
1492 sprintf(s, "Parameter %s already exists (SDDS_DefineParameter)", name);
1493 SDDS_SetError(s);
1494 return (-1);
1495 }
1496 layout->parameter_index[index]->index = layout->n_parameters;
1497
1498 if (!SDDS_ZeroMemory(definition = layout->parameter_definition + layout->n_parameters, sizeof(PARAMETER_DEFINITION))) {
1499 SDDS_SetError("Unable to define parameter--can't zero memory for parameter definition (SDDS_DefineParameter)");
1500 return (-1);
1501 }
1502 definition->name = new_indexed_parameter->name;
1503 if (symbol && !SDDS_CopyString(&definition->symbol, symbol)) {
1504 SDDS_SetError("Memory allocation failure (SDDS_DefineParameter)");
1505 return (-1);
1506 }
1507 if (units && !SDDS_CopyString(&definition->units, units)) {
1508 SDDS_SetError("Memory allocation failure (SDDS_DefineParameter)");
1509 return (-1);
1510 }
1511 if (description && !SDDS_CopyString(&definition->description, description)) {
1512 SDDS_SetError("Memory allocation failure (SDDS_DefineParameter)");
1513 return (-1);
1514 }
1515 if (type <= 0 || type > SDDS_NUM_TYPES) {
1516 SDDS_SetError("Unknown data type (SDDS_DefineParameter)");
1517 return (-1);
1518 }
1519 definition->type = type;
1520 if (format_string) {
1521 if (!SDDS_VerifyPrintfFormat(format_string, type)) {
1522 SDDS_SetError("Invalid format string (SDDS_DefineParameter)");
1523 return (-1);
1524 }
1525 if (!SDDS_CopyString(&definition->format_string, format_string)) {
1526 SDDS_SetError("Memory allocation failure (SDDS_DefineParameter)");
1527 return (-1);
1528 }
1529 }
1530 if (fixed_value && !SDDS_CopyString(&(definition->fixed_value), fixed_value)) {
1531 SDDS_SetError("Couldn't copy fixed_value string (SDDS_DefineParameter)");
1532 return (-1);
1533 }
1534 definition->definition_mode = SDDS_NORMAL_DEFINITION;
1535 if (type == SDDS_STRING)
1536 definition->memory_number = SDDS_CreateRpnMemory(name, 1);
1537 else
1538 definition->memory_number = SDDS_CreateRpnMemory(name, 0);
1539 layout->n_parameters += 1;
1540 return (layout->n_parameters - 1);
1541}
1542
1543/**
1544 * @brief Defines a data array within the SDDS dataset.
1545 *
1546 * This function processes the definition of a data array in the SDDS dataset. It allows the user
1547 * to specify the array's name, symbol, units, description, format string, data type, field length,
1548 * number of dimensions, and associated group name. The function ensures that the array name is valid
1549 * and unique within the dataset before defining it.
1550 *
1551 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1552 * @param[in] name A NULL-terminated string specifying the name of the array. This name must be unique within the dataset.
1553 * @param[in] symbol A NULL-terminated string specifying the symbol for the array. Pass @c NULL if no symbol is desired.
1554 * @param[in] units A NULL-terminated string specifying the units of the array. Pass @c NULL if no units are desired.
1555 * @param[in] description A NULL-terminated string providing a description of the array. Pass @c NULL if no description is desired.
1556 * @param[in] format_string A NULL-terminated string specifying the printf-style format for ASCII output. If @c NULL is passed, a default format is selected based on the array type.
1557 * @param[in] type An integer representing the data type of the array. Must be one of the following:
1558 * - @c SDDS_LONGDOUBLE
1559 * - @c SDDS_DOUBLE
1560 * - @c SDDS_FLOAT
1561 * - @c SDDS_LONG
1562 * - @c SDDS_ULONG
1563 * - @c SDDS_SHORT
1564 * - @c SDDS_USHORT
1565 * - @c SDDS_CHARACTER
1566 * - @c SDDS_STRING
1567 * @param[in] field_length An integer specifying the length of the field allotted to the array for ASCII output. If set to @c 0, the field length is ignored. If negative, the field length is set to the absolute value, and leading and trailing white-space are eliminated for @c SDDS_STRING types upon reading.
1568 * @param[in] dimensions An integer specifying the number of dimensions of the array. Must be greater than @c 0.
1569 * @param[in] group_name A NULL-terminated string specifying the name of the array group to which this array belongs. This allows related arrays to be grouped together (e.g., parallel arrays).
1570 *
1571 * @return
1572 * - On success, returns the index of the newly defined array within the dataset.
1573 * - Returns @c -1 on failure, with an error message set internally.
1574 *
1575 * @pre
1576 * - The dataset must be initialized and configured for output.
1577 * - The array name must be unique and valid.
1578 * - The specified data type must be supported by the dataset.
1579 *
1580 * @post
1581 * - The array is defined within the dataset with the specified attributes.
1582 * - The dataset's internal structures are updated to include the new array.
1583 *
1584 * @note
1585 * - For string-type arrays, the fixed value is managed differently, and leading/trailing white-space is handled based on the field length parameter.
1586 * - The function supports multi-dimensional arrays as specified by the @c dimensions parameter.
1587 *
1588 * @warning
1589 * - Defining an array with an invalid type, field length, or number of dimensions will result in an error.
1590 * - Attempting to define an array with a name that already exists within the dataset will result in an error.
1591 */
1592int32_t SDDS_DefineArray(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length, int32_t dimensions, const char *group_name) {
1593 SDDS_LAYOUT *layout;
1594 ARRAY_DEFINITION *definition;
1595 char s[SDDS_MAXLINE];
1596 SORTED_INDEX *new_indexed_array;
1597 int32_t index, duplicate;
1598
1599 if (!SDDS_IsValidName(name, "array"))
1600 return -1;
1601 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DefineArray"))
1602 return (-1);
1603 if (!name) {
1604 SDDS_SetError("NULL name not allowed for array definition");
1605 return (-1);
1606 }
1607 layout = &SDDS_dataset->layout;
1608 if (!(layout->array_definition =
1609 SDDS_Realloc(layout->array_definition, sizeof(*layout->array_definition) * (layout->n_arrays + 1))) ||
1610 !(layout->array_index = SDDS_Realloc(layout->array_index, sizeof(*layout->array_index) * (layout->n_arrays + 1))) || !(new_indexed_array = (SORTED_INDEX *)SDDS_Malloc(sizeof(*new_indexed_array)))) {
1611 SDDS_SetError("Memory allocation failure (SDDS_DefineArray)");
1612 return (-1);
1613 }
1614
1615 if (!SDDS_CopyString(&new_indexed_array->name, name))
1616 return -1;
1617 index = binaryInsert((void **)layout->array_index, layout->n_arrays, new_indexed_array, SDDS_CompareIndexedNames, &duplicate);
1618 if (duplicate) {
1619 sprintf(s, "Array %s already exists (SDDS_DefineArray)", name);
1620 SDDS_SetError(s);
1621 return (-1);
1622 }
1623 layout->array_index[index]->index = layout->n_arrays;
1624
1625 if (!SDDS_ZeroMemory(definition = layout->array_definition + layout->n_arrays, sizeof(ARRAY_DEFINITION))) {
1626 SDDS_SetError("Unable to define array--can't zero memory for array definition (SDDS_DefineArray)");
1627 return (-1);
1628 }
1629 definition->name = new_indexed_array->name;
1630 if ((symbol && !SDDS_CopyString(&definition->symbol, symbol)) || (units && !SDDS_CopyString(&definition->units, units)) || (description && !SDDS_CopyString(&definition->description, description)) || (group_name && !SDDS_CopyString(&definition->group_name, group_name))) {
1631 SDDS_SetError("Memory allocation failure (SDDS_DefineArray)");
1632 return (-1);
1633 }
1634 if (type <= 0 || type > SDDS_NUM_TYPES) {
1635 SDDS_SetError("Unknown data type (SDDS_DefineArray)");
1636 return (-1);
1637 }
1638 definition->type = type;
1639 if (format_string) {
1640 if (!SDDS_VerifyPrintfFormat(format_string, type)) {
1641 SDDS_SetError("Invalid format string (SDDS_DefineArray)");
1642 return (-1);
1643 }
1644 if (!SDDS_CopyString(&definition->format_string, format_string)) {
1645 SDDS_SetError("Memory allocation failure (SDDS_DefineArray)");
1646 return (-1);
1647 }
1648 }
1649 if ((definition->field_length = field_length) < 0 && type != SDDS_STRING) {
1650 SDDS_SetError("Invalid field length (SDDS_DefineArray)");
1651 return (-1);
1652 }
1653 if ((definition->dimensions = dimensions) < 1) {
1654 SDDS_SetError("Invalid number of dimensions for array (SDDS_DefineArray)");
1655 return (-1);
1656 }
1657 layout->n_arrays += 1;
1658 return (layout->n_arrays - 1);
1659}
1660
1661/**
1662 * @brief Defines a data column within the SDDS dataset.
1663 *
1664 * This function processes the definition of a data column in the SDDS dataset. It allows the user
1665 * to specify the column's name, symbol, units, description, format string, data type, and field length.
1666 * The function ensures that the column name is valid and unique within the dataset before defining it.
1667 *
1668 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1669 * @param[in] name A NULL-terminated string specifying the name of the column. This name must be unique within the dataset.
1670 * @param[in] symbol A NULL-terminated string specifying the symbol for the column. Pass @c NULL if no symbol is desired.
1671 * @param[in] units A NULL-terminated string specifying the units of the column. Pass @c NULL if no units are desired.
1672 * @param[in] description A NULL-terminated string providing a description of the column. Pass @c NULL if no description is desired.
1673 * @param[in] format_string A NULL-terminated string specifying the printf-style format for ASCII output. If @c NULL is passed, a default format is selected based on the column type.
1674 * @param[in] type An integer representing the data type of the column. Must be one of the following:
1675 * - @c SDDS_LONGDOUBLE
1676 * - @c SDDS_DOUBLE
1677 * - @c SDDS_FLOAT
1678 * - @c SDDS_LONG
1679 * - @c SDDS_ULONG
1680 * - @c SDDS_SHORT
1681 * - @c SDDS_USHORT
1682 * - @c SDDS_CHARACTER
1683 * - @c SDDS_STRING
1684 * @param[in] field_length An integer specifying the length of the field allotted to the column for ASCII output. If set to @c 0, the field length is ignored. If negative, the field length is set to the absolute value, and leading and trailing white-space are eliminated for @c SDDS_STRING types upon reading.
1685 *
1686 * @return
1687 * - On success, returns the index of the newly defined column within the dataset.
1688 * - Returns @c -1 on failure, with an error message set internally.
1689 *
1690 * @pre
1691 * - The dataset must be initialized and configured for output.
1692 * - The column name must be unique and valid.
1693 * - The specified data type must be supported by the dataset.
1694 *
1695 * @post
1696 * - The column is defined within the dataset with the specified attributes.
1697 * - The dataset's internal structures are updated to include the new column.
1698 * - If rows have already been allocated, the data arrays are resized to accommodate the new column.
1699 *
1700 * @note
1701 * - For string-type columns, the fixed value is managed differently, and leading/trailing white-space is handled based on the field length parameter.
1702 * - The function ensures that data arrays are appropriately resized if data has already been allocated.
1703 *
1704 * @warning
1705 * - Defining a column with an invalid type, field length, or name will result in an error.
1706 * - Attempting to define a column with a name that already exists within the dataset will result in an error.
1707 * - Memory allocation failures during the definition process will lead to an error.
1708 */
1709int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length) {
1710 SDDS_LAYOUT *layout;
1711 COLUMN_DEFINITION *definition;
1712 char s[SDDS_MAXLINE];
1713 SORTED_INDEX *new_indexed_column;
1714 int32_t index;
1715 int32_t duplicate;
1716
1717 if (!SDDS_IsValidName(name, "column"))
1718 return -1;
1719 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DefineColumn"))
1720 return (-1);
1721 if (!name) {
1722 SDDS_SetError("NULL name not allowed for column definition");
1723 return (-1);
1724 }
1725 layout = &SDDS_dataset->layout;
1726 if (!(layout->column_definition =
1727 SDDS_Realloc(layout->column_definition, sizeof(*layout->column_definition) * (layout->n_columns + 1))) ||
1728 !(layout->column_index = SDDS_Realloc(layout->column_index, sizeof(*layout->column_index) * (layout->n_columns + 1))) || !(new_indexed_column = (SORTED_INDEX *)SDDS_Malloc(sizeof(*new_indexed_column)))) {
1729 SDDS_SetError("Memory allocation failure (SDDS_DefineColumn)");
1730 return (-1);
1731 }
1732 if (!SDDS_CopyString(&new_indexed_column->name, name))
1733 return -1;
1734 index = binaryInsert((void **)layout->column_index, layout->n_columns, new_indexed_column, SDDS_CompareIndexedNames, &duplicate);
1735 if (duplicate) {
1736 sprintf(s, "Column %s already exists (SDDS_DefineColumn)", name);
1737 SDDS_SetError(s);
1738 return (-1);
1739 }
1740 layout->column_index[index]->index = layout->n_columns;
1741 if (!SDDS_ZeroMemory(definition = layout->column_definition + layout->n_columns, sizeof(COLUMN_DEFINITION))) {
1742 SDDS_SetError("Unable to define column--can't zero memory for column definition (SDDS_DefineColumn)");
1743 return (-1);
1744 }
1745 definition->name = new_indexed_column->name;
1746 if (symbol && !SDDS_CopyString(&definition->symbol, symbol)) {
1747 SDDS_SetError("Memory allocation failure (SDDS_DefineColumn)");
1748 return (-1);
1749 }
1750 if (units && !SDDS_CopyString(&definition->units, units)) {
1751 SDDS_SetError("Memory allocation failure (SDDS_DefineColumn)");
1752 return (-1);
1753 }
1754 if (description && !SDDS_CopyString(&definition->description, description)) {
1755 SDDS_SetError("Memory allocation failure (SDDS_DefineColumn)");
1756 return (-1);
1757 }
1758 if (type <= 0 || type > SDDS_NUM_TYPES) {
1759 SDDS_SetError("Unknown data type (SDDS_DefineColumn)");
1760 return (-1);
1761 }
1762 definition->type = type;
1763 if (format_string) {
1764 if (!SDDS_VerifyPrintfFormat(format_string, type)) {
1765 SDDS_SetError("Invalid format string (SDDS_DefineColumn)");
1766 return (-1);
1767 }
1768 if (!SDDS_CopyString(&definition->format_string, format_string)) {
1769 SDDS_SetError("Memory allocation failure (SDDS_DefineColumn)");
1770 return (-1);
1771 }
1772 }
1773 if ((definition->field_length = field_length) < 0 && type != SDDS_STRING) {
1774 SDDS_SetError("Invalid field length (SDDS_DefineColumn)");
1775 return (-1);
1776 }
1777
1778 if (SDDS_dataset->n_rows_allocated) {
1779 if (!SDDS_dataset->data) {
1780 SDDS_SetError("data array NULL but rows have been allocated! (SDDS_DefineColumn)");
1781 return (-1);
1782 }
1783 /* data already present--must resize data and parameter memory */
1784 if (!(SDDS_dataset->data = SDDS_Realloc(SDDS_dataset->data, sizeof(*SDDS_dataset->data) * (layout->n_columns + 1))) || !(SDDS_dataset->data[layout->n_columns] = calloc(SDDS_dataset->n_rows_allocated, SDDS_type_size[type - 1]))) {
1785 SDDS_SetError("Memory allocation failure (SDDS_DefineColumn)");
1786 return (-1);
1787 }
1788 }
1789
1790 /* not part of output: */
1791 definition->definition_mode = SDDS_NORMAL_DEFINITION;
1792 if (type == SDDS_STRING)
1793 definition->memory_number = SDDS_CreateRpnMemory(name, 1);
1794 else {
1795 definition->memory_number = SDDS_CreateRpnMemory(name, 0);
1796 }
1797 sprintf(s, "&%s", name);
1798 definition->pointer_number = SDDS_CreateRpnArray(s);
1799
1800 layout->n_columns += 1;
1801 return (layout->n_columns - 1);
1802}
1803
1804/**
1805 * @brief Defines a simple data column within the SDDS dataset.
1806 *
1807 * This function provides a simplified interface for defining a data column in the SDDS dataset.
1808 * It allows the user to specify only the column's name, units, and data type, while omitting optional
1809 * parameters such as symbol, description, format string, and field length. Internally, it calls
1810 * @c SDDS_DefineColumn with default values for the omitted parameters.
1811 *
1812 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1813 * @param[in] name A NULL-terminated string specifying the name of the column. This name must be unique within the dataset.
1814 * @param[in] unit A NULL-terminated string specifying the units of the column. Pass @c NULL if no units are desired.
1815 * @param[in] type An integer representing the data type of the column. Must be one of the following:
1816 * - @c SDDS_LONGDOUBLE
1817 * - @c SDDS_DOUBLE
1818 * - @c SDDS_FLOAT
1819 * - @c SDDS_LONG
1820 * - @c SDDS_ULONG
1821 * - @c SDDS_SHORT
1822 * - @c SDDS_USHORT
1823 * - @c SDDS_CHARACTER
1824 * - @c SDDS_STRING
1825 *
1826 * @return
1827 * - @c 1 on successful definition of the column.
1828 * - @c 0 on failure, with an error message set internally.
1829 *
1830 * @pre
1831 * - The dataset must be initialized and configured for output.
1832 * - The column name must be unique and valid.
1833 *
1834 * @post
1835 * - The column is defined within the dataset with the specified name, units, and type.
1836 * - The dataset's internal structures are updated to include the new column.
1837 *
1838 * @note
1839 * - This function is intended for scenarios where only basic column attributes are needed.
1840 * - Optional parameters such as symbol, description, format string, and field length are set to default values.
1841 *
1842 * @warning
1843 * - Defining a column with an invalid type or name will result in an error.
1844 * - Attempting to define a column with a name that already exists within the dataset will result in an error.
1845 */
1846int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type) {
1847 if (SDDS_DefineColumn(SDDS_dataset, name, NULL, unit, NULL, NULL, type, 0) < 0)
1848 return 0;
1849 return (1);
1850}
1851
1852/**
1853 * @brief Defines a simple data parameter within the SDDS dataset.
1854 *
1855 * This function provides a simplified interface for defining a data parameter in the SDDS dataset.
1856 * It allows the user to specify only the parameter's name, units, and data type, while omitting
1857 * optional attributes such as symbol, description, format string, and fixed value. Internally,
1858 * it calls @c SDDS_DefineParameter with default values for the omitted parameters.
1859 *
1860 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1861 * @param[in] name A NULL-terminated string specifying the name of the parameter. This name must be unique within the dataset.
1862 * @param[in] unit A NULL-terminated string specifying the units of the parameter. Pass @c NULL if no units are desired.
1863 * @param[in] type An integer representing the data type of the parameter. Must be one of the following:
1864 * - @c SDDS_LONGDOUBLE
1865 * - @c SDDS_DOUBLE
1866 * - @c SDDS_FLOAT
1867 * - @c SDDS_LONG
1868 * - @c SDDS_ULONG
1869 * - @c SDDS_SHORT
1870 * - @c SDDS_USHORT
1871 * - @c SDDS_CHARACTER
1872 * - @c SDDS_STRING
1873 *
1874 * @return
1875 * - @c 1 on successful definition of the parameter.
1876 * - @c 0 on failure, with an error message set internally.
1877 *
1878 * @pre
1879 * - The dataset must be initialized and configured for output.
1880 * - The parameter name must be unique and valid.
1881 *
1882 * @post
1883 * - The parameter is defined within the dataset with the specified name, units, and type.
1884 * - The dataset's internal structures are updated to include the new parameter.
1885 *
1886 * @note
1887 * - This function is intended for scenarios where only basic parameter attributes are needed.
1888 * - Optional parameters such as symbol, description, format string, and fixed value are set to default values.
1889 *
1890 * @warning
1891 * - Defining a parameter with an invalid type or name will result in an error.
1892 * - Attempting to define a parameter with a name that already exists within the dataset will result in an error.
1893 */
1894int32_t SDDS_DefineSimpleParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type) {
1895 if (SDDS_DefineParameter(SDDS_dataset, name, NULL, unit, NULL, NULL, type, NULL) < 0)
1896 return 0;
1897 return (1);
1898}
1899
1900/**
1901 * @brief Defines multiple simple data columns of the same data type within the SDDS dataset.
1902 *
1903 * This function provides a streamlined way to define multiple data columns in the SDDS dataset that share
1904 * the same data type. It allows the user to specify the names and units of the columns, while omitting
1905 * optional attributes such as symbol, description, format string, and field length. Internally, it calls
1906 * @c SDDS_DefineColumn for each column with default values for the omitted parameters.
1907 *
1908 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1909 * @param[in] number The number of columns to define. Must be greater than or equal to @c 0.
1910 * @param[in] name An array of NULL-terminated strings specifying the names of the columns. Each name must be unique within the dataset.
1911 * @param[in] unit An array of NULL-terminated strings specifying the units of the columns. Pass @c NULL for elements where no units are desired.
1912 * @param[in] type An integer representing the data type for all the columns. Must be one of the following:
1913 * - @c SDDS_LONGDOUBLE
1914 * - @c SDDS_DOUBLE
1915 * - @c SDDS_FLOAT
1916 * - @c SDDS_LONG
1917 * - @c SDDS_ULONG
1918 * - @c SDDS_SHORT
1919 * - @c SDDS_USHORT
1920 * - @c SDDS_CHARACTER
1921 * - @c SDDS_STRING
1922 *
1923 * @return
1924 * - @c 1 on successful definition of all specified columns.
1925 * - @c 0 on failure to define any of the columns, with an error message set internally.
1926 *
1927 * @pre
1928 * - The dataset must be initialized and configured for output.
1929 * - The @c name array must contain unique and valid names for each column.
1930 * - The @c type must be a supported data type.
1931 *
1932 * @post
1933 * - All specified columns are defined within the dataset with the provided names and units.
1934 * - The dataset's internal structures are updated to include the new columns.
1935 *
1936 * @note
1937 * - Passing @c number as @c 0 results in no action and returns success.
1938 * - This function is optimized for defining multiple columns of the same type, enhancing code readability and efficiency.
1939 *
1940 * @warning
1941 * - Defining a column with an invalid type or name will result in an error.
1942 * - Attempting to define a column with a name that already exists within the dataset will result in an error.
1943 * - Ensure that the @c name and @c unit arrays are properly allocated and contain valid strings.
1944 */
1945int32_t SDDS_DefineSimpleColumns(SDDS_DATASET *SDDS_dataset, int32_t number, char **name, char **unit, int32_t type) {
1946 int32_t i;
1947 if (!number)
1948 return (1);
1949 if (!name)
1950 return 0;
1951 for (i = 0; i < number; i++)
1952 if (SDDS_DefineColumn(SDDS_dataset, name[i], NULL, unit ? unit[i] : NULL, NULL, NULL, type, 0) < 0)
1953 return 0;
1954 return (1);
1955}
1956
1957/**
1958 * @brief Defines multiple simple data parameters of the same data type within the SDDS dataset.
1959 *
1960 * This function provides a streamlined way to define multiple data parameters in the SDDS dataset that share
1961 * the same data type. It allows the user to specify the names and units of the parameters, while omitting
1962 * optional attributes such as symbol, description, format string, and fixed value. Internally, it calls
1963 * @c SDDS_DefineParameter for each parameter with default values for the omitted parameters.
1964 *
1965 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
1966 * @param[in] number The number of parameters to define. Must be greater than or equal to @c 0.
1967 * @param[in] name An array of NULL-terminated strings specifying the names of the parameters. Each name must be unique within the dataset.
1968 * @param[in] unit An array of NULL-terminated strings specifying the units of the parameters. Pass @c NULL for elements where no units are desired.
1969 * @param[in] type An integer representing the data type for all the parameters. Must be one of the following:
1970 * - @c SDDS_LONGDOUBLE
1971 * - @c SDDS_DOUBLE
1972 * - @c SDDS_FLOAT
1973 * - @c SDDS_LONG
1974 * - @c SDDS_ULONG
1975 * - @c SDDS_SHORT
1976 * - @c SDDS_USHORT
1977 * - @c SDDS_CHARACTER
1978 * - @c SDDS_STRING
1979 *
1980 * @return
1981 * - @c 1 on successful definition of all specified parameters.
1982 * - @c 0 on failure to define any of the parameters, with an error message set internally.
1983 *
1984 * @pre
1985 * - The dataset must be initialized and configured for output.
1986 * - The @c name array must contain unique and valid names for each parameter.
1987 * - The @c type must be a supported data type.
1988 *
1989 * @post
1990 * - All specified parameters are defined within the dataset with the provided names and units.
1991 * - The dataset's internal structures are updated to include the new parameters.
1992 *
1993 * @note
1994 * - Passing @c number as @c 0 results in no action and returns success.
1995 * - This function is optimized for defining multiple parameters of the same type, enhancing code readability and efficiency.
1996 *
1997 * @warning
1998 * - Defining a parameter with an invalid type or name will result in an error.
1999 * - Attempting to define a parameter with a name that already exists within the dataset will result in an error.
2000 * - Ensure that the @c name and @c unit arrays are properly allocated and contain valid strings.
2001 */
2002int32_t SDDS_DefineSimpleParameters(SDDS_DATASET *SDDS_dataset, int32_t number, char **name, char **unit, int32_t type) {
2003 int32_t i;
2004 if (!number)
2005 return (1);
2006 if (!name)
2007 return 0;
2008 for (i = 0; i < number; i++)
2009 if (SDDS_DefineParameter(SDDS_dataset, name[i], NULL, unit ? unit[i] : NULL, NULL, NULL, type, NULL) < 0)
2010 return 0;
2011 return (1);
2012}
2013
2014static uint32_t nameValidityFlags = 0;
2015/**
2016 * @brief Sets the validity flags for parameter and column names in the SDDS dataset.
2017 *
2018 * This function allows the user to configure the rules for validating names of parameters and columns
2019 * within the SDDS dataset. The validity flags determine the set of allowed characters and naming conventions.
2020 *
2021 * @param[in] flags A bitmask representing the desired name validity flags. Possible flags include:
2022 * - @c SDDS_ALLOW_ANY_NAME: Allows any name without restrictions.
2023 * - @c SDDS_ALLOW_V15_NAME: Enables compatibility with SDDS version 1.5 naming conventions.
2024 * - Additional flags as defined in the SDDS library.
2025 *
2026 * @return
2027 * - The previous name validity flags before the update.
2028 *
2029 * @pre
2030 * - The function can be called at any time before defining parameters or columns to influence name validation.
2031 *
2032 * @post
2033 * - The name validity flags are updated to reflect the specified rules.
2034 *
2035 * @note
2036 * - Changing name validity flags affects how subsequent parameter and column names are validated.
2037 * - It is recommended to set the desired validity flags before defining any dataset elements to avoid validation errors.
2038 *
2039 * @warning
2040 * - Improperly setting validity flags may lead to unintended acceptance or rejection of valid or invalid names.
2041 * - Ensure that the flags are set according to the desired naming conventions for your dataset.
2042 */
2043int32_t SDDS_SetNameValidityFlags(uint32_t flags) {
2044 uint32_t oldFlags;
2045 oldFlags = nameValidityFlags;
2046 nameValidityFlags = flags;
2047 return oldFlags;
2048}
2049
2050/**
2051 * @brief Checks if a given name is valid for a specified class within the SDDS dataset.
2052 *
2053 * This function validates whether the provided name adheres to the naming conventions and rules
2054 * defined by the current name validity flags for the specified class (e.g., parameter, column).
2055 * It ensures that the name contains only allowed characters and follows the required structure.
2056 *
2057 * @param[in] name The name to be validated. Must be a NULL-terminated string.
2058 * @param[in] class The class type to which the name belongs (e.g., "parameter", "column"). This is used
2059 * primarily for error reporting.
2060 *
2061 * @return
2062 * - @c 1 if the name is valid for the specified class.
2063 * - @c 0 if the name is invalid, with an error message set internally.
2064 *
2065 * @pre
2066 * - The name must be a valid NULL-terminated string.
2067 * - The class must be a valid NULL-terminated string representing a recognized class type.
2068 *
2069 * @post
2070 * - If the name is invalid, an error message is recorded detailing the reason.
2071 *
2072 * @note
2073 * - The validation rules are influenced by the current name validity flags set via @c SDDS_SetNameValidityFlags.
2074 * - Environment variables or other configuration settings may also affect name validity.
2075 *
2076 * @warning
2077 * - Using names that do not adhere to the validation rules will result in parameters or columns not being defined.
2078 * - Ensure that all names meet the required standards before attempting to define dataset elements.
2079 */
2080int32_t SDDS_IsValidName(const char *name, const char *class) {
2081 char *ptr;
2082 int32_t isValid = 1;
2083 char s[SDDS_MAXLINE];
2084 static char *validChars = "@:#+%-._$&/[]";
2085 static char *startChars = ".:";
2086
2087 if (nameValidityFlags & SDDS_ALLOW_ANY_NAME)
2088 return 1;
2089 ptr = (char *)name;
2090 if (strlen(name) == 0)
2091 isValid = 0;
2092 else if (!(nameValidityFlags & SDDS_ALLOW_V15_NAME)) {
2093 /* post V1.5 allows only alpha and startChars members as first character */
2094 /* V1.5 allows alpha, digits, and any validChars members */
2095 if (!(isalpha(*ptr) || strchr(startChars, *ptr)))
2096 isValid = 0;
2097 }
2098 while (isValid && *ptr) {
2099 if (!(isalnum(*ptr) || strchr(validChars, *ptr)))
2100 isValid = 0;
2101 ptr++;
2102 }
2103 if (!isValid) {
2104 sprintf(s, "The following %s name is invalid: >%s<\n(sddsconvert may be used to change the name)\n", class, name);
2105 SDDS_SetError(s);
2106 return 0;
2107 }
2108 return 1;
2109}
2110
2111/**
2112 * @brief Defines an associate for the SDDS dataset.
2113 *
2114 * This function defines an associate for the SDDS dataset, allowing the association of additional
2115 * files or data with the primary dataset. Associates can provide supplementary information or link
2116 * related datasets together. The function sets up the necessary attributes such as name, filename,
2117 * path, description, contents, and SDDS flag to describe the associate.
2118 *
2119 * **Note:** This function is **NOT USED** in the current implementation and will always return @c 0
2120 * unless compiled with @c RW_ASSOCIATES defined.
2121 *
2122 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
2123 * @param[in] name A NULL-terminated string specifying the name of the associate. This name must be unique within the dataset.
2124 * @param[in] filename A NULL-terminated string specifying the filename of the associate. Must be a valid filename.
2125 * @param[in] path A NULL-terminated string specifying the path to the associate. Pass @c NULL if no path is desired.
2126 * @param[in] description A NULL-terminated string providing a description of the associate. Pass @c NULL if no description is desired.
2127 * @param[in] contents A NULL-terminated string detailing the contents of the associate. Pass @c NULL if no contents are desired.
2128 * @param[in] sdds An integer flag indicating the type of associate. Typically used to specify whether the associate is an SDDS file.
2129 *
2130 * @return
2131 * - On success, returns the index of the newly defined associate within the dataset.
2132 * - Returns a negative value on failure, with an error message set internally.
2133 * - Returns @c 0 if @c RW_ASSOCIATES is not defined.
2134 *
2135 * @pre
2136 * - The dataset must be initialized and configured for output.
2137 * - @c RW_ASSOCIATES must be defined during compilation to use this feature.
2138 * - The associate name and filename must be unique and valid.
2139 *
2140 * @post
2141 * - The associate is defined within the dataset with the specified attributes.
2142 * - The dataset's internal structures are updated to include the new associate.
2143 *
2144 * @note
2145 * - Associates provide a mechanism to link additional data or files to the primary SDDS dataset.
2146 * - Properly defining associates can enhance data organization and accessibility.
2147 *
2148 * @warning
2149 * - Defining an associate with an invalid type, name, or filename will result in an error.
2150 * - Attempting to define an associate with a name that already exists within the dataset will result in an error.
2151 * - Ensure that the @c filename and @c path (if provided) are valid and accessible.
2152 */
2153int32_t SDDS_DefineAssociate(SDDS_DATASET *SDDS_dataset, const char *name, const char *filename, const char *path, const char *description, const char *contents, int32_t sdds) {
2154
2155#if RW_ASSOCIATES == 0
2156 return 0;
2157#else
2158 SDDS_LAYOUT *layout;
2159 ASSOCIATE_DEFINITION *definition;
2160 char s[SDDS_MAXLINE];
2161 if (!SDDS_IsValidName(name, "associate"))
2162 return -1;
2163 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DefineAssociate"))
2164 return (-1);
2165 layout = &SDDS_dataset->layout;
2166 if (!(layout->associate_definition = SDDS_Realloc(layout->associate_definition, sizeof(*layout->associate_definition) * (layout->n_associates + 1)))) {
2167 SDDS_SetError("Memory allocation failure (SDDS_DefineAssociate)");
2168 return (-1);
2169 }
2170 if (!name) {
2171 SDDS_SetError("NULL name not allowed for associate file (SDDS_DefineAssociate)");
2172 return (-1);
2173 }
2174 if (!filename) {
2175 SDDS_SetError("NULL filename not allowed for associate file (SDDS_DefineAssociate)");
2176 return (-1);
2177 }
2178 if (SDDS_GetAssociateIndex(SDDS_dataset, name) >= 0) {
2179 sprintf(s, "Associate with name %s already exists (SDDS_DefineAssociate)", name);
2180 SDDS_SetError(s);
2181 return (-1);
2182 }
2183 if (!SDDS_ZeroMemory(definition = layout->associate_definition + layout->n_associates, sizeof(ASSOCIATE_DEFINITION))) {
2184 SDDS_SetError("Unable to define associate--can't zero memory for associate (SDDS_DefineAssociate)");
2185 return (-1);
2186 }
2187
2188 if (!SDDS_CopyString(&definition->name, name)) {
2189 SDDS_SetError("Memory allocation failure (SDDS_DefineAssociate)");
2190 return (-1);
2191 }
2192 if (!SDDS_CopyString(&definition->filename, filename)) {
2193 SDDS_SetError("Memory allocation failure (SDDS_DefineAssociate)");
2194 return (-1);
2195 }
2196 if (path && !SDDS_CopyString(&definition->path, path)) {
2197 SDDS_SetError("Memory allocation failure (SDDS_DefineAssociate)");
2198 return (-1);
2199 }
2200 if (contents && !SDDS_CopyString(&definition->contents, contents)) {
2201 SDDS_SetError("Memory allocation failure (SDDS_DefineAssociate)");
2202 return (-1);
2203 }
2204 if (description && !SDDS_CopyString(&definition->description, description)) {
2205 SDDS_SetError("Memory allocation failure (SDDS_DefineAssociate)");
2206 return (-1);
2207 }
2208 definition->sdds = sdds;
2209 layout->n_associates += 1;
2210 return (layout->n_associates - 1);
2211#endif
2212}
2213
2214/**
2215 * @brief Erases all data entries in the SDDS dataset.
2216 *
2217 * This function removes all data from the specified SDDS dataset, effectively resetting it to an empty state.
2218 * It frees any allocated memory associated with data columns, parameters, and arrays, ensuring that
2219 * all dynamic data is properly cleared. This is useful for reusing the dataset for new data without
2220 * retaining previous entries.
2221 *
2222 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
2223 *
2224 * @return
2225 * - @c 1 on successful erasure of all data.
2226 * - @c 0 on failure, with an error message set internally.
2227 *
2228 * @pre
2229 * - The dataset must be initialized and configured.
2230 *
2231 * @post
2232 * - All data rows are removed from the dataset.
2233 * - Memory allocated for data columns, parameters, and arrays is freed.
2234 * - The dataset is ready to accept new data entries.
2235 *
2236 * @note
2237 * - This function does not alter the dataset's layout definitions; only the data entries are cleared.
2238 * - After erasing data, the dataset can be reused to write new data tables without redefining the layout.
2239 *
2240 * @warning
2241 * - Erasing data is irreversible; ensure that any necessary data is backed up before calling this function.
2242 * - Concurrent access to the dataset while erasing data may lead to undefined behavior.
2243 */
2244int32_t SDDS_EraseData(SDDS_DATASET *SDDS_dataset) {
2245 SDDS_LAYOUT *layout;
2246 int64_t i, j;
2247 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_EraseData"))
2248 return 0;
2249 layout = &SDDS_dataset->layout;
2250 if (SDDS_dataset->data) {
2251 for (i = 0; i < layout->n_columns; i++) {
2252 if (!SDDS_dataset->data[i])
2253 continue;
2254 if (layout->column_definition[i].type == SDDS_STRING) {
2255 for (j = 0; j < SDDS_dataset->n_rows; j++) {
2256 if (((char **)SDDS_dataset->data[i])[j]) {
2257 free(((char **)SDDS_dataset->data[i])[j]);
2258 ((char **)SDDS_dataset->data[i])[j] = NULL;
2259 }
2260 }
2261 }
2262 }
2263 }
2264 SDDS_dataset->n_rows = 0;
2265
2266 if (SDDS_dataset->parameter) {
2267 for (i = 0; i < layout->n_parameters; i++) {
2268 if (!SDDS_dataset->parameter[i])
2269 continue;
2270 if (layout->parameter_definition[i].type == SDDS_STRING && *(char **)(SDDS_dataset->parameter[i])) {
2271 free(*(char **)(SDDS_dataset->parameter[i]));
2272 *(char **)SDDS_dataset->parameter[i] = NULL;
2273 }
2274 }
2275 }
2276
2277 if (SDDS_dataset->array) {
2278 for (i = 0; i < layout->n_arrays; i++) {
2279 if (SDDS_dataset->array[i].definition->type == SDDS_STRING) {
2280 for (j = 0; j < SDDS_dataset->array[i].elements; j++) {
2281 if (((char **)SDDS_dataset->array[i].data)[j]) {
2282 free(((char **)SDDS_dataset->array[i].data)[j]);
2283 ((char **)SDDS_dataset->array[i].data)[j] = NULL;
2284 }
2285 }
2286 }
2287 }
2288 }
2289
2290 return (1);
2291}
2292
2293/**
2294 * @brief Sets the row count mode for the SDDS dataset.
2295 *
2296 * This function configures how row counts are managed within the SDDS dataset. The row count mode
2297 * determines whether row counts are variable, fixed, or entirely omitted during data writing.
2298 * Proper configuration of row count modes can enhance data integrity and performance based on
2299 * specific use cases.
2300 *
2301 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
2302 * @param[in] mode The row count mode to be set. Must be one of the following:
2303 * - @c SDDS_VARIABLEROWCOUNT: Enables variable row counts, allowing the number of rows to vary.
2304 * - @c SDDS_FIXEDROWCOUNT: Sets a fixed row count mode, where the number of rows is constant.
2305 * - @c SDDS_NOROWCOUNT: Disables row counts, omitting them from the dataset.
2306 *
2307 * @return
2308 * - @c 1 on successful configuration of the row count mode.
2309 * - @c 0 on failure, with an error message set internally.
2310 *
2311 * @pre
2312 * - The dataset must be initialized and configured for output.
2313 * - The layout must not have been written to the file yet.
2314 *
2315 * @post
2316 * - The dataset's row count mode is updated according to the specified mode.
2317 *
2318 * @note
2319 * - Changing the row count mode affects how row metadata is handled during data writing.
2320 * - The @c SDDS_FIXEDROWCOUNT mode may require specifying additional parameters such as row increment.
2321 *
2322 * @warning
2323 * - Attempting to change the row count mode after the layout has been written to the file or while reading from a file will result in an error.
2324 * - Selecting an invalid row count mode will result in an error.
2325 */
2326int32_t SDDS_SetRowCountMode(SDDS_DATASET *SDDS_dataset, uint32_t mode) {
2327 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetRowCountMode"))
2328 return 0;
2329 if (SDDS_dataset->layout.layout_written) {
2330 SDDS_SetError("Can't change row count mode after writing the layout, or for a file you are reading.");
2331 return 0;
2332 }
2333 if (mode & SDDS_VARIABLEROWCOUNT) {
2334 SDDS_dataset->layout.data_mode.fixed_row_count = 0;
2335 SDDS_dataset->layout.data_mode.no_row_counts = 0;
2336 } else if (mode & SDDS_FIXEDROWCOUNT) {
2337 SDDS_dataset->layout.data_mode.fixed_row_count = 1;
2338 SDDS_dataset->layout.data_mode.fixed_row_increment = 500;
2339 SDDS_dataset->layout.data_mode.no_row_counts = 0;
2340 SDDS_dataset->layout.data_mode.fsync_data = 0;
2341 } else if (mode & SDDS_NOROWCOUNT) {
2342 SDDS_dataset->layout.data_mode.fixed_row_count = 0;
2343 SDDS_dataset->layout.data_mode.no_row_counts = 1;
2344 } else {
2345 SDDS_SetError("Invalid row count mode (SDDS_SetRowCountMode).");
2346 return 0;
2347 }
2348 if (!SDDS_SaveLayout(SDDS_dataset))
2349 return 0;
2350 return 1;
2351}
2352
2353/**
2354 * @brief Disables file synchronization for the SDDS dataset.
2355 *
2356 * This function disables the file synchronization feature for the specified SDDS dataset. File synchronization
2357 * ensures that all buffered data is immediately written to disk, enhancing data integrity. By disabling
2358 * this feature, the dataset will no longer perform synchronous writes, which can improve performance
2359 * but may risk data loss in the event of a system failure.
2360 *
2361 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
2362 *
2363 * @post
2364 * - File synchronization is disabled, meaning that @c SDDS_SyncDataSet will not call @c fsync.
2365 *
2366 * @note
2367 * - Disabling file synchronization can lead to improved performance, especially when writing large datasets.
2368 * - It is recommended to use this function only when performance is a higher priority than immediate data integrity.
2369 *
2370 * @warning
2371 * - Without file synchronization, there is a risk of data loss if the system crashes before buffered data is written to disk.
2372 * - Ensure that data integrity is managed through other means if synchronization is disabled.
2373 */
2374void SDDS_DisableFSync(SDDS_DATASET *SDDS_dataset) {
2375 SDDS_dataset->layout.data_mode.fsync_data = 0;
2376}
2377
2378/**
2379 * @brief Enables file synchronization for the SDDS dataset.
2380 *
2381 * This function enables the file synchronization feature for the specified SDDS dataset. File synchronization
2382 * ensures that all buffered data is immediately written to disk, enhancing data integrity. Enabling this
2383 * feature can be crucial for applications where data consistency and reliability are paramount.
2384 *
2385 * @param[in,out] SDDS_dataset Pointer to the SDDS_DATASET structure representing the dataset.
2386 *
2387 * @post
2388 * - File synchronization is enabled, meaning that @c SDDS_SyncDataSet will call @c fsync to flush buffers to disk.
2389 *
2390 * @note
2391 * - Enabling file synchronization may impact performance due to the increased number of disk write operations.
2392 * - It is recommended to enable synchronization when data integrity is critical, such as in transactional systems.
2393 *
2394 * @warning
2395 * - Frequent synchronization can lead to reduced performance, especially when writing large amounts of data.
2396 * - Balance the need for data integrity with performance requirements based on the specific use case.
2397 */
2398void SDDS_EnableFSync(SDDS_DATASET *SDDS_dataset) {
2399 SDDS_dataset->layout.data_mode.fsync_data = 1;
2400}
2401
2402/**
2403 * @brief Synchronizes the SDDS dataset's file to disk.
2404 *
2405 * Performs a file synchronization operation on the specified SDDS dataset to ensure that
2406 * all buffered data is flushed to the storage medium. This is crucial for maintaining
2407 * data integrity, especially in scenarios where unexpected shutdowns or crashes may occur.
2408 *
2409 * ## Platform-Specific Behavior
2410 * - **vxWorks, Windows (_WIN32), macOS (__APPLE__)**:
2411 * - The function assumes that synchronization is always successful and returns `1`.
2412 * - **Other Platforms**:
2413 * - Attempts to flush the dataset's file buffer to disk using the `fsync` system call.
2414 * - Returns `1` if `fsync` succeeds, indicating successful synchronization.
2415 * - Returns `0` if `fsync` fails or if the dataset/file pointer is invalid.
2416 *
2417 * @param[in] SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset
2418 * to be synchronized.
2419 * @return int32_t
2420 * - `1` on successful synchronization.
2421 * - `0` on failure.
2422 */
2423int32_t SDDS_DoFSync(SDDS_DATASET *SDDS_dataset) {
2424#if defined(vxWorks) || defined(_WIN32) || defined(__APPLE__)
2425 return 1;
2426#else
2427 if (SDDS_dataset && SDDS_dataset->layout.fp)
2428 return fsync(fileno(SDDS_dataset->layout.fp)) == 0;
2429 return 0;
2430#endif
2431}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_UpdateAsciiPage(SDDS_DATASET *SDDS_dataset, uint32_t mode)
Updates the current ASCII page of an SDDS dataset with new data.
int32_t SDDS_WriteAsciiPage(SDDS_DATASET *SDDS_dataset)
Writes a page of data in ASCII format to the SDDS dataset.
Definition SDDS_ascii.c:410
int32_t SDDS_SetDefaultIOBufferSize(int32_t newValue)
Definition SDDS_binary.c:66
void SDDS_SwapLong64(int64_t *data)
Swaps the endianness of a 64-bit integer.
int32_t SDDS_UpdateBinaryPage(SDDS_DATASET *SDDS_dataset, uint32_t mode)
Updates the binary page of an SDDS dataset.
void SDDS_SwapLong(int32_t *data)
Swaps the endianness of a 32-bit integer.
int32_t SDDS_WriteBinaryPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_SaveLayout(SDDS_DATASET *SDDS_dataset)
Definition SDDS_copy.c:615
int32_t SDDS_type_size[SDDS_NUM_TYPES]
Array of sizes for each supported data type.
Definition SDDS_data.c:62
char * SDDS_data_mode[SDDS_NUM_DATA_MODES]
Array of supported data modes.
Definition SDDS_data.c:33
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_ReadLayout(SDDS_DATASET *SDDS_dataset, FILE *fp)
Definition SDDS_input.c:517
int32_t SDDS_ReadPageSparse(SDDS_DATASET *SDDS_dataset, uint32_t mode, int64_t sparse_interval, int64_t sparse_offset, int32_t sparse_statistics)
Internal definitions and function declarations for SDDS with LZMA support.
int32_t SDDS_LZMAWriteVersion(int32_t version_number, struct lzmafile *lzmafp)
Writes the SDDS protocol version to an LZMA-compressed file.
Definition SDDS_write.c:77
int32_t SDDS_LZMAWriteArrayDefinition(ARRAY_DEFINITION *array_definition, struct lzmafile *lzmafp)
Writes an array definition to an LZMA-compressed file.
Definition SDDS_write.c:722
int32_t SDDS_LZMAWriteColumnDefinition(COLUMN_DEFINITION *column, struct lzmafile *lzmafp)
Writes a column definition to an LZMA-compressed file.
Definition SDDS_write.c:356
int32_t SDDS_WriteAssociateDefinition(ASSOCIATE_DEFINITION *associate, FILE *fp)
Writes an associate definition to a standard file.
Definition SDDS_write.c:493
int32_t SDDS_LZMAWriteDescription(char *description, char *contents, struct lzmafile *lzmafp)
Writes the SDDS description section to an LZMA-compressed file.
Definition SDDS_write.c:280
int32_t SDDS_WriteVersion(int32_t version_number, FILE *fp)
Writes the SDDS protocol version to a standard file.
Definition SDDS_write.c:59
int32_t SDDS_WriteColumnDefinition(COLUMN_DEFINITION *column, FILE *fp)
Writes a column definition to a standard file.
Definition SDDS_write.c:329
int32_t SDDS_LZMAWriteDataMode(SDDS_LAYOUT *layout, struct lzmafile *lzmafp)
Writes the data mode section to an LZMA-compressed file.
Definition SDDS_write.c:614
int32_t SDDS_WriteArrayDefinition(ARRAY_DEFINITION *array_definition, FILE *fp)
Writes an array definition to a standard file.
Definition SDDS_write.c:692
int32_t SDDS_LZMAWriteAssociateDefinition(ASSOCIATE_DEFINITION *associate, struct lzmafile *lzmafp)
Writes an associate definition to an LZMA-compressed file.
Definition SDDS_write.c:520
int32_t SDDS_WriteDataMode(SDDS_LAYOUT *layout, FILE *fp)
Writes the data mode section to a standard file.
Definition SDDS_write.c:576
int32_t SDDS_WriteParameterDefinition(PARAMETER_DEFINITION *parameter, FILE *fp)
Writes a parameter definition to a standard file.
Definition SDDS_write.c:411
int32_t SDDS_WriteDescription(char *description, char *contents, FILE *fp)
Writes the SDDS description section to a standard file.
Definition SDDS_write.c:256
int32_t SDDS_LZMAWriteParameterDefinition(PARAMETER_DEFINITION *parameter, struct lzmafile *lzmafp)
Writes a parameter definition to an LZMA-compressed file.
Definition SDDS_write.c:438
void SDDS_DisableFSync(SDDS_DATASET *SDDS_dataset)
Disables file synchronization for the SDDS dataset.
int32_t SDDS_DefineParameter1(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, void *fixed_value)
Defines a data parameter with a fixed numerical value.
int32_t SDDS_InitializeAppend(SDDS_DATASET *SDDS_dataset, const char *filename)
Initializes the SDDS dataset for appending data by adding a new page to an existing file.
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_InitializeAppendToPage(SDDS_DATASET *SDDS_dataset, const char *filename, int64_t updateInterval, int64_t *rowsPresentReturn)
Initializes the SDDS dataset for appending data to the last page of an existing file.
int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_EraseData(SDDS_DATASET *SDDS_dataset)
Erases all data entries in the SDDS dataset.
int32_t SDDS_DisconnectFile(SDDS_DATASET *SDDS_dataset)
Disconnects the SDDS dataset from its associated file.
Definition SDDS_output.c:70
int32_t SDDS_SyncDataSet(SDDS_DATASET *SDDS_dataset)
Synchronizes the SDDS dataset with the disk by flushing buffered data.
int32_t SDDS_DefineAssociate(SDDS_DATASET *SDDS_dataset, const char *name, const char *filename, const char *path, const char *description, const char *contents, int32_t sdds)
Defines an associate for the SDDS dataset.
int32_t SDDS_Parallel_InitializeOutput(SDDS_DATASET *SDDS_dataset, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset for parallel processing.
void SDDS_EnableFSync(SDDS_DATASET *SDDS_dataset)
Enables file synchronization for the SDDS dataset.
int32_t SDDS_DefineSimpleParameters(SDDS_DATASET *SDDS_dataset, int32_t number, char **name, char **unit, int32_t type)
Defines multiple simple data parameters of the same data type within the SDDS dataset.
int32_t SDDS_DefineSimpleParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data parameter within the SDDS dataset.
int32_t SDDS_SetRowCountMode(SDDS_DATASET *SDDS_dataset, uint32_t mode)
Sets the row count mode for the SDDS dataset.
int32_t SDDS_DefineArray(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length, int32_t dimensions, const char *group_name)
Defines a data array within the SDDS dataset.
int32_t SDDS_DefineSimpleColumns(SDDS_DATASET *SDDS_dataset, int32_t number, char **name, char **unit, int32_t type)
Defines multiple simple data columns of the same data type within the SDDS dataset.
int32_t SDDS_ReconnectInputFile(SDDS_DATASET *SDDS_dataset, long position)
Reconnects the input file for the SDDS dataset at a specified position.
int32_t SDDS_DoFSync(SDDS_DATASET *SDDS_dataset)
Synchronizes the SDDS dataset's file to disk.
int32_t SDDS_UpdatePage(SDDS_DATASET *SDDS_dataset, uint32_t mode)
Updates the current page of the SDDS dataset.
int32_t SDDS_SetNameValidityFlags(uint32_t flags)
Sets the validity flags for parameter and column names in the SDDS dataset.
int32_t SDDS_SetNoRowCounts(SDDS_DATASET *SDDS_dataset, int32_t value)
Sets the flag to enable or disable row counts in the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_ReconnectFile(SDDS_DATASET *SDDS_dataset)
Reconnects the SDDS dataset to its previously associated file.
int32_t SDDS_IsValidName(const char *name, const char *class)
Checks if a given name is valid for a specified class within the SDDS dataset.
long SDDS_DisconnectInputFile(SDDS_DATASET *SDDS_dataset)
Disconnects the input file from the SDDS dataset.
int32_t SDDS_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
int64_t SDDS_CreateRpnMemory(const char *name, short is_string)
Stub function for creating RPN memory when RPN_SUPPORT is not enabled.
Definition SDDS_rpn.c:785
int64_t SDDS_CreateRpnArray(char *name)
Stub function for creating RPN arrays when RPN_SUPPORT is not enabled.
Definition SDDS_rpn.c:795
int32_t SDDS_FileIsLocked(const char *filename)
Determines if a specified file is locked.
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.
int SDDS_CompareIndexedNames(const void *s1, const void *s2)
Compares two SORTED_INDEX structures by their name fields.
int32_t SDDS_VerifyPrintfFormat(const char *string, int32_t type)
Verifies that a printf format string is compatible with a specified data type.
Definition SDDS_utils.c:750
int32_t SDDS_SprintTypedValue(void *data, int64_t index, int32_t type, const char *format, char *buffer, uint32_t mode)
Formats a data value of a specified type into a string buffer using an optional printf format string.
Definition SDDS_utils.c:151
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_LockFile(FILE *fp, const char *filename, const char *caller)
Attempts to lock a specified file.
int32_t SDDS_GetAssociateIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named associate in the SDDS dataset.
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.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
int32_t SDDS_MPI_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the layout of the SDDS dataset to the MPI file.
int32_t SDDS_MPI_ReconnectFile(SDDS_DATASET *SDDS_dataset)
Reconnects the MPI file associated with the SDDS dataset.
int32_t SDDS_MPI_DisconnectFile(SDDS_DATASET *SDDS_dataset)
Disconnects the MPI file associated with the SDDS dataset.
int32_t SDDS_MPI_WritePage(SDDS_DATASET *SDDS_dataset)
Writes a page of data to the MPI file associated with the SDDS dataset.
#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_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_LONGDOUBLE
Identifier for the long double data type.
Definition SDDStypes.h:31
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
Definition SDDStypes.h:49