SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
SDDS_extract.c
Go to the documentation of this file.
1/**
2 * @file SDDS_extract.c
3 * @brief This file contains routines for getting pointers to SDDS objects like columns and parameters.
4 *
5 * This file provides functions for extracting data in the
6 * Self-Describing Data Sets (SDDS) format.
7 *
8 * @copyright
9 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
10 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
11 *
12 * @license
13 * This file is distributed under the terms of the Software License Agreement
14 * found in the file LICENSE included with this distribution.
15 *
16 * @author M. Borland, C. Saunders, R. Soliday, H. Shang
17 */
18
19#include "SDDS.h"
20#include "SDDS_internal.h"
21#include "mdb.h"
22
23#if defined(_WIN32) && !defined(_MINGW)
24/*#define isnan(x) _isnan(x)*/
25#endif
26
27/**
28 * @brief Sets the acceptance flags for all rows in the current data table of a data set.
29 *
30 * This function initializes the acceptance flags for each row in the data table. A non-zero flag indicates that the row is "of interest" and should be considered in subsequent operations, while a zero flag marks the row for rejection.
31 *
32 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
33 * @param row_flag_value Integer value to assign to all row flags.
34 * - Non-zero value: Marks rows as accepted ("of interest").
35 * - Zero value: Marks rows as rejected.
36 *
37 * @return
38 * - **1** on successful update of row flags.
39 * - **0** on failure, with an error message recorded.
40 *
41 * @note
42 * This function overwrites any existing row flags with the specified `row_flag_value`.
43 *
44 * @sa SDDS_GetRowFlag, SDDS_GetRowFlags
45 */
46int32_t SDDS_SetRowFlags(SDDS_DATASET *SDDS_dataset, int32_t row_flag_value) {
47 /* int32_t i; */
48 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetRowFlags"))
49 return (0);
50 if (!SDDS_SetMemory(SDDS_dataset->row_flag, SDDS_dataset->n_rows_allocated, SDDS_LONG, (int32_t)row_flag_value, (int32_t)0)) {
51 SDDS_SetError("Unable to set row flags--memory filling failed (SDDS_SetRowFlags)");
52 return (0);
53 }
54 return (1);
55}
56
57/**
58 * @brief Retrieves the acceptance flag of a specific row in the current data table.
59 *
60 * This function fetches the acceptance flag for a given row. The flag indicates whether the row is "of interest" (non-zero) or rejected (zero).
61 *
62 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
63 * @param row Index of the row whose flag is to be retrieved. Must be within the range [0, n_rows-1].
64 *
65 * @return
66 * - **Non-negative integer** representing the flag value of the specified row.
67 * - **-1** if the dataset is invalid or the row index is out of bounds.
68 *
69 * @sa SDDS_SetRowFlags, SDDS_GetRowFlags
70 */
71int32_t SDDS_GetRowFlag(SDDS_DATASET *SDDS_dataset, int64_t row) {
72 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetRowFlag"))
73 return -1;
74 if (row < 0 || row >= SDDS_dataset->n_rows)
75 return -1;
76 return SDDS_dataset->row_flag[row];
77}
78
79/**
80 * @brief Retrieves the acceptance flags for all rows in the current data table.
81 *
82 * This function copies the acceptance flags of each row into a provided array. Each flag indicates whether the corresponding row is "of interest" (non-zero) or rejected (zero).
83 *
84 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
85 * @param flag Pointer to an integer array where the row flags will be stored. The array must have at least `rows` elements.
86 * @param rows Number of rows to retrieve flags for. Typically, this should match the total number of rows in the data table.
87 *
88 * @return
89 * - **1** on successful retrieval of all row flags.
90 * - **0** on failure, with an error message recorded (e.g., if row count mismatches).
91 *
92 * @note
93 * Ensure that the `flag` array is adequately allocated to hold the flags for all specified rows.
94 *
95 * @sa SDDS_SetRowFlags, SDDS_GetRowFlag
96 */
97int32_t SDDS_GetRowFlags(SDDS_DATASET *SDDS_dataset, int32_t *flag, int64_t rows) {
98 int64_t i;
99 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetRowFlags"))
100 return 0;
101 if (rows != SDDS_dataset->n_rows) {
102 SDDS_SetError("Row count mismatch (SDDS_GetRowFlags)");
103 return 0;
104 }
105 for (i = 0; i < rows; i++)
106 flag[i] = SDDS_dataset->row_flag[i];
107 return 1;
108}
109
110/**
111 * @brief Sets acceptance flags for rows based on specified criteria.
112 *
113 * This function allows setting row flags in two modes:
114 * - **SDDS_FLAG_ARRAY**: Sets flags based on an array of flag values.
115 * - **SDDS_INDEX_LIMITS**: Sets flags for a range of rows to a specific value.
116 *
117 * A non-zero flag indicates that a row is "of interest", while a zero flag marks it for rejection.
118 *
119 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
120 * @param mode Operation mode determining how flags are set. Possible values:
121 * - `SDDS_FLAG_ARRAY`:
122 * ```c
123 * SDDS_AssertRowFlags(SDDS_DATASET *SDDS_dataset, SDDS_FLAG_ARRAY, int32_t *flagArray, int64_t rowsInArray);
124 * ```
125 * - `SDDS_INDEX_LIMITS`:
126 * ```c
127 * SDDS_AssertRowFlags(SDDS_DATASET *SDDS_dataset, SDDS_INDEX_LIMITS, int64_t start, int64_t end, int32_t value);
128 * ```
129 * @param ... Variable arguments based on the selected mode:
130 * - **SDDS_FLAG_ARRAY**:
131 * - `int32_t *flagArray`: Array of flag values to assign.
132 * - `int64_t rowsInArray`: Number of rows in `flagArray`.
133 * - **SDDS_INDEX_LIMITS**:
134 * - `int64_t start`: Starting row index (inclusive).
135 * - `int64_t end`: Ending row index (inclusive).
136 * - `int32_t value`: Flag value to assign to the specified range.
137 *
138 * @return
139 * - **1** on successful assignment of row flags.
140 * - **0** on failure, with an error message recorded (e.g., invalid parameters, memory issues).
141 *
142 * @note
143 * - For `SDDS_FLAG_ARRAY`, if `rowsInArray` exceeds the number of allocated rows, it is truncated to fit.
144 * - For `SDDS_INDEX_LIMITS`, if `end` exceeds the number of rows, it is adjusted to the last valid row index.
145 *
146 * @sa SDDS_SetRowFlags, SDDS_GetRowFlags, SDDS_GetRowFlag
147 */
148int32_t SDDS_AssertRowFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode, ...)
149/* usage:
150 SDDS_AssertRowFlags(&SDDSset, SDDS_FLAG_ARRAY, int32_t *flagArray, int64_t rowsInArray)
151 rowsInArray is normally equal to the number of rows in the table
152 SDDS_AssertRowFlags(&SDDSset, SDDS_INDEX_LIMITS, int64_t start, int64_t end, int32_t value)
153*/
154{
155 int64_t i, rows, startRow, endRow;
156 va_list argptr;
157 int32_t retval;
158 int32_t *flagArray, flagValue;
159 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_AssertRowFlags"))
160 return (0);
161
162 va_start(argptr, mode);
163 retval = 0;
164 switch (mode) {
165 case SDDS_FLAG_ARRAY:
166 if (!(flagArray = va_arg(argptr, int32_t *)))
167 SDDS_SetError("NULL flag array pointer seen (SDDS_AssertRowFlags)");
168 else if ((rows = va_arg(argptr, int64_t)) < 0)
169 SDDS_SetError("invalid row count seen (SDDS_AssertRowFlags)");
170 else {
171 if (rows >= SDDS_dataset->n_rows)
172 rows = SDDS_dataset->n_rows;
173 for (i = 0; i < rows; i++)
174 SDDS_dataset->row_flag[i] = flagArray[i];
175 retval = 1;
176 }
177 break;
178 case SDDS_INDEX_LIMITS:
179 if ((startRow = va_arg(argptr, int64_t)) < 0 || (endRow = va_arg(argptr, int64_t)) < startRow)
180 SDDS_SetError("invalid start and end row values (SDDS_AssertRowFlags)");
181 else {
182 flagValue = va_arg(argptr, int32_t);
183 if (endRow >= SDDS_dataset->n_rows || endRow < 0)
184 endRow = SDDS_dataset->n_rows - 1;
185 for (i = startRow; i <= endRow; i++)
186 SDDS_dataset->row_flag[i] = flagValue;
187 retval = 1;
188 }
189 break;
190 default:
191 SDDS_SetError("unknown mode passed (SDDS_AssertRowFlags)");
192 break;
193 }
194
195 va_end(argptr);
196 return retval;
197}
198
199/**
200 * @brief Sets the acceptance flags for all columns in the current data table of a data set.
201 *
202 * This function initializes the acceptance flags for each column. A non-zero flag indicates that the column is "of interest" and should be considered in subsequent operations, while a zero flag marks the column for rejection.
203 *
204 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
205 * @param column_flag_value Integer value to assign to all column flags.
206 * - Non-zero value: Marks columns as accepted ("of interest").
207 * - Zero value: Marks columns as rejected.
208 *
209 * @return
210 * - **1** on successful update of column flags.
211 * - **0** on failure, with an error message recorded (e.g., memory allocation failure).
212 *
213 * @note
214 * This function overwrites any existing column flags with the specified `column_flag_value`. It also updates the `column_order` array accordingly.
215 *
216 * @sa SDDS_GetColumnFlags, SDDS_AssertColumnFlags
217 */
218int32_t SDDS_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value) {
219 int64_t i;
220 /* int32_t j; */
221 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetColumnFlags"))
222 return 0;
223 if ((!SDDS_dataset->column_flag || !SDDS_dataset->column_order) && !SDDS_AllocateColumnFlags(SDDS_dataset))
224 return 0;
225 if (!SDDS_SetMemory(SDDS_dataset->column_flag, SDDS_dataset->layout.n_columns, SDDS_LONG, (int32_t)column_flag_value, (int32_t)0)) {
226 SDDS_SetError("Unable to set column flags--memory filling failed (SDDS_SetColumnFlags)");
227 return (0);
228 }
229 SDDS_dataset->n_of_interest = column_flag_value ? SDDS_dataset->layout.n_columns : 0;
230 for (i = 0; i < SDDS_dataset->layout.n_columns; i++)
231 SDDS_dataset->column_order[i] = column_flag_value ? i : -1;
232 return (1);
233}
234
235/**
236 * @brief Sets acceptance flags for columns based on specified criteria.
237 *
238 * This function allows setting column flags in two modes:
239 * - **SDDS_FLAG_ARRAY**: Sets flags based on an array of flag values.
240 * - **SDDS_INDEX_LIMITS**: Sets flags for a range of columns to a specific value.
241 *
242 * A non-zero flag indicates that a column is "of interest", while a zero flag marks it for rejection.
243 *
244 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
245 * @param mode Operation mode determining how flags are set. Possible values:
246 * - `SDDS_FLAG_ARRAY`:
247 * ```c
248 * SDDS_AssertColumnFlags(SDDS_DATASET *SDDS_dataset, SDDS_FLAG_ARRAY, int32_t *flagArray, int32_t columnsInArray);
249 * ```
250 * - `SDDS_INDEX_LIMITS`:
251 * ```c
252 * SDDS_AssertColumnFlags(SDDS_DATASET *SDDS_dataset, SDDS_INDEX_LIMITS, int32_t start, int32_t end, int32_t value);
253 * ```
254 * @param ... Variable arguments based on the selected mode:
255 * - **SDDS_FLAG_ARRAY**:
256 * - `int32_t *flagArray`: Array of flag values to assign.
257 * - `int32_t columnsInArray`: Number of columns in `flagArray`.
258 * - **SDDS_INDEX_LIMITS**:
259 * - `int32_t start`: Starting column index (inclusive).
260 * - `int32_t end`: Ending column index (inclusive).
261 * - `int32_t value`: Flag value to assign to the specified range.
262 *
263 * @return
264 * - **1** on successful assignment of column flags.
265 * - **0** on failure, with an error message recorded (e.g., invalid parameters, memory issues).
266 *
267 * @note
268 * - For `SDDS_FLAG_ARRAY`, if `columnsInArray` exceeds the number of allocated columns, it is truncated to fit.
269 * - For `SDDS_INDEX_LIMITS`, if `end` exceeds the number of columns, it is adjusted to the last valid column index.
270 *
271 * @sa SDDS_SetColumnFlags, SDDS_GetColumnFlags, SDDS_GetColumnFlag
272 */
273int32_t SDDS_AssertColumnFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode, ...) {
274 int64_t i, j;
275 int32_t columns, startColumn, endColumn;
276 va_list argptr;
277 int32_t retval;
278 int32_t *flagArray, flagValue;
279
280 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_AssertColumnFlags"))
281 return (0);
282 if ((!SDDS_dataset->column_flag || !SDDS_dataset->column_order) && !SDDS_AllocateColumnFlags(SDDS_dataset))
283 return 0;
284
285 va_start(argptr, mode);
286 retval = 0;
287 switch (mode) {
288 case SDDS_FLAG_ARRAY:
289 if (!(flagArray = va_arg(argptr, int32_t *)))
290 SDDS_SetError("NULL flag array pointer seen (SDDS_AssertColumnFlags)");
291 else if ((columns = va_arg(argptr, int32_t)) < 0)
292 SDDS_SetError("invalid column count seen (SDDS_AssertColumnFlags)");
293 else {
294 if (columns >= SDDS_dataset->layout.n_columns)
295 columns = SDDS_dataset->layout.n_columns - 1;
296 for (i = 0; i < columns; i++)
297 SDDS_dataset->column_flag[i] = flagArray[i];
298 retval = 1;
299 }
300 break;
301 case SDDS_INDEX_LIMITS:
302 if ((startColumn = va_arg(argptr, int32_t)) < 0 || (endColumn = va_arg(argptr, int32_t)) < startColumn)
303 SDDS_SetError("invalid start and end column values (SDDS_AssertColumnFlags)");
304 else {
305 flagValue = va_arg(argptr, int32_t);
306 if (endColumn >= SDDS_dataset->layout.n_columns || endColumn < 0)
307 endColumn = SDDS_dataset->layout.n_columns - 1;
308 for (i = startColumn; i <= endColumn; i++)
309 SDDS_dataset->column_flag[i] = flagValue;
310 retval = 1;
311 }
312 break;
313 default:
314 SDDS_SetError("unknown mode passed (SDDS_AssertColumnFlags)");
315 break;
316 }
317 va_end(argptr);
318
319 for (i = j = 0; i < SDDS_dataset->layout.n_columns; i++) {
320 if (SDDS_dataset->column_flag[i])
321 SDDS_dataset->column_order[j++] = i;
322 }
323
324 SDDS_dataset->n_of_interest = j;
325
326 return retval;
327}
328
329/**
330 * @brief Counts the number of columns marked as "of interest" in the current data table.
331 *
332 * This function returns the total number of columns that have been flagged as "of interest" based on their acceptance flags.
333 *
334 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
335 *
336 * @return
337 * - **Non-negative integer** representing the number of columns marked as "of interest".
338 * - **-1** if the dataset is invalid.
339 *
340 * @sa SDDS_CountRowsOfInterest, SDDS_SetColumnFlags, SDDS_GetColumnFlags
341 */
343 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_CountRowsOfInterest"))
344 return (-1);
345 return (SDDS_dataset->n_of_interest);
346}
347
348/**
349 * @brief Counts the number of rows marked as "of interest" in the current data table.
350 *
351 * This function iterates through the row acceptance flags and tallies the number of rows that are flagged as "of interest" (non-zero).
352 *
353 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
354 *
355 * @return
356 * - **Number of rows** with non-zero acceptance flags.
357 * - **-1** on error (e.g., invalid dataset or tabular data).
358 *
359 * @note
360 * Ensure that the dataset contains tabular data before invoking this function.
361 *
362 * @sa SDDS_SetRowFlags, SDDS_GetRowFlags, SDDS_GetRowFlag
363 */
365 int64_t n_rows, i;
366 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_CountRowsOfInterest"))
367 return (-1);
368 if (!SDDS_CheckTabularData(SDDS_dataset, "SDDS_CountRowsOfInterest"))
369 return (-1);
370 if (!SDDS_dataset->layout.n_columns)
371 return 0;
372 for (i = n_rows = 0; i < SDDS_dataset->n_rows; i++) {
373 if (SDDS_dataset->row_flag[i])
374 n_rows += 1;
375 }
376 return (n_rows);
377}
378
379/**
380 * @brief Sets the acceptance flags for columns based on specified naming criteria.
381 *
382 * This function allows modifying column acceptance flags using various methods, including specifying column names directly or using pattern matching.
383 *
384 * Supported modes:
385 * - **SDDS_NAME_ARRAY**: Provide an array of column names to mark as "of interest".
386 * - **SDDS_NAMES_STRING**: Provide a single string containing comma-separated column names.
387 * - **SDDS_NAME_STRINGS**: Provide multiple individual column name strings, terminated by `NULL`.
388 * - **SDDS_MATCH_STRING**: Provide a pattern string and a logic mode to match column names.
389 *
390 * A non-zero flag indicates that a column is "of interest", while a zero flag marks it for rejection.
391 *
392 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
393 * @param mode Operation mode determining how columns are selected. Possible values:
394 * - `SDDS_NAME_ARRAY`:
395 * ```c
396 * SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, SDDS_NAME_ARRAY, int32_t n_entries, char **nameArray);
397 * ```
398 * - `SDDS_NAMES_STRING`:
399 * ```c
400 * SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, SDDS_NAMES_STRING, char *names);
401 * ```
402 * - `SDDS_NAME_STRINGS`:
403 * ```c
404 * SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, SDDS_NAME_STRINGS, char *name1, char *name2, ..., NULL);
405 * ```
406 * - `SDDS_MATCH_STRING`:
407 * ```c
408 * SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, SDDS_MATCH_STRING, char *pattern, int32_t logic_mode);
409 * ```
410 * @param ... Variable arguments based on the selected mode:
411 * - **SDDS_NAME_ARRAY**:
412 * - `int32_t n_entries`: Number of column names in the array.
413 * - `char **nameArray`: Array of column name strings.
414 * - **SDDS_NAMES_STRING**:
415 * - `char *names`: Comma-separated string of column names.
416 * - **SDDS_NAME_STRINGS**:
417 * - `char *name1, char *name2, ..., NULL`: Individual column name strings terminated by `NULL`.
418 * - **SDDS_MATCH_STRING**:
419 * - `char *pattern`: Pattern string to match column names (supports wildcards).
420 * - `int32_t logic_mode`: Logic mode for matching (e.g., AND, OR).
421 *
422 * @return
423 * - **1** on successful update of column flags.
424 * - **0** on failure, with an error message recorded (e.g., invalid mode, memory issues, unrecognized column names).
425 *
426 * @note
427 * - When using `SDDS_MATCH_STRING`, the `pattern` may include wildcards to match multiple column names.
428 * - Ensure that column names provided exist within the dataset to avoid errors.
429 *
430 * @sa SDDS_SetColumnFlags, SDDS_AssertColumnFlags, SDDS_GetColumnFlags
431 */
432int32_t SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, int32_t mode, ...)
433/* This routine has 3 calling modes:
434 * SDDS_SetColumnsOfInterest(&SDDS_dataset, SDDS_NAME_ARRAY, int32_t n_entries, char **name)
435 * SDDS_SetColumnsOfInterest(&SDDS_dataset, SDDS_NAMES_STRING, char *names)
436 * SDDS_SetColumnsOfInterest(&SDDS_dataset, SDDS_NAME_STRINGS, char *name1, char *name2, ..., NULL )
437 * SDDS_SetColumnsOfInterest(&SDDS_dataset, SDDS_MATCH_STRING, char *name, int32_t logic_mode)
438 */
439{
440 va_list argptr;
441 int32_t i, j, index, n_names;
442 int32_t retval;
443 /* int32_t type; */
444 char **name, *string, *match_string, *ptr;
445 int32_t local_memory; /* (0,1,2) --> (none, pointer array, pointer array + strings) locally allocated */
446 char buffer[SDDS_MAXLINE];
447 int32_t logic;
448
449 name = NULL;
450 n_names = local_memory = logic = 0;
451
452 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetColumnsOfInterest"))
453 return (0);
454 if ((!SDDS_dataset->column_flag || !SDDS_dataset->column_order) && !SDDS_AllocateColumnFlags(SDDS_dataset))
455 return 0;
456 va_start(argptr, mode);
457 retval = -1;
458 match_string = NULL;
459 switch (mode) {
460 case SDDS_NAME_ARRAY:
461 local_memory = 0;
462 n_names = va_arg(argptr, int32_t);
463 name = va_arg(argptr, char **);
464 break;
465 case SDDS_NAMES_STRING:
466 local_memory = 2;
467 n_names = 0;
468 name = NULL;
469 ptr = va_arg(argptr, char *);
470 SDDS_CopyString(&string, ptr);
471 while ((ptr = strchr(string, ',')))
472 *ptr = ' ';
473 while (SDDS_GetToken(string, buffer, SDDS_MAXLINE) > 0) {
474 if (!(name = SDDS_Realloc(name, sizeof(*name) * (n_names + 1))) || !SDDS_CopyString(name + n_names, buffer)) {
475 SDDS_SetError("Unable to process column selection--memory allocation failure (SDDS_SetColumnsOfInterest)");
476 retval = 0;
477 break;
478 }
479 n_names++;
480 }
481 free(string);
482 break;
483 case SDDS_NAME_STRINGS:
484 local_memory = 1;
485 n_names = 0;
486 name = NULL;
487 while ((string = va_arg(argptr, char *))) {
488 if (!(name = SDDS_Realloc(name, sizeof(*name) * (n_names + 1)))) {
489 SDDS_SetError("Unable to process column selection--memory allocation failure (SDDS_SetColumnsOfInterest)");
490 retval = 0;
491 break;
492 }
493 name[n_names++] = string;
494 }
495 break;
496 case SDDS_MATCH_STRING:
497 local_memory = 0;
498 n_names = 1;
499 if (!(string = va_arg(argptr, char *))) {
500 SDDS_SetError("Unable to process column selection--invalid matching string (SDDS_SetColumnsOfInterest)");
501 retval = 0;
502 break;
503 }
504 match_string = expand_ranges(string);
505 logic = va_arg(argptr, int32_t);
506 break;
507 default:
508 SDDS_SetError("Unable to process column selection--unknown mode (SDDS_SetColumnsOfInterest)");
509 retval = 0;
510 break;
511 }
512
513 va_end(argptr);
514 if (retval != -1)
515 return (retval);
516
517 if (n_names == 0) {
518 SDDS_SetError("Unable to process column selection--no names in call (SDDS_SetColumnsOfInterest)");
519 return (0);
520 }
521 if (!SDDS_dataset->column_order) {
522 SDDS_SetError("Unable to process column selection--'column_order' array in SDDS_DATASET is NULL (SDDS_SetColumnsOfInterest)");
523 return (0);
524 }
525
526 if (mode != SDDS_MATCH_STRING) {
527 for (i = 0; i < n_names; i++) {
528 if ((index = SDDS_GetColumnIndex(SDDS_dataset, name[i])) < 0) {
529 sprintf(buffer, "Unable to process column selection--unrecognized column name %s seen (SDDS_SetColumnsOfInterest)", name[i]);
530 SDDS_SetError(buffer);
531 return (0);
532 }
533 for (j = 0; j < SDDS_dataset->n_of_interest; j++)
534 if (index == SDDS_dataset->column_order[j])
535 break;
536 if (j == SDDS_dataset->n_of_interest) {
537 SDDS_dataset->column_flag[index] = 1;
538 SDDS_dataset->column_order[j] = index;
539 SDDS_dataset->n_of_interest++;
540 }
541 }
542 } else {
543 for (i = 0; i < SDDS_dataset->layout.n_columns; i++) {
544 if (SDDS_Logic(SDDS_dataset->column_flag[i], wild_match(SDDS_dataset->layout.column_definition[i].name, match_string), logic)) {
545#if defined(DEBUG)
546 fprintf(stderr, "logic match of %s to %s\n", SDDS_dataset->layout.column_definition[i].name, match_string);
547#endif
548 for (j = 0; j < SDDS_dataset->n_of_interest; j++)
549 if (i == SDDS_dataset->column_order[j])
550 break;
551 if (j == SDDS_dataset->n_of_interest) {
552 SDDS_dataset->column_flag[i] = 1;
553 SDDS_dataset->column_order[j] = i;
554 SDDS_dataset->n_of_interest++;
555 }
556 } else {
557#if defined(DEBUG)
558 fprintf(stderr, "no logic match of %s to %s\n", SDDS_dataset->layout.column_definition[i].name, match_string);
559#endif
560 SDDS_dataset->column_flag[i] = 0;
561 for (j = 0; j < SDDS_dataset->n_of_interest; j++)
562 if (i == SDDS_dataset->column_order[j])
563 break;
564 if (j != SDDS_dataset->n_of_interest) {
565 for (j++; j < SDDS_dataset->n_of_interest; j++)
566 SDDS_dataset->column_order[j - 1] = SDDS_dataset->column_order[j];
567 }
568 }
569 }
570 free(match_string);
571 }
572
573#if defined(DEBUG)
574 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
575 fprintf(stderr, "column %" PRId32 " will be %s\n", i, SDDS_dataset->layout.column_definition[SDDS_dataset->column_order[i]].name);
576#endif
577
578 if (local_memory == 2) {
579 for (i = 0; i < n_names; i++)
580 free(name[i]);
581 }
582 if (local_memory >= 1)
583 free(name);
584
585 return (1);
586}
587
588/**
589 * @brief Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
590 *
591 * This function returns a newly allocated array containing data from the specified column for all rows that are flagged as "of interest". The data type of the returned array matches the column's data type.
592 *
593 * For columns of type `SDDS_STRING`, the returned array is of type `char**`, with each element being a dynamically allocated string.
594 *
595 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
596 * @param column_name NULL-terminated string specifying the name of the column to retrieve.
597 *
598 * @return
599 * - **Pointer to the data array** on success. The type of the array corresponds to the column's data type.
600 * - **NULL** on failure, with an error message recorded (e.g., unrecognized column name, memory allocation failure, no rows of interest).
601 *
602 * @warning
603 * The caller is responsible for freeing the allocated memory to avoid memory leaks. For `SDDS_STRING` types, each string within the array should be freed individually, followed by the array itself.
604 *
605 * @note
606 * - The number of rows in the returned array can be obtained using `SDDS_CountRowsOfInterest`.
607 * - If the column's memory mode is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data may be freed after access.
608 *
609 * @sa SDDS_GetInternalColumn, SDDS_CountRowsOfInterest, SDDS_SetRowFlags
610 */
611void *SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name) {
612 int32_t size, type, index;
613 int64_t i, j, n_rows;
614 void *data;
615 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetColumn"))
616 return (NULL);
617 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
618 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetColumn)");
619 return (NULL);
620 }
621 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
622 SDDS_SetError("Unable to get column--no rows left (SDDS_GetColumn)");
623 return (NULL);
624 }
625 if (!(type = SDDS_GetColumnType(SDDS_dataset, index))) {
626 SDDS_SetError("Unable to get column--data type undefined (SDDS_GetColumn)");
627 return (NULL);
628 }
629 size = SDDS_type_size[type - 1];
630 if (!(data = SDDS_Malloc(size * n_rows))) {
631 SDDS_SetError("Unable to get column--memory allocation failure (SDDS_GetColumn)");
632 return (NULL);
633 }
634 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
635 if (SDDS_dataset->row_flag[i]) {
636 if (type != SDDS_STRING)
637 memcpy((char *)data + size * j++, (char *)SDDS_dataset->data[index] + size * i, size);
638 else if (!SDDS_CopyString((char **)data + j++, ((char ***)SDDS_dataset->data)[index][i]))
639 return (NULL);
640 }
641 }
642 if (j != n_rows) {
643 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetColumn)");
644 return (NULL);
645 }
646 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
647 SDDS_dataset->column_track_memory[index] = 0;
648 //Free internal copy now under the assumption that the program will not ask for it again.
649 if (type == SDDS_STRING) {
650 if (0) {
651 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
652 char **ptr = (char **)SDDS_dataset->data[index];
653 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
654 if (*ptr)
655 free(*ptr);
656 free(SDDS_dataset->data[index]);
657 SDDS_dataset->data[index] = NULL;
658 }
659 } else {
660 free(SDDS_dataset->data[index]);
661 SDDS_dataset->data[index] = NULL;
662 }
663 }
664 return (data);
665}
666
667/**
668 * @brief Retrieves an internal pointer to the data of a specified column, including all rows.
669 *
670 * This function returns a direct pointer to the internal data array of the specified column. Unlike `SDDS_GetColumn`, it includes all rows, regardless of their acceptance flags.
671 *
672 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the data set.
673 * @param column_name NULL-terminated string specifying the name of the column to retrieve.
674 *
675 * @return
676 * - **Pointer to the internal data array** on success. The type of the pointer corresponds to the column's data type.
677 * - **NULL** on failure, with an error message recorded (e.g., unrecognized column name).
678 *
679 * @warning
680 * Modifying the data through the returned pointer affects the internal state of the dataset. Use with caution to avoid unintended side effects.
681 *
682 * @note
683 * - If the column's memory mode is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data may be freed after access.
684 * - This function does not allocate new memory; it provides direct access to the dataset's internal structures.
685 *
686 * @sa SDDS_GetColumn, SDDS_SetColumnFlags, SDDS_CountColumnsOfInterest
687 */
688void *SDDS_GetInternalColumn(SDDS_DATASET *SDDS_dataset, char *column_name) {
689 int32_t index;
690 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetInternalColumn"))
691 return (NULL);
692 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
693 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetInternalColumn)");
694 return (NULL);
695 }
696 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
697 SDDS_dataset->column_track_memory[index] = 0;
698 }
699 return SDDS_dataset->data[index];
700}
701
702/**
703 * @brief Retrieves the data of a specified numerical column as an array of long doubles, considering only rows marked as "of interest".
704 *
705 * This function extracts data from a specified column within the current data table of a dataset. It processes only those rows that are flagged as "of interest" (i.e., have a non-zero acceptance flag). The extracted data is returned as a newly allocated array of `long double` values.
706 *
707 * @param SDDS_dataset
708 * Pointer to the `SDDS_DATASET` structure representing the data set.
709 * @param column_name
710 * NULL-terminated string specifying the name of the column from which data is to be retrieved.
711 *
712 * @return
713 * - **Pointer to an array of `long double`** containing the data from the specified column for all rows marked as "of interest".
714 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized column name, non-numeric column type, memory allocation failure). In this case, an error message is recorded internally.
715 *
716 * @warning
717 * - The caller is responsible for freeing the allocated memory to prevent memory leaks.
718 * - This function assumes that the specified column contains numerical data. Attempting to retrieve data from a non-numeric column (excluding `SDDS_CHARACTER`) will result in an error.
719 *
720 * @note
721 * - The number of elements in the returned array corresponds to the number of rows marked as "of interest", which can be obtained using `SDDS_CountRowsOfInterest`.
722 * - If the dataset's memory mode for the column is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the column may be freed after access.
723 *
724 * @sa
725 * - `SDDS_GetColumnInDoubles`
726 * - `SDDS_GetColumnInFloats`
727 * - `SDDS_GetColumn`
728 * - `SDDS_CountRowsOfInterest`
729 */
730long double *SDDS_GetColumnInLongDoubles(SDDS_DATASET *SDDS_dataset, char *column_name) {
731 int32_t size, type, index;
732 int64_t i, j, n_rows;
733 long double *data;
734 void *rawData;
735
736 j = 0;
737
738 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetColumnInLongDoubles"))
739 return (NULL);
740 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
741 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetColumnInLongDoubles)");
742 return (NULL);
743 }
744 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
745 SDDS_SetError("Unable to get column--no rows left (SDDS_GetColumnInLongDoubles)");
746 return (NULL);
747 }
748 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) <= 0 || (size = SDDS_GetTypeSize(type)) <= 0 || (!SDDS_NUMERIC_TYPE(type) && type != SDDS_CHARACTER)) {
749 SDDS_SetError("Unable to get column--data size or type undefined or non-numeric (SDDS_GetColumnInLongDoubles)");
750 return (NULL);
751 }
752 if (!(data = (long double *)SDDS_Malloc(sizeof(long double) * n_rows))) {
753 SDDS_SetError("Unable to get column--memory allocation failure (SDDS_GetColumnInLongDoubles)");
754 return (NULL);
755 }
756 rawData = SDDS_dataset->data[index];
757 switch (type) {
758 case SDDS_LONGDOUBLE:
759 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
760 if (SDDS_dataset->row_flag[i])
761 data[j++] = ((long double *)rawData)[i];
762 }
763 break;
764 case SDDS_DOUBLE:
765 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
766 if (SDDS_dataset->row_flag[i])
767 data[j++] = ((double *)rawData)[i];
768 }
769 break;
770 case SDDS_FLOAT:
771 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
772 if (SDDS_dataset->row_flag[i])
773 data[j++] = ((float *)rawData)[i];
774 }
775 break;
776 case SDDS_LONG:
777 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
778 if (SDDS_dataset->row_flag[i])
779 data[j++] = ((int32_t *)rawData)[i];
780 }
781 break;
782 case SDDS_ULONG:
783 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
784 if (SDDS_dataset->row_flag[i])
785 data[j++] = ((uint32_t *)rawData)[i];
786 }
787 break;
788 case SDDS_LONG64:
789 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
790 if (SDDS_dataset->row_flag[i])
791 data[j++] = ((int64_t *)rawData)[i];
792 }
793 break;
794 case SDDS_ULONG64:
795 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
796 if (SDDS_dataset->row_flag[i])
797 data[j++] = ((uint64_t *)rawData)[i];
798 }
799 break;
800 case SDDS_SHORT:
801 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
802 if (SDDS_dataset->row_flag[i])
803 data[j++] = ((short *)rawData)[i];
804 }
805 break;
806 case SDDS_USHORT:
807 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
808 if (SDDS_dataset->row_flag[i])
809 data[j++] = ((unsigned short *)rawData)[i];
810 }
811 break;
812 case SDDS_CHARACTER:
813 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
814 if (SDDS_dataset->row_flag[i])
815 data[j++] = ((char *)rawData)[i];
816 }
817 break;
818 }
819 if (j != n_rows) {
820 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetColumnInLongDoubles)");
821 return (NULL);
822 }
823 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
824 SDDS_dataset->column_track_memory[index] = 0;
825 //Free internal copy now under the assumption that the program will not ask for it again.
826 if (type == SDDS_STRING) {
827 if (0) {
828 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
829 char **ptr = (char **)SDDS_dataset->data[index];
830 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
831 if (*ptr)
832 free(*ptr);
833 free(SDDS_dataset->data[index]);
834 SDDS_dataset->data[index] = NULL;
835 }
836 } else {
837 free(SDDS_dataset->data[index]);
838 SDDS_dataset->data[index] = NULL;
839 }
840 }
841 return (data);
842}
843
844/**
845 * @brief Retrieves the data of a specified numerical column as an array of doubles, considering only rows marked as "of interest".
846 *
847 * This function extracts data from a specified column within the current data table of a dataset. It processes only those rows that are flagged as "of interest" (i.e., have a non-zero acceptance flag). The extracted data is returned as a newly allocated array of `double` values.
848 *
849 * @param SDDS_dataset
850 * Pointer to the `SDDS_DATASET` structure representing the data set.
851 * @param column_name
852 * NULL-terminated string specifying the name of the column from which data is to be retrieved.
853 *
854 * @return
855 * - **Pointer to an array of `double`** containing the data from the specified column for all rows marked as "of interest".
856 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized column name, non-numeric column type, memory allocation failure). In this case, an error message is recorded internally.
857 *
858 * @warning
859 * - The caller is responsible for freeing the allocated memory to prevent memory leaks.
860 * - This function assumes that the specified column contains numerical data. Attempting to retrieve data from a non-numeric column (excluding `SDDS_CHARACTER`) will result in an error.
861 *
862 * @note
863 * - The number of elements in the returned array corresponds to the number of rows marked as "of interest", which can be obtained using `SDDS_CountRowsOfInterest`.
864 * - If the dataset's memory mode for the column is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the column may be freed after access.
865 *
866 * @sa
867 * - `SDDS_GetColumnInLongDoubles`
868 * - `SDDS_GetColumnInFloats`
869 * - `SDDS_GetColumn`
870 * - `SDDS_CountRowsOfInterest`
871 */
872double *SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name) {
873 int32_t size, type, index;
874 int64_t i, j, n_rows;
875 double *data;
876 void *rawData;
877
878 j = 0;
879
880 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetColumnInDoubles"))
881 return (NULL);
882 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
883 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetColumnInDoubles)");
884 return (NULL);
885 }
886 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
887 SDDS_SetError("Unable to get column--no rows left (SDDS_GetColumnInDoubles)");
888 return (NULL);
889 }
890 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) <= 0 || (size = SDDS_GetTypeSize(type)) <= 0 || (!SDDS_NUMERIC_TYPE(type) && type != SDDS_CHARACTER)) {
891 SDDS_SetError("Unable to get column--data size or type undefined or non-numeric (SDDS_GetColumnInDoubles)");
892 return (NULL);
893 }
894 if (!(data = (double *)SDDS_Malloc(sizeof(double) * n_rows))) {
895 SDDS_SetError("Unable to get column--memory allocation failure (SDDS_GetColumnInDoubles)");
896 return (NULL);
897 }
898 rawData = SDDS_dataset->data[index];
899 switch (type) {
900 case SDDS_LONGDOUBLE:
901 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
902 if (SDDS_dataset->row_flag[i])
903 data[j++] = ((long double *)rawData)[i];
904 }
905 break;
906 case SDDS_DOUBLE:
907 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
908 if (SDDS_dataset->row_flag[i])
909 data[j++] = ((double *)rawData)[i];
910 }
911 break;
912 case SDDS_FLOAT:
913 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
914 if (SDDS_dataset->row_flag[i])
915 data[j++] = ((float *)rawData)[i];
916 }
917 break;
918 case SDDS_LONG:
919 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
920 if (SDDS_dataset->row_flag[i])
921 data[j++] = ((int32_t *)rawData)[i];
922 }
923 break;
924 case SDDS_ULONG:
925 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
926 if (SDDS_dataset->row_flag[i])
927 data[j++] = ((uint32_t *)rawData)[i];
928 }
929 break;
930 case SDDS_LONG64:
931 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
932 if (SDDS_dataset->row_flag[i])
933 data[j++] = ((int64_t *)rawData)[i];
934 }
935 break;
936 case SDDS_ULONG64:
937 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
938 if (SDDS_dataset->row_flag[i])
939 data[j++] = ((uint64_t *)rawData)[i];
940 }
941 break;
942 case SDDS_SHORT:
943 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
944 if (SDDS_dataset->row_flag[i])
945 data[j++] = ((short *)rawData)[i];
946 }
947 break;
948 case SDDS_USHORT:
949 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
950 if (SDDS_dataset->row_flag[i])
951 data[j++] = ((unsigned short *)rawData)[i];
952 }
953 break;
954 case SDDS_CHARACTER:
955 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
956 if (SDDS_dataset->row_flag[i])
957 data[j++] = ((char *)rawData)[i];
958 }
959 break;
960 }
961 if (j != n_rows) {
962 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetColumnInDoubles)");
963 return (NULL);
964 }
965 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
966 SDDS_dataset->column_track_memory[index] = 0;
967 //Free internal copy now under the assumption that the program will not ask for it again.
968 if (type == SDDS_STRING) {
969 if (0) {
970 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
971 char **ptr = (char **)SDDS_dataset->data[index];
972 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
973 if (*ptr)
974 free(*ptr);
975 free(SDDS_dataset->data[index]);
976 SDDS_dataset->data[index] = NULL;
977 }
978 } else {
979 free(SDDS_dataset->data[index]);
980 SDDS_dataset->data[index] = NULL;
981 }
982 }
983 return (data);
984}
985
986/**
987 * @brief Retrieves the data of a specified numerical column as an array of floats, considering only rows marked as "of interest".
988 *
989 * This function extracts data from a specified column within the current data table of a dataset. It processes only those rows that are flagged as "of interest" (i.e., have a non-zero acceptance flag). The extracted data is returned as a newly allocated array of `float` values.
990 *
991 * @param SDDS_dataset
992 * Pointer to the `SDDS_DATASET` structure representing the data set.
993 * @param column_name
994 * NULL-terminated string specifying the name of the column from which data is to be retrieved.
995 *
996 * @return
997 * - **Pointer to an array of `float`** containing the data from the specified column for all rows marked as "of interest".
998 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized column name, non-numeric column type, memory allocation failure). In this case, an error message is recorded internally.
999 *
1000 * @warning
1001 * - The caller is responsible for freeing the allocated memory to prevent memory leaks.
1002 * - This function assumes that the specified column contains numerical data. Attempting to retrieve data from a non-numeric column (excluding `SDDS_CHARACTER`) will result in an error.
1003 *
1004 * @note
1005 * - The number of elements in the returned array corresponds to the number of rows marked as "of interest", which can be obtained using `SDDS_CountRowsOfInterest`.
1006 * - If the dataset's memory mode for the column is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the column may be freed after access.
1007 *
1008 * @sa
1009 * - `SDDS_GetColumnInLongDoubles`
1010 * - `SDDS_GetColumnInDoubles`
1011 * - `SDDS_GetColumn`
1012 * - `SDDS_CountRowsOfInterest`
1013 */
1014float *SDDS_GetColumnInFloats(SDDS_DATASET *SDDS_dataset, char *column_name) {
1015 int32_t size, type, index;
1016 int64_t i, j, n_rows;
1017 float *data;
1018 void *rawData;
1019
1020 j = 0;
1021
1022 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetColumnInFloats"))
1023 return (NULL);
1024 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1025 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetColumnInFloats)");
1026 return (NULL);
1027 }
1028 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
1029 SDDS_SetError("Unable to get column--no rows left (SDDS_GetColumnInFloats)");
1030 return (NULL);
1031 }
1032 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) <= 0 || (size = SDDS_GetTypeSize(type)) <= 0 || (!SDDS_NUMERIC_TYPE(type) && type != SDDS_CHARACTER)) {
1033 SDDS_SetError("Unable to get column--data size or type undefined or non-numeric (SDDS_GetColumnInFloats)");
1034 return (NULL);
1035 }
1036 if (!(data = (float *)SDDS_Malloc(sizeof(float) * n_rows))) {
1037 SDDS_SetError("Unable to get column--memory allocation failure (SDDS_GetColumnInFloats)");
1038 return (NULL);
1039 }
1040 rawData = SDDS_dataset->data[index];
1041 switch (type) {
1042 case SDDS_LONGDOUBLE:
1043 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1044 if (SDDS_dataset->row_flag[i])
1045 data[j++] = ((long double *)rawData)[i];
1046 }
1047 break;
1048 case SDDS_DOUBLE:
1049 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1050 if (SDDS_dataset->row_flag[i])
1051 data[j++] = ((double *)rawData)[i];
1052 }
1053 break;
1054 case SDDS_FLOAT:
1055 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1056 if (SDDS_dataset->row_flag[i])
1057 data[j++] = ((float *)rawData)[i];
1058 }
1059 break;
1060 case SDDS_LONG:
1061 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1062 if (SDDS_dataset->row_flag[i])
1063 data[j++] = ((int32_t *)rawData)[i];
1064 }
1065 break;
1066 case SDDS_ULONG:
1067 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1068 if (SDDS_dataset->row_flag[i])
1069 data[j++] = ((uint32_t *)rawData)[i];
1070 }
1071 break;
1072 case SDDS_LONG64:
1073 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1074 if (SDDS_dataset->row_flag[i])
1075 data[j++] = ((int64_t *)rawData)[i];
1076 }
1077 break;
1078 case SDDS_ULONG64:
1079 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1080 if (SDDS_dataset->row_flag[i])
1081 data[j++] = ((uint64_t *)rawData)[i];
1082 }
1083 break;
1084 case SDDS_SHORT:
1085 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1086 if (SDDS_dataset->row_flag[i])
1087 data[j++] = ((short *)rawData)[i];
1088 }
1089 break;
1090 case SDDS_USHORT:
1091 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1092 if (SDDS_dataset->row_flag[i])
1093 data[j++] = ((unsigned short *)rawData)[i];
1094 }
1095 break;
1096 case SDDS_CHARACTER:
1097 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1098 if (SDDS_dataset->row_flag[i])
1099 data[j++] = ((char *)rawData)[i];
1100 }
1101 break;
1102 }
1103 if (j != n_rows) {
1104 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetColumnInFloats)");
1105 return (NULL);
1106 }
1107 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
1108 SDDS_dataset->column_track_memory[index] = 0;
1109 //Free internal copy now under the assumption that the program will not ask for it again.
1110 if (type == SDDS_STRING) {
1111 if (0) {
1112 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
1113 char **ptr = (char **)SDDS_dataset->data[index];
1114 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
1115 if (*ptr)
1116 free(*ptr);
1117 free(SDDS_dataset->data[index]);
1118 SDDS_dataset->data[index] = NULL;
1119 }
1120 } else {
1121 free(SDDS_dataset->data[index]);
1122 SDDS_dataset->data[index] = NULL;
1123 }
1124 }
1125 return (data);
1126}
1127
1128/**
1129 * @brief Retrieves the data of a specified numerical column as an array of 32-bit integers, considering only rows marked as "of interest".
1130 *
1131 * This function extracts data from a specified column within the current data table of a dataset. It processes only those rows that are flagged as "of interest" (i.e., have a non-zero acceptance flag). The extracted data is returned as a newly allocated array of `int32_t` values.
1132 *
1133 * @param SDDS_dataset
1134 * Pointer to the `SDDS_DATASET` structure representing the data set.
1135 * @param column_name
1136 * NULL-terminated string specifying the name of the column from which data is to be retrieved.
1137 *
1138 * @return
1139 * - **Pointer to an array of `int32_t`** containing the data from the specified column for all rows marked as "of interest".
1140 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized column name, non-numeric column type, memory allocation failure). In this case, an error message is recorded internally.
1141 *
1142 * @warning
1143 * - The caller is responsible for freeing the allocated memory to prevent memory leaks.
1144 * - This function assumes that the specified column contains numerical data. Attempting to retrieve data from a non-numeric column (excluding `SDDS_CHARACTER`) will result in an error.
1145 *
1146 * @note
1147 * - The number of elements in the returned array corresponds to the number of rows marked as "of interest", which can be obtained using `SDDS_CountRowsOfInterest`.
1148 * - If the dataset's memory mode for the column is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the column may be freed after access.
1149 *
1150 * @sa
1151 * - `SDDS_GetColumnInLongDoubles`
1152 * - `SDDS_GetColumnInDoubles`
1153 * - `SDDS_GetColumnInFloats`
1154 * - `SDDS_GetColumn`
1155 * - `SDDS_CountRowsOfInterest`
1156 */
1157int32_t *SDDS_GetColumnInLong(SDDS_DATASET *SDDS_dataset, char *column_name) {
1158 int32_t size, type, index;
1159 int64_t i, j, n_rows;
1160 int32_t *data;
1161 void *rawData;
1162 j = 0;
1163 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetColumnInLong"))
1164 return (NULL);
1165 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1166 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetColumnInLong)");
1167 return (NULL);
1168 }
1169 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
1170 SDDS_SetError("Unable to get column--no rows left (SDDS_GetColumnInLong)");
1171 return (NULL);
1172 }
1173 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) <= 0 || (size = SDDS_GetTypeSize(type)) <= 0 || (!SDDS_NUMERIC_TYPE(type) && type != SDDS_CHARACTER)) {
1174 SDDS_SetError("Unable to get column--data size or type undefined or non-numeric (SDDS_GetColumnInLong)");
1175 return (NULL);
1176 }
1177 if (!(data = (int32_t *)SDDS_Malloc(sizeof(int32_t) * n_rows))) {
1178 SDDS_SetError("Unable to get column--memory allocation failure (SDDS_GetColumnInLong)");
1179 return (NULL);
1180 }
1181 rawData = SDDS_dataset->data[index];
1182 switch (type) {
1183 case SDDS_LONGDOUBLE:
1184 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1185 if (SDDS_dataset->row_flag[i])
1186 data[j++] = ((long double *)rawData)[i];
1187 }
1188 break;
1189 case SDDS_DOUBLE:
1190 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1191 if (SDDS_dataset->row_flag[i])
1192 data[j++] = ((double *)rawData)[i];
1193 }
1194 break;
1195 case SDDS_FLOAT:
1196 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1197 if (SDDS_dataset->row_flag[i])
1198 data[j++] = ((float *)rawData)[i];
1199 }
1200 break;
1201 case SDDS_LONG:
1202 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1203 if (SDDS_dataset->row_flag[i])
1204 data[j++] = ((int32_t *)rawData)[i];
1205 }
1206 break;
1207 case SDDS_ULONG:
1208 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1209 if (SDDS_dataset->row_flag[i])
1210 data[j++] = ((uint32_t *)rawData)[i];
1211 }
1212 break;
1213 case SDDS_LONG64:
1214 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1215 if (SDDS_dataset->row_flag[i])
1216 data[j++] = ((int64_t *)rawData)[i];
1217 }
1218 break;
1219 case SDDS_ULONG64:
1220 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1221 if (SDDS_dataset->row_flag[i])
1222 data[j++] = ((uint64_t *)rawData)[i];
1223 }
1224 break;
1225 case SDDS_SHORT:
1226 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1227 if (SDDS_dataset->row_flag[i])
1228 data[j++] = ((short *)rawData)[i];
1229 }
1230 break;
1231 case SDDS_USHORT:
1232 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1233 if (SDDS_dataset->row_flag[i])
1234 data[j++] = ((unsigned short *)rawData)[i];
1235 }
1236 break;
1237 case SDDS_CHARACTER:
1238 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1239 if (SDDS_dataset->row_flag[i])
1240 data[j++] = ((char *)rawData)[i];
1241 }
1242 break;
1243 }
1244 if (j != n_rows) {
1245 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetColumnInLong)");
1246 return (NULL);
1247 }
1248 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
1249 SDDS_dataset->column_track_memory[index] = 0;
1250 //Free internal copy now under the assumption that the program will not ask for it again.
1251 if (type == SDDS_STRING) {
1252 if (0) {
1253 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
1254 char **ptr = (char **)SDDS_dataset->data[index];
1255 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
1256 if (*ptr)
1257 free(*ptr);
1258 free(SDDS_dataset->data[index]);
1259 SDDS_dataset->data[index] = NULL;
1260 }
1261 } else {
1262 free(SDDS_dataset->data[index]);
1263 SDDS_dataset->data[index] = NULL;
1264 }
1265 }
1266 return (data);
1267}
1268
1269/**
1270 * @brief Retrieves the data of a specified numerical column as an array of short integers, considering only rows marked as "of interest".
1271 *
1272 * This function extracts data from a specified column within the current data table of a dataset. It processes only those rows that are flagged as "of interest" (i.e., have a non-zero acceptance flag). The extracted data is returned as a newly allocated array of `short` values.
1273 *
1274 * @param SDDS_dataset
1275 * Pointer to the `SDDS_DATASET` structure representing the data set.
1276 * @param column_name
1277 * NULL-terminated string specifying the name of the column from which data is to be retrieved.
1278 *
1279 * @return
1280 * - **Pointer to an array of `short`** containing the data from the specified column for all rows marked as "of interest".
1281 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized column name, non-numeric column type, memory allocation failure). In this case, an error message is recorded internally.
1282 *
1283 * @warning
1284 * - The caller is responsible for freeing the allocated memory to prevent memory leaks.
1285 * - This function assumes that the specified column contains numerical data. Attempting to retrieve data from a non-numeric column (excluding `SDDS_CHARACTER`) will result in an error.
1286 *
1287 * @note
1288 * - The number of elements in the returned array corresponds to the number of rows marked as "of interest", which can be obtained using `SDDS_CountRowsOfInterest`.
1289 * - If the dataset's memory mode for the column is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the column may be freed after access.
1290 *
1291 * @sa
1292 * - `SDDS_GetColumnInLongDoubles`
1293 * - `SDDS_GetColumnInDoubles`
1294 * - `SDDS_GetColumnInFloats`
1295 * - `SDDS_GetColumn`
1296 * - `SDDS_CountRowsOfInterest`
1297 */
1298short *SDDS_GetColumnInShort(SDDS_DATASET *SDDS_dataset, char *column_name) {
1299 int32_t size, type, index;
1300 int64_t i, j, n_rows;
1301 short *data;
1302 void *rawData;
1303 j = 0;
1304 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetColumnInShort"))
1305 return (NULL);
1306 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1307 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetColumnInShort)");
1308 return (NULL);
1309 }
1310 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
1311 SDDS_SetError("Unable to get column--no rows left (SDDS_GetColumnInShort)");
1312 return (NULL);
1313 }
1314 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) <= 0 || (size = SDDS_GetTypeSize(type)) <= 0 || (!SDDS_NUMERIC_TYPE(type) && type != SDDS_CHARACTER)) {
1315 SDDS_SetError("Unable to get column--data size or type undefined or non-numeric (SDDS_GetColumnInShort)");
1316 return (NULL);
1317 }
1318 if (!(data = (short *)SDDS_Malloc(sizeof(short) * n_rows))) {
1319 SDDS_SetError("Unable to get column--memory allocation failure (SDDS_GetColumnInShort)");
1320 return (NULL);
1321 }
1322 rawData = SDDS_dataset->data[index];
1323 switch (type) {
1324 case SDDS_LONGDOUBLE:
1325 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1326 if (SDDS_dataset->row_flag[i])
1327 data[j++] = ((long double *)rawData)[i];
1328 }
1329 break;
1330 case SDDS_DOUBLE:
1331 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1332 if (SDDS_dataset->row_flag[i])
1333 data[j++] = ((double *)rawData)[i];
1334 }
1335 break;
1336 case SDDS_FLOAT:
1337 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1338 if (SDDS_dataset->row_flag[i])
1339 data[j++] = ((float *)rawData)[i];
1340 }
1341 break;
1342 case SDDS_LONG:
1343 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1344 if (SDDS_dataset->row_flag[i])
1345 data[j++] = ((int32_t *)rawData)[i];
1346 }
1347 break;
1348 case SDDS_ULONG:
1349 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1350 if (SDDS_dataset->row_flag[i])
1351 data[j++] = ((uint32_t *)rawData)[i];
1352 }
1353 break;
1354 case SDDS_LONG64:
1355 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1356 if (SDDS_dataset->row_flag[i])
1357 data[j++] = ((int64_t *)rawData)[i];
1358 }
1359 break;
1360 case SDDS_ULONG64:
1361 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1362 if (SDDS_dataset->row_flag[i])
1363 data[j++] = ((uint64_t *)rawData)[i];
1364 }
1365 break;
1366 case SDDS_SHORT:
1367 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1368 if (SDDS_dataset->row_flag[i])
1369 data[j++] = ((short *)rawData)[i];
1370 }
1371 break;
1372 case SDDS_USHORT:
1373 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1374 if (SDDS_dataset->row_flag[i])
1375 data[j++] = ((unsigned short *)rawData)[i];
1376 }
1377 break;
1378 case SDDS_CHARACTER:
1379 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1380 if (SDDS_dataset->row_flag[i])
1381 data[j++] = ((char *)rawData)[i];
1382 }
1383 break;
1384 }
1385 if (j != n_rows) {
1386 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetColumnInShort)");
1387 return (NULL);
1388 }
1389 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
1390 SDDS_dataset->column_track_memory[index] = 0;
1391 //Free internal copy now under the assumption that the program will not ask for it again.
1392 if (type == SDDS_STRING) {
1393 if (0) {
1394 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
1395 char **ptr = (char **)SDDS_dataset->data[index];
1396 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
1397 if (*ptr)
1398 free(*ptr);
1399 free(SDDS_dataset->data[index]);
1400 SDDS_dataset->data[index] = NULL;
1401 }
1402 } else {
1403 free(SDDS_dataset->data[index]);
1404 SDDS_dataset->data[index] = NULL;
1405 }
1406 }
1407 return (data);
1408}
1409
1410/**
1411 * @brief Retrieves the data of a specified column as an array of strings, considering only rows marked as "of interest".
1412 *
1413 * This function extracts data from a specified column within the current data table of a dataset. It processes only those rows that are flagged as "of interest" (i.e., have a non-zero acceptance flag). The extracted data is returned as a newly allocated array of `char*` (strings).
1414 *
1415 * @param SDDS_dataset
1416 * Pointer to the `SDDS_DATASET` structure representing the data set.
1417 * @param column_name
1418 * NULL-terminated string specifying the name of the column from which data is to be retrieved.
1419 *
1420 * @return
1421 * - **Pointer to an array of `char*`** containing the data from the specified column for all rows marked as "of interest".
1422 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized column name, non-string column type, memory allocation failure). In this case, an error message is recorded internally.
1423 *
1424 * @warning
1425 * - The caller is responsible for freeing the allocated memory to prevent memory leaks. Each string within the array should be freed individually, followed by the array itself.
1426 * - This function assumes that the specified column contains string data (`SDDS_STRING` or `SDDS_CHARACTER`). Attempting to retrieve data from a non-string column will result in an error.
1427 *
1428 * @note
1429 * - The number of elements in the returned array corresponds to the number of rows marked as "of interest", which can be obtained using `SDDS_CountRowsOfInterest`.
1430 * - If the dataset's memory mode for the column is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the column may be freed after access.
1431 *
1432 * @sa
1433 * - `SDDS_GetColumnInLongDoubles`
1434 * - `SDDS_GetColumnInDoubles`
1435 * - `SDDS_GetColumnInFloats`
1436 * - `SDDS_GetColumn`
1437 * - `SDDS_CountRowsOfInterest`
1438 */
1439char **SDDS_GetColumnInString(SDDS_DATASET *SDDS_dataset, char *column_name) {
1440 int32_t size, type, index;
1441 int64_t i, j, n_rows;
1442 char **data;
1443 char buffer[SDDS_MAXLINE];
1444
1445 void *rawData;
1446 j = 0;
1447 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetColumnInString"))
1448 return (NULL);
1449 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1450 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetColumnInString)");
1451 return (NULL);
1452 }
1453 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
1454 SDDS_SetError("Unable to get column--no rows left (SDDS_GetColumnInString)");
1455 return (NULL);
1456 }
1457
1458 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) <= 0 || (size = SDDS_GetTypeSize(type)) <= 0 ||
1459 (!SDDS_NUMERIC_TYPE(type) && type != SDDS_CHARACTER && type != SDDS_STRING)) {
1460 SDDS_SetError("Unable to get column--data size or type undefined or non-numeric (SDDS_GetColumnInString)");
1461 return (NULL);
1462 }
1463 if (!(data = (char **)SDDS_Malloc(sizeof(*data) * n_rows))) {
1464 SDDS_SetError("Unable to get column--memory allocation failure (SDDS_GetColumnInString)");
1465 return (NULL);
1466 }
1467 rawData = SDDS_dataset->data[index];
1468 switch (type) {
1469 case SDDS_LONGDOUBLE:
1470 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1471 if (SDDS_dataset->row_flag[i]) {
1472 if (LDBL_DIG == 18) {
1473 sprintf(buffer, "%22.18Le", ((long double *)rawData)[i]);
1474 } else {
1475 sprintf(buffer, "%22.15Le", ((long double *)rawData)[i]);
1476 }
1477 SDDS_CopyString(&data[j++], buffer);
1478 }
1479 }
1480 break;
1481 case SDDS_DOUBLE:
1482 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1483 if (SDDS_dataset->row_flag[i]) {
1484 sprintf(buffer, "%22.15le", ((double *)rawData)[i]);
1485 SDDS_CopyString(&data[j++], buffer);
1486 }
1487 }
1488 break;
1489 case SDDS_FLOAT:
1490 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1491 if (SDDS_dataset->row_flag[i]) {
1492 sprintf(buffer, "%15.8e", ((float *)rawData)[i]);
1493 SDDS_CopyString(&data[j++], buffer);
1494 }
1495 }
1496 break;
1497 case SDDS_LONG64:
1498 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1499 if (SDDS_dataset->row_flag[i]) {
1500 sprintf(buffer, "%" PRId64, ((int64_t *)rawData)[i]);
1501 SDDS_CopyString(&data[j++], buffer);
1502 }
1503 }
1504 break;
1505 case SDDS_ULONG64:
1506 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1507 if (SDDS_dataset->row_flag[i]) {
1508 sprintf(buffer, "%" PRIu64, ((uint64_t *)rawData)[i]);
1509 SDDS_CopyString(&data[j++], buffer);
1510 }
1511 }
1512 break;
1513 case SDDS_LONG:
1514 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1515 if (SDDS_dataset->row_flag[i]) {
1516 sprintf(buffer, "%" PRId32, ((int32_t *)rawData)[i]);
1517 SDDS_CopyString(&data[j++], buffer);
1518 }
1519 }
1520 break;
1521 case SDDS_ULONG:
1522 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1523 if (SDDS_dataset->row_flag[i]) {
1524 sprintf(buffer, "%" PRIu32, ((uint32_t *)rawData)[i]);
1525 SDDS_CopyString(&data[j++], buffer);
1526 }
1527 }
1528 break;
1529 case SDDS_SHORT:
1530 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1531 if (SDDS_dataset->row_flag[i]) {
1532 sprintf(buffer, "%hd", ((short *)rawData)[i]);
1533 SDDS_CopyString(&data[j++], buffer);
1534 }
1535 }
1536 break;
1537 case SDDS_USHORT:
1538 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1539 if (SDDS_dataset->row_flag[i]) {
1540 sprintf(buffer, "%hu", ((unsigned short *)rawData)[i]);
1541 SDDS_CopyString(&data[j++], buffer);
1542 }
1543 }
1544 break;
1545 case SDDS_CHARACTER:
1546 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1547 if (SDDS_dataset->row_flag[i]) {
1548 sprintf(buffer, "%c", ((char *)rawData)[i]);
1549 SDDS_CopyString(&data[j++], buffer);
1550 }
1551 }
1552 break;
1553 case SDDS_STRING:
1554 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1555 if (SDDS_dataset->row_flag[i]) {
1556 SDDS_CopyString(&data[j++], ((char **)rawData)[i]);
1557 }
1558 }
1559 break;
1560 }
1561 if (j != n_rows) {
1562 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetColumnInString)");
1563 return (NULL);
1564 }
1565 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
1566 SDDS_dataset->column_track_memory[index] = 0;
1567 //Free internal copy now under the assumption that the program will not ask for it again.
1568 if (type == SDDS_STRING) {
1569 if (0) {
1570 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
1571 char **ptr = (char **)SDDS_dataset->data[index];
1572 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
1573 if (*ptr)
1574 free(*ptr);
1575 free(SDDS_dataset->data[index]);
1576 SDDS_dataset->data[index] = NULL;
1577 }
1578 } else {
1579 free(SDDS_dataset->data[index]);
1580 SDDS_dataset->data[index] = NULL;
1581 }
1582 }
1583 return (data);
1584}
1585
1586/**
1587 * @brief Retrieves the data of a specified numerical column as an array of a desired numerical type, considering only rows marked as "of interest".
1588 *
1589 * This function extracts data from a specified column within the current data table of a dataset. It processes only those rows that are flagged as "of interest" (i.e., have a non-zero acceptance flag). The extracted data is returned as a newly allocated array of the specified numerical type.
1590 *
1591 * @param SDDS_dataset
1592 * Pointer to the `SDDS_DATASET` structure representing the data set.
1593 * @param column_name
1594 * NULL-terminated string specifying the name of the column from which data is to be retrieved.
1595 * @param desiredType
1596 * Integer constant representing the desired data type for the returned array. Must be one of the supported `SDDS` numerical types (e.g., `SDDS_DOUBLE`, `SDDS_FLOAT`, etc.).
1597 *
1598 * @return
1599 * - **Pointer to an array of the desired numerical type** containing the data from the specified column for all rows marked as "of interest".
1600 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized column name, non-numeric column type, memory allocation failure, type casting failure). In this case, an error message is recorded internally.
1601 *
1602 * @warning
1603 * - The caller is responsible for freeing the allocated memory to prevent memory leaks.
1604 * - This function assumes that the specified column contains numerical data. Attempting to retrieve data from a non-numeric column (excluding `SDDS_CHARACTER`) will result in an error.
1605 *
1606 * @note
1607 * - The number of elements in the returned array corresponds to the number of rows marked as "of interest", which can be obtained using `SDDS_CountRowsOfInterest`.
1608 * - If the dataset's memory mode for the column is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the column may be freed after access.
1609 * - If the `desiredType` matches the column's data type, this function internally calls `SDDS_GetColumn`. Otherwise, it performs type casting using `SDDS_CastValue`.
1610 *
1611 * @sa
1612 * - `SDDS_GetColumnInLongDoubles`
1613 * - `SDDS_GetColumnInDoubles`
1614 * - `SDDS_GetColumnInFloats`
1615 * - `SDDS_GetColumn`
1616 * - `SDDS_CountRowsOfInterest`
1617 */
1618void *SDDS_GetNumericColumn(SDDS_DATASET *SDDS_dataset, char *column_name, int32_t desiredType) {
1619 int32_t size, type, desiredTypeSize, index;
1620 int64_t i, j, n_rows;
1621 void *data;
1622 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetNumericColumn"))
1623 return (NULL);
1624 if (!SDDS_NUMERIC_TYPE(desiredType) && desiredType != SDDS_CHARACTER) {
1625 SDDS_SetError("Unable to get column--desired type is nonnumeric (SDDS_GetNumericColumn)");
1626 return (NULL);
1627 }
1628 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1629 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetNumericColumn)");
1630 return (NULL);
1631 }
1632 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) <= 0 || (size = SDDS_GetTypeSize(type)) <= 0 || (!SDDS_NUMERIC_TYPE(type) && type != SDDS_CHARACTER)) {
1633 SDDS_SetError("Unable to get column--data size or type undefined or non-numeric (SDDS_GetNumericColumn)");
1634 return (NULL);
1635 }
1636 if (type == desiredType)
1637 return SDDS_GetColumn(SDDS_dataset, column_name);
1638 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
1639 SDDS_SetError("Unable to get column--no rows left (SDDS_GetNumericColumn)");
1640 return (NULL);
1641 }
1642 if (!(data = (void *)SDDS_Malloc((desiredTypeSize = SDDS_GetTypeSize(desiredType)) * n_rows))) {
1643 SDDS_SetError("Unable to get column--memory allocation failure (SDDS_GetNumericColumn)");
1644 return (NULL);
1645 }
1646 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1647 if (SDDS_dataset->row_flag[i] && !SDDS_CastValue(SDDS_dataset->data[index], i, type, desiredType, (char *)data + desiredTypeSize * j++)) {
1648 SDDS_SetError("Unable to get column--cast to double failed (SDDS_GetNumericColumn)");
1649 return (NULL);
1650 }
1651 }
1652 if (j != n_rows) {
1653 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetNumericColumn)");
1654 return (NULL);
1655 }
1656 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
1657 SDDS_dataset->column_track_memory[index] = 0;
1658 //Free internal copy now under the assumption that the program will not ask for it again.
1659 if (type == SDDS_STRING) {
1660 if (0) {
1661 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
1662 char **ptr = (char **)SDDS_dataset->data[index];
1663 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
1664 if (*ptr)
1665 free(*ptr);
1666 free(SDDS_dataset->data[index]);
1667 SDDS_dataset->data[index] = NULL;
1668 }
1669 } else {
1670 free(SDDS_dataset->data[index]);
1671 SDDS_dataset->data[index] = NULL;
1672 }
1673 }
1674 return (data);
1675}
1676
1677/**
1678 * @brief Retrieves the actual row index corresponding to a selected row position within the current data table.
1679 *
1680 * This function maps a selected row index (i.e., the position among rows marked as "of interest") to its corresponding actual row index within the dataset's data table.
1681 *
1682 * @param SDDS_dataset
1683 * Pointer to the `SDDS_DATASET` structure representing the data set.
1684 * @param srow_index
1685 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1686 *
1687 * @return
1688 * - **Non-negative integer** representing the actual row index within the dataset's data table.
1689 * - **-1** if an error occurs (e.g., invalid dataset, tabular data not present, `srow_index` out of range).
1690 *
1691 * @warning
1692 * - Ensure that `srow_index` is within the valid range [0, `SDDS_CountRowsOfInterest(SDDS_dataset)` - 1] to avoid out-of-range errors.
1693 *
1694 * @note
1695 * - This function is useful when iterating over selected rows and needing to access their actual positions within the dataset.
1696 *
1697 * @sa
1698 * - `SDDS_CountRowsOfInterest`
1699 * - `SDDS_GetValue`
1700 * - `SDDS_GetValueAsDouble`
1701 */
1702int64_t SDDS_GetSelectedRowIndex(SDDS_DATASET *SDDS_dataset, int64_t srow_index) {
1703 int64_t i, j;
1704 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetSelectedRowIndex"))
1705 return (-1);
1706 if (!SDDS_CheckTabularData(SDDS_dataset, "SDDS_GetSelectedRowIndex"))
1707 return (-1);
1708 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1709 if (SDDS_dataset->row_flag[i] && j++ == srow_index)
1710 break;
1711 }
1712 if (i == SDDS_dataset->n_rows)
1713 return (-1);
1714 return (i);
1715}
1716
1717/**
1718 * @brief Retrieves the value from a specified column and selected row, optionally storing it in provided memory.
1719 *
1720 * This function accesses the value of a specific column and selected row within the current data table of a dataset. It returns the value as a pointer to the data, allowing for both direct access and optional storage in user-provided memory.
1721 *
1722 * @param SDDS_dataset
1723 * Pointer to the `SDDS_DATASET` structure representing the data set.
1724 * @param column_name
1725 * NULL-terminated string specifying the name of the column from which the value is to be retrieved.
1726 * @param srow_index
1727 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1728 * @param memory
1729 * Pointer to user-allocated memory where the retrieved value will be stored. If `NULL`, the function allocates memory internally, and the caller is responsible for freeing it.
1730 *
1731 * @return
1732 * - **Pointer to the retrieved value** stored in `memory` (if provided) or in newly allocated memory.
1733 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized column name, undefined data type, memory allocation failure, invalid row index). In this case, an error message is recorded internally.
1734 *
1735 * @warning
1736 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
1737 * - The function does not perform type casting. Ensure that the provided `memory` is of the appropriate type matching the column's data type.
1738 * - Modifying the data through the returned pointer affects the internal state of the dataset. Use with caution to avoid unintended side effects.
1739 *
1740 * @note
1741 * - For columns containing string data (`SDDS_STRING`), the function copies the string into `memory`. A typical usage would involve passing a pointer to a `char*` variable.
1742 * ```c
1743 * char *string;
1744 * SDDS_GetValue(&SDDS_dataset, "name", index, &string);
1745 * // or
1746 * string = *(char**)SDDS_GetValue(&SDDS_dataset, "name", index, NULL);
1747 * ```
1748 * - The number of rows marked as "of interest" can be obtained using `SDDS_CountRowsOfInterest`.
1749 *
1750 * @sa
1751 * - `SDDS_GetValueAsDouble`
1752 * - `SDDS_GetSelectedRowIndex`
1753 * - `SDDS_CountRowsOfInterest`
1754 */
1755void *SDDS_GetValue(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t srow_index, void *memory) {
1756 int32_t type, size, column_index;
1757 int64_t row_index;
1758 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValue"))
1759 return (NULL);
1760 if ((column_index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1761 SDDS_SetError("Unable to get value--column name is not recognized (SDDS_GetValue)");
1762 return (NULL);
1763 }
1764 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
1765 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValue)");
1766 return (NULL);
1767 }
1768 size = SDDS_type_size[type - 1];
1769 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
1770 SDDS_SetError("Unable to get value--row index out of range (SDDS_GetValue)");
1771 return (NULL);
1772 }
1773 if (type != SDDS_STRING) {
1774 if (!memory && !(memory = SDDS_Malloc(size))) {
1775 SDDS_SetError("Unable to get value--memory allocation failure (SDDS_GetValue)");
1776 return (NULL);
1777 }
1778 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
1779 return (memory);
1780 }
1781 /* for character string data, a typical call would be
1782 * char *string;
1783 * SDDS_GetValue(&SDDS_dataset, "name", index, &string) or
1784 * string = *(char**)SDDS_GetValue(&SDDS_dataset, "name", index, NULL)
1785 */
1786 if (!memory && !(memory = SDDS_Malloc(size))) {
1787 SDDS_SetError("Unable to get value--memory allocation failure (SDDS_GetValue)");
1788 return (NULL);
1789 }
1790 if (SDDS_CopyString(memory, ((char **)SDDS_dataset->data[column_index])[row_index]))
1791 return (memory);
1792 return (NULL);
1793}
1794
1795/**
1796 * @brief Retrieves the value from a specified column and selected row, casting it to a double.
1797 *
1798 * This function accesses the value of a specific column and selected row within the current data table of a dataset. It casts the retrieved value to a `double` before returning it.
1799 *
1800 * @param SDDS_dataset
1801 * Pointer to the `SDDS_DATASET` structure representing the data set.
1802 * @param column_name
1803 * NULL-terminated string specifying the name of the column from which the value is to be retrieved.
1804 * @param srow_index
1805 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1806 *
1807 * @return
1808 * - **Double** representing the casted value from the specified column and row.
1809 * - **0** if an error occurs (e.g., invalid dataset, unrecognized column name, undefined data type, invalid row index, non-numeric column type). In this case, an error message is recorded internally.
1810 *
1811 * @warning
1812 * - This function only supports numerical data types. Attempting to retrieve and cast data from non-numeric columns (excluding `SDDS_CHARACTER`) will result in an error.
1813 *
1814 * @note
1815 * - The function internally allocates temporary memory to store the value before casting. This memory is freed before the function returns.
1816 *
1817 * @sa
1818 * - `SDDS_GetValue`
1819 * - `SDDS_GetSelectedRowIndex`
1820 * - `SDDS_CountRowsOfInterest`
1821 */
1822double SDDS_GetValueAsDouble(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t srow_index) {
1823 int32_t type, size, column_index;
1824 int64_t row_index;
1825 void *memory;
1826 double value = 0;
1827 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValueAsDouble"))
1828 return (0);
1829 if ((column_index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1830 SDDS_SetError("Unable to get value--column name is not recognized (SDDS_GetValueAsDouble)");
1831 return (0);
1832 }
1833 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
1834 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValueAsDouble)");
1835 return (0);
1836 }
1837 size = SDDS_type_size[type - 1];
1838 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
1839 SDDS_SetError("Unable to get value--row index out of range (SDDS_GetValueAsDouble)");
1840 return (0);
1841 }
1842 if ((type != SDDS_STRING) && (type != SDDS_CHARACTER)) {
1843 memory = SDDS_Malloc(size);
1844 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
1845 switch (type) {
1846 case SDDS_SHORT:
1847 value = *(short *)memory;
1848 break;
1849 case SDDS_USHORT:
1850 value = *(unsigned short *)memory;
1851 break;
1852 case SDDS_LONG:
1853 value = *(int32_t *)memory;
1854 break;
1855 case SDDS_ULONG:
1856 value = *(uint32_t *)memory;
1857 break;
1858 case SDDS_LONG64:
1859 value = *(int64_t *)memory;
1860 break;
1861 case SDDS_ULONG64:
1862 value = *(uint64_t *)memory;
1863 break;
1864 case SDDS_FLOAT:
1865 value = *(float *)memory;
1866 break;
1867 case SDDS_DOUBLE:
1868 value = *(double *)memory;
1869 break;
1870 case SDDS_LONGDOUBLE:
1871 value = *(long double *)memory;
1872 break;
1873 }
1874 free(memory);
1875 return (value);
1876 }
1877 SDDS_SetError("Unable to get non-numeric value as double (SDDS_GetValueAsDouble)");
1878 return (0);
1879}
1880
1881/**
1882 * @brief Retrieves the value from a specified column and selected row, casting it to a double.
1883 *
1884 * This function accesses the value of a specific column (identified by its index) and a selected row (identified by its
1885 * selected row index among rows marked as "of interest") within the current data table of a dataset. It casts the retrieved
1886 * value to a `double` before returning it.
1887 *
1888 * @param SDDS_dataset
1889 * Pointer to the `SDDS_DATASET` structure representing the data set.
1890 * @param column_index
1891 * Zero-based index of the column from which the value is to be retrieved. Must be within the range [0, n_columns-1].
1892 * @param srow_index
1893 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1894 *
1895 * @return
1896 * - **Double** representing the casted value from the specified column and row.
1897 * - **0.0** if an error occurs (e.g., invalid dataset, column index out of range, undefined data type, row index out of range,
1898 * non-numeric column type). In this case, an error message is recorded internally.
1899 *
1900 * @warning
1901 * - This function only supports numerical data types. Attempting to retrieve and cast data from non-numeric columns (excluding `SDDS_CHARACTER`)
1902 * will result in an error.
1903 * - The returned value `0.0` may be ambiguous if it is a valid data value. Always check for errors using `SDDS_CheckError` or similar mechanisms.
1904 *
1905 * @note
1906 * - The number of rows marked as "of interest" can be obtained using `SDDS_CountRowsOfInterest`.
1907 * - If the dataset's memory mode for the column is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the column may be freed after access.
1908 *
1909 * @sa
1910 * - `SDDS_GetValue`
1911 * - `SDDS_GetValueAsDouble`
1912 * - `SDDS_GetSelectedRowIndex`
1913 * - `SDDS_CountRowsOfInterest`
1914 */
1915double SDDS_GetValueByIndexAsDouble(SDDS_DATASET *SDDS_dataset, int32_t column_index, int64_t srow_index) {
1916 int32_t type, size;
1917 int64_t row_index;
1918 void *memory;
1919 double value = 0;
1920 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValueByIndexAsDouble"))
1921 return (0);
1922 if (column_index < 0 || column_index >= SDDS_dataset->layout.n_columns) {
1923 SDDS_SetError("Unable to get value--column index out of range (SDDS_GetValueByIndexAsDouble)");
1924 return (0);
1925 }
1926 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
1927 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValueByIndexAsDouble)");
1928 return (0);
1929 }
1930 size = SDDS_type_size[type - 1];
1931 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
1932 SDDS_SetError("Unable to get value--row index out of range (SDDS_GetValueByIndexAsDouble)");
1933 return (0);
1934 }
1935 if ((type != SDDS_STRING) && (type != SDDS_CHARACTER)) {
1936 memory = SDDS_Malloc(size);
1937 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
1938 switch (type) {
1939 case SDDS_SHORT:
1940 value = *(short *)memory;
1941 break;
1942 case SDDS_USHORT:
1943 value = *(unsigned short *)memory;
1944 break;
1945 case SDDS_LONG:
1946 value = *(int32_t *)memory;
1947 break;
1948 case SDDS_ULONG:
1949 value = *(uint32_t *)memory;
1950 break;
1951 case SDDS_LONG64:
1952 value = *(int64_t *)memory;
1953 break;
1954 case SDDS_ULONG64:
1955 value = *(uint64_t *)memory;
1956 break;
1957 case SDDS_FLOAT:
1958 value = *(float *)memory;
1959 break;
1960 case SDDS_DOUBLE:
1961 value = *(double *)memory;
1962 break;
1963 case SDDS_LONGDOUBLE:
1964 value = *(long double *)memory;
1965 break;
1966 }
1967 free(memory);
1968 return (value);
1969 }
1970 SDDS_SetError("Unable to get non-numeric value as double (SDDS_GetValueByIndexAsDouble)");
1971 return (0);
1972}
1973
1974/**
1975 * @brief Retrieves the value from a specified column and selected row, optionally storing it in provided memory.
1976 *
1977 * This function accesses the value of a specific column (identified by its index) and a selected row (identified by its
1978 * selected row index among rows marked as "of interest") within the current data table of a dataset. The retrieved value is either
1979 * copied into user-provided memory or returned as a direct pointer to the internal data.
1980 *
1981 * @param SDDS_dataset
1982 * Pointer to the `SDDS_DATASET` structure representing the data set.
1983 * @param column_index
1984 * Zero-based index of the column from which the value is to be retrieved. Must be within the range [0, n_columns-1].
1985 * @param srow_index
1986 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1987 * @param memory
1988 * Pointer to user-allocated memory where the retrieved value will be stored. If `NULL`, the function returns a pointer to the internal data.
1989 *
1990 * @return
1991 * - **Pointer to the retrieved value** stored in `memory` (if provided) or to the internal data.
1992 * - **NULL** if an error occurs (e.g., invalid dataset, column index out of range, undefined data type, row index out of range, memory allocation failure, non-numeric column type). In this case, an error message is recorded internally.
1993 *
1994 * @warning
1995 * - If `memory` is `NULL`, the function returns a direct pointer to the internal data. Modifying the data through this pointer affects the dataset's internal state.
1996 * - If `memory` is provided, ensure that it points to sufficient memory to hold the data type of the column.
1997 * - This function does not perform type casting. Ensure that the `memory` type matches the column's data type.
1998 *
1999 * @note
2000 * - For columns containing string data (`SDDS_STRING`), the function copies the string into `memory`. A typical usage would involve passing a pointer to a `char*` variable.
2001 * ```c
2002 * char *string;
2003 * SDDS_GetValueByIndex(&SDDS_dataset, column_index, index, &string);
2004 * // or
2005 * string = *(char**)SDDS_GetValueByIndex(&SDDS_dataset, column_index, index, NULL);
2006 * ```
2007 * - The number of rows marked as "of interest" can be obtained using `SDDS_CountRowsOfInterest`.
2008 *
2009 * @sa
2010 * - `SDDS_GetValue`
2011 * - `SDDS_GetValueAsDouble`
2012 * - `SDDS_GetSelectedRowIndex`
2013 * - `SDDS_CountRowsOfInterest`
2014 */
2015void *SDDS_GetValueByIndex(SDDS_DATASET *SDDS_dataset, int32_t column_index, int64_t srow_index, void *memory) {
2016 int32_t type, size;
2017 int64_t row_index;
2018 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValueByIndex"))
2019 return (NULL);
2020 if (column_index < 0 || column_index >= SDDS_dataset->layout.n_columns) {
2021 SDDS_SetError("Unable to get value--column index out of range (SDDS_GetValueByIndex)");
2022 return (NULL);
2023 }
2024 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
2025 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValueByIndex)");
2026 return (NULL);
2027 }
2028 size = SDDS_type_size[type - 1];
2029 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
2030 SDDS_SetError("Unable to get value--row index out of range (SDDS_GetValueByIndex)");
2031 return (NULL);
2032 }
2033 if (type != SDDS_STRING) {
2034 if (memory) {
2035 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
2036 return (memory);
2037 }
2038 return ((char *)SDDS_dataset->data[column_index] + row_index * size);
2039 }
2040 /* for character string data, a typical call would be
2041 * char *string;
2042 * SDDS_GetValueByIndex(&SDDS_dataset, cindex, index, &string) or
2043 * string = *(char**)SDDS_GetValue(&SDDS_dataset, cindex, index, NULL)
2044 */
2045 if (!memory)
2046 memory = SDDS_Malloc(size);
2047 if (SDDS_CopyString(memory, ((char **)SDDS_dataset->data[column_index])[row_index]))
2048 return (memory);
2049 return (NULL);
2050}
2051
2052/**
2053 * @brief Retrieves the value from a specified column and absolute row index, optionally storing it in provided memory.
2054 *
2055 * This function accesses the value of a specific column (identified by its index) and an absolute row index within the current
2056 * data table of a dataset. The retrieved value is either copied into user-provided memory or returned as a direct pointer to the internal data.
2057 *
2058 * @param SDDS_dataset
2059 * Pointer to the `SDDS_DATASET` structure representing the data set.
2060 * @param column_index
2061 * Zero-based index of the column from which the value is to be retrieved. Must be within the range [0, n_columns-1].
2062 * @param row_index
2063 * Absolute zero-based row index within the dataset's data table. Must be within the range [0, n_rows-1].
2064 * @param memory
2065 * Pointer to user-allocated memory where the retrieved value will be stored. If `NULL`, the function returns a pointer to the internal data.
2066 *
2067 * @return
2068 * - **Pointer to the retrieved value** stored in `memory` (if provided) or to the internal data.
2069 * - **NULL** if an error occurs (e.g., invalid dataset, column index out of range, row index out of range, undefined data type, memory allocation failure, non-numeric column type). In this case, an error message is recorded internally.
2070 *
2071 * @warning
2072 * - If `memory` is `NULL`, the function returns a direct pointer to the internal data. Modifying the data through this pointer affects the dataset's internal state.
2073 * - If `memory` is provided, ensure that it points to sufficient memory to hold the data type of the column.
2074 * - This function does not perform type casting. Ensure that the `memory` type matches the column's data type.
2075 *
2076 * @note
2077 * - Unlike `SDDS_GetValueByIndex`, this function uses an absolute row index rather than a selected row index among rows marked as "of interest".
2078 * - For columns containing string data (`SDDS_STRING`), the function copies the string into `memory`. A typical usage would involve passing a pointer to a `char*` variable.
2079 * ```c
2080 * char *string;
2081 * SDDS_GetValueByAbsIndex(&SDDS_dataset, column_index, row_index, &string);
2082 * // or
2083 * string = *(char**)SDDS_GetValueByAbsIndex(&SDDS_dataset, column_index, row_index, NULL);
2084 * ```
2085 *
2086 * @sa
2087 * - `SDDS_GetValue`
2088 * - `SDDS_GetValueAsDouble`
2089 * - `SDDS_CountRowsOfInterest`
2090 */
2091void *SDDS_GetValueByAbsIndex(SDDS_DATASET *SDDS_dataset, int32_t column_index, int64_t row_index, void *memory) {
2092 int32_t type, size;
2093 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValueByAbsIndex"))
2094 return (NULL);
2095 if (column_index < 0 || column_index >= SDDS_dataset->layout.n_columns) {
2096 SDDS_SetError("Unable to get value--column index out of range (SDDS_GetValueByAbsIndex)");
2097 return (NULL);
2098 }
2099 if (row_index < 0 || row_index >= SDDS_dataset->n_rows) {
2100 SDDS_SetError("Unable to get value--index out of range (SDDS_GetValueByAbsIndex)");
2101 return (NULL);
2102 }
2103 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
2104 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValueByAbsIndex)");
2105 return (NULL);
2106 }
2107 size = SDDS_type_size[type - 1];
2108 if (type != SDDS_STRING) {
2109 if (memory) {
2110 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
2111 return (memory);
2112 }
2113 return ((char *)SDDS_dataset->data[column_index] + row_index * size);
2114 }
2115 /* for character string data, a typical call would be
2116 * char *string;
2117 * SDDS_GetValueByAbsIndex(&SDDS_dataset, cindex, index, &string) or
2118 * string = *(char**)SDDS_GetValue(&SDDS_dataset, cindex, index, NULL)
2119 */
2120 if (!memory)
2121 memory = SDDS_Malloc(size);
2122 if (SDDS_CopyString(memory, ((char **)SDDS_dataset->data[column_index])[row_index]))
2123 return (memory);
2124 return (NULL);
2125}
2126
2127/**
2128 * @brief Determines the data type of the rows based on selected columns in the current data table.
2129 *
2130 * This function iterates through all columns marked as "of interest" and verifies that they share the same data type. If all selected columns have a consistent data type, that type is returned. If there is a mismatch in data types among the selected columns, an error is recorded.
2131 *
2132 * @param SDDS_dataset
2133 * Pointer to the `SDDS_DATASET` structure representing the data set.
2134 *
2135 * @return
2136 * - **Integer representing the data type** (as defined by SDDS constants) if all selected columns have the same data type.
2137 * - **0** on failure (e.g., invalid dataset, no columns selected, inconsistent data types among selected columns). In this case, an error message is recorded internally.
2138 *
2139 * @warning
2140 * - Ensure that at least one column is marked as "of interest" before calling this function to avoid unexpected results.
2141 *
2142 * @note
2143 * - This function is useful for operations that require uniform data types across all selected columns.
2144 *
2145 * @sa
2146 * - `SDDS_GetRow`
2147 * - `SDDS_SetColumnFlags`
2148 * - `SDDS_GetColumnType`
2149 */
2150int32_t SDDS_GetRowType(SDDS_DATASET *SDDS_dataset) {
2151 int64_t i;
2152 int32_t type;
2153 type = -1;
2154 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetRowType"))
2155 return (0);
2156 for (i = 0; i < SDDS_dataset->layout.n_columns; i++) {
2157 if (!SDDS_dataset->column_flag[i])
2158 continue;
2159 if (type == -1)
2160 type = SDDS_dataset->layout.column_definition[i].type;
2161 else if (type != SDDS_dataset->layout.column_definition[i].type) {
2162 SDDS_SetError("Unable to get row type--inconsistent data type for selected columns (SDDS_GetRowType)");
2163 return (0);
2164 }
2165 }
2166 return (type);
2167}
2168
2169/**
2170 * @brief Retrieves the data of a specific selected row as an array, considering only columns marked as "of interest".
2171 *
2172 * This function extracts data from a specific selected row (identified by its selected row index among rows marked as "of interest")
2173 * within the current data table of a dataset. It processes only those columns that are flagged as "of interest" and returns the row's data
2174 * as a newly allocated array or stores it in user-provided memory.
2175 *
2176 * @param SDDS_dataset
2177 * Pointer to the `SDDS_DATASET` structure representing the data set.
2178 * @param srow_index
2179 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
2180 * @param memory
2181 * Pointer to user-allocated memory where the retrieved row data will be stored. If `NULL`, the function allocates memory.
2182 *
2183 * @return
2184 * - **Pointer to the retrieved row data array** stored in `memory` (if provided) or to newly allocated memory.
2185 * - **NULL** if an error occurs (e.g., invalid dataset, row index out of range, inconsistent row types, memory allocation failure). In this case, an error message is recorded internally.
2186 *
2187 * @warning
2188 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
2189 * - All selected columns must have the same data type. If there is an inconsistency, the function will fail.
2190 * - For columns containing string data (`SDDS_STRING`), each element in the returned array is a dynamically allocated string that must be freed individually, followed by the array itself.
2191 *
2192 * @note
2193 * - The number of elements in the returned array corresponds to the number of columns marked as "of interest", which can be obtained using `SDDS_CountColumnsOfInterest`.
2194 * - If the dataset's memory mode for the columns is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the columns may be freed after access.
2195 *
2196 * @sa
2197 * - `SDDS_GetRowType`
2198 * - `SDDS_SetColumnFlags`
2199 * - `SDDS_GetValue`
2200 * - `SDDS_CountColumnsOfInterest`
2201 */
2202void *SDDS_GetRow(SDDS_DATASET *SDDS_dataset, int64_t srow_index, void *memory) {
2203 void *data;
2204 int32_t size, type;
2205 int64_t i, row_index;
2206
2207 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetRow"))
2208 return (NULL);
2209 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
2210 SDDS_SetError("Unable to get row--row index out of range (SDDS_GetRow)");
2211 return (NULL);
2212 }
2213 if (SDDS_dataset->n_of_interest <= 0) {
2214 SDDS_SetError("Unable to get row--no columns selected (SDDS_GetRow)");
2215 return (NULL);
2216 }
2217 if ((type = SDDS_GetRowType(SDDS_dataset)) <= 0) {
2218 SDDS_SetError("Unable to get row--inconsistent data type in selected columns (SDDS_GetRow)");
2219 return (NULL);
2220 }
2221 size = SDDS_type_size[type - 1];
2222 if (memory)
2223 data = memory;
2224 else if (!(data = SDDS_Malloc(size * SDDS_dataset->n_of_interest))) {
2225 SDDS_SetError("Unable to get row--memory allocation failure (SDDS_GetRow)");
2226 return (NULL);
2227 }
2228 if (type != SDDS_STRING)
2229 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2230 memcpy((char *)data + i * size, (char *)SDDS_dataset->data[SDDS_dataset->column_order[i]] + row_index * size, size);
2231 else
2232 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2233 if (!SDDS_CopyString((char **)data + i, ((char **)SDDS_dataset->data[SDDS_dataset->column_order[i]])[row_index]))
2234 return (NULL);
2235 return (data);
2236}
2237
2238/**
2239 * @brief Retrieves all rows marked as "of interest" as a matrix (array of row arrays).
2240 *
2241 * This function extracts all rows that are flagged as "of interest" within the current data table of a dataset. It processes only those columns that are flagged as "of interest" and returns the data as a matrix, where each row is an array of values corresponding to the selected columns.
2242 *
2243 * @param SDDS_dataset
2244 * Pointer to the `SDDS_DATASET` structure representing the data set.
2245 * @param n_rows
2246 * Pointer to an `int64_t` variable where the number of rows retrieved will be stored.
2247 *
2248 * @return
2249 * - **Pointer to an array of pointers**, where each pointer references a row's data array.
2250 * - **NULL** if an error occurs (e.g., invalid dataset, no columns selected, inconsistent row types, memory allocation failure). In this case, an error message is recorded internally.
2251 *
2252 * @warning
2253 * - The caller is responsible for freeing the allocated memory to prevent memory leaks. This includes freeing each individual row array followed by the array of pointers itself.
2254 * - All selected columns must have the same data type. If there is an inconsistency, the function will fail.
2255 *
2256 * @note
2257 * - The number of rows retrieved is stored in the variable pointed to by `n_rows`.
2258 * - For columns containing string data (`SDDS_STRING`), each element in the row arrays is a dynamically allocated string that must be freed individually.
2259 * - If the dataset's memory mode for the columns is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the columns may be freed after access.
2260 *
2261 * @sa
2262 * - `SDDS_GetRowType`
2263 * - `SDDS_SetColumnFlags`
2264 * - `SDDS_GetRow`
2265 * - `SDDS_CountRowsOfInterest`
2266 */
2267void *SDDS_GetMatrixOfRows(SDDS_DATASET *SDDS_dataset, int64_t *n_rows) {
2268 void **data;
2269 int32_t size, type;
2270 int64_t i, j, k;
2271 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetMatrixOfRows"))
2272 return (NULL);
2273 if (SDDS_dataset->n_of_interest <= 0) {
2274 SDDS_SetError("Unable to get matrix of rows--no columns selected (SDDS_GetMatrixOfRows)");
2275 return (NULL);
2276 }
2277 if (!SDDS_CheckTabularData(SDDS_dataset, "SDDS_GetMatrixOfRows"))
2278 return (NULL);
2279 if ((type = SDDS_GetRowType(SDDS_dataset)) <= 0) {
2280 SDDS_SetError("Unable to get row--inconsistent data type in selected columns (SDDS_GetMatrixOfRows)");
2281 return (NULL);
2282 }
2283 size = SDDS_type_size[type - 1];
2284 if ((*n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
2285 SDDS_SetError("Unable to get matrix of rows--no rows of interest (SDDS_GetMatrixOfRows)");
2286 return (NULL);
2287 }
2288 if (!(data = (void **)SDDS_Malloc(sizeof(*data) * (*n_rows)))) {
2289 SDDS_SetError("Unable to get matrix of rows--memory allocation failure (SDDS_GetMatrixOfRows)");
2290 return (NULL);
2291 }
2292 for (j = k = 0; j < SDDS_dataset->n_rows; j++) {
2293 if (SDDS_dataset->row_flag[j]) {
2294 if (!(data[k] = SDDS_Malloc(size * SDDS_dataset->n_of_interest))) {
2295 SDDS_SetError("Unable to get matrix of rows--memory allocation failure (SDDS_GetMatrixOfRows)");
2296 return (NULL);
2297 }
2298 if (type != SDDS_STRING)
2299 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2300 memcpy((char *)data[k] + i * size, (char *)SDDS_dataset->data[SDDS_dataset->column_order[i]] + j * size, size);
2301 else
2302 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2303 if (!SDDS_CopyString((char **)(data[k]) + i, ((char **)SDDS_dataset->data[SDDS_dataset->column_order[i]])[j]))
2304 return (NULL);
2305 k++;
2306 }
2307 }
2308 return (data);
2309}
2310
2311/**
2312 * @brief Retrieves all rows marked as "of interest" as a matrix, casting each value to a specified numerical type.
2313 *
2314 * This function extracts all rows that are flagged as "of interest" within the current data table of a dataset and casts each value to a specified numerical type. It processes only those columns that are flagged as "of interest" and returns the data as a matrix, where each row is an array of casted values corresponding to the selected columns.
2315 *
2316 * @param SDDS_dataset
2317 * Pointer to the `SDDS_DATASET` structure representing the data set.
2318 * @param n_rows
2319 * Pointer to an `int64_t` variable where the number of rows retrieved will be stored.
2320 * @param sddsType
2321 * Integer constant representing the desired data type for casting (e.g., `SDDS_DOUBLE`, `SDDS_FLOAT`, etc.). Must be a valid numerical type as defined by SDDS.
2322 *
2323 * @return
2324 * - **Pointer to an array of pointers**, where each pointer references a row's data array cast to the specified type.
2325 * - **NULL** if an error occurs (e.g., invalid dataset, no columns selected, inconsistent data types among selected columns, non-numeric `sddsType`, memory allocation failure). In this case, an error message is recorded internally.
2326 *
2327 * @warning
2328 * - The caller is responsible for freeing the allocated memory to prevent memory leaks. This includes freeing each individual row array followed by the array of pointers itself.
2329 * - All selected columns must have numerical data types. If any selected column is non-numeric, the function will fail.
2330 * - Ensure that `sddsType` is a valid numerical type supported by SDDS.
2331 *
2332 * @note
2333 * - The number of rows retrieved is stored in the variable pointed to by `n_rows`.
2334 * - This function performs type casting using `SDDS_CastValue`. If casting fails for any value, the function will terminate and return `NULL`.
2335 * - If the dataset's memory mode for the columns is set to `DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS`, the internal data for the columns may be freed after access.
2336 *
2337 * @sa
2338 * - `SDDS_GetMatrixOfRows`
2339 * - `SDDS_CastValue`
2340 * - `SDDS_GetRowType`
2341 * - `SDDS_SetColumnFlags`
2342 * - `SDDS_CountRowsOfInterest`
2343 */
2344void *SDDS_GetCastMatrixOfRows(SDDS_DATASET *SDDS_dataset, int64_t *n_rows, int32_t sddsType) {
2345 void **data;
2346 int32_t size;
2347 int64_t i, j, k;
2348
2349 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetCastMatrixOfRows"))
2350 return (NULL);
2351 if (!SDDS_NUMERIC_TYPE(sddsType)) {
2352 SDDS_SetError("Unable to get matrix of rows--no columns selected (SDDS_GetCastMatrixOfRows)");
2353 return NULL;
2354 }
2355 if (SDDS_dataset->n_of_interest <= 0) {
2356 SDDS_SetError("Unable to get matrix of rows--no columns selected (SDDS_GetCastMatrixOfRows)");
2357 return (NULL);
2358 }
2359 if (!SDDS_CheckTabularData(SDDS_dataset, "SDDS_GetCastMatrixOfRows"))
2360 return (NULL);
2361 size = SDDS_type_size[sddsType - 1];
2362 if ((*n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
2363 SDDS_SetError("Unable to get matrix of rows--no rows of interest (SDDS_GetCastMatrixOfRows)");
2364 return (NULL);
2365 }
2366 if (!(data = (void **)SDDS_Malloc(sizeof(*data) * (*n_rows)))) {
2367 SDDS_SetError("Unable to get matrix of rows--memory allocation failure (SDDS_GetCastMatrixOfRows)");
2368 return (NULL);
2369 }
2370 for (i = 0; i < SDDS_dataset->n_of_interest; i++) {
2371 if (!SDDS_NUMERIC_TYPE(SDDS_dataset->layout.column_definition[SDDS_dataset->column_order[i]].type)) {
2372 SDDS_SetError("Unable to get matrix of rows--not all columns are numeric (SDDS_GetCastMatrixOfRows)");
2373 return NULL;
2374 }
2375 }
2376 for (j = k = 0; j < SDDS_dataset->n_rows; j++) {
2377 if (SDDS_dataset->row_flag[j]) {
2378 if (!(data[k] = SDDS_Malloc(size * SDDS_dataset->n_of_interest))) {
2379 SDDS_SetError("Unable to get matrix of rows--memory allocation failure (SDDS_GetCastMatrixOfRows)");
2380 return (NULL);
2381 }
2382 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2383 SDDS_CastValue(SDDS_dataset->data[SDDS_dataset->column_order[i]], j, SDDS_dataset->layout.column_definition[SDDS_dataset->column_order[i]].type, sddsType, (char *)data[k] + i * sizeof(double));
2384 k++;
2385 }
2386 }
2387 return (data);
2388}
2389
2390/**
2391 * @brief Retrieves multiple parameter values from the current data table of a data set.
2392 *
2393 * This variadic function allows the retrieval of multiple parameter values in a single call. Each parameter's name and corresponding memory location are provided as pairs of arguments.
2394 *
2395 * @param SDDS_dataset
2396 * Pointer to the `SDDS_DATASET` structure representing the data set.
2397 * @param ...
2398 * Variable arguments consisting of pairs of:
2399 * - `char *parameter_name`: NULL-terminated string specifying the name of the parameter.
2400 * - `void *memory`: Pointer to memory where the parameter's value will be stored. If `NULL`, the function will fail for that parameter.
2401 * - The argument list should be terminated when `parameter_name` is `NULL`.
2402 *
2403 * @return
2404 * - **1** on successful retrieval of all specified parameters.
2405 * - **0** if any parameter retrieval fails. An error message is recorded for the first failure encountered.
2406 *
2407 * @warning
2408 * - The function expects an even number of arguments (pairs of parameter names and memory pointers). An odd number may result in undefined behavior.
2409 * - Ensure that the `memory` pointers provided are of appropriate types and have sufficient space to hold the parameter values.
2410 *
2411 * @note
2412 * - To terminate the argument list, pass a `NULL` as the parameter name.
2413 * ```c
2414 * SDDS_GetParameters(&SDDS_dataset, "param1", &value1, "param2", &value2, NULL);
2415 * ```
2416 *
2417 * @sa
2418 * - `SDDS_GetParameter`
2419 * - `SDDS_GetParameterByIndex`
2420 */
2421int32_t SDDS_GetParameters(SDDS_DATASET *SDDS_dataset, ...) {
2422 va_list argptr;
2423 char *name;
2424 void *data;
2425 int32_t retval;
2426 char s[SDDS_MAXLINE];
2427
2428 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameters"))
2429 return 0;
2430 va_start(argptr, SDDS_dataset);
2431 retval = 1;
2432 do {
2433 if (!(name = va_arg(argptr, char *)))
2434 break;
2435 if (!(data = va_arg(argptr, void *)))
2436 retval = 0;
2437 if (!SDDS_GetParameter(SDDS_dataset, name, data)) {
2438 sprintf(s, "Unable to get value of parameter %s (SDDS_GetParameters)", name);
2439 SDDS_SetError(s);
2440 }
2441 } while (retval);
2442 va_end(argptr);
2443 return retval;
2444}
2445
2446/**
2447 * @brief Retrieves the value of a specified parameter from the current data table of a data set.
2448 *
2449 * This function accesses the value of a specific parameter (identified by its name) within the current data table of a dataset. The retrieved value is either copied into user-provided memory or returned as a direct pointer to the internal data.
2450 *
2451 * @param SDDS_dataset
2452 * Pointer to the `SDDS_DATASET` structure representing the data set.
2453 * @param parameter_name
2454 * NULL-terminated string specifying the name of the parameter from which the value is to be retrieved.
2455 * @param memory
2456 * Pointer to user-allocated memory where the retrieved parameter value will be stored. If `NULL`, the function allocates memory.
2457 *
2458 * @return
2459 * - **Pointer to the retrieved parameter value** stored in `memory` (if provided) or to newly allocated memory.
2460 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized parameter name, undefined data type, memory allocation failure, string copy failure). In this case, an error message is recorded internally.
2461 *
2462 * @warning
2463 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
2464 * - For parameters containing string data (`SDDS_STRING`), the function copies the string into `memory`. A typical usage would involve passing a pointer to a `char*` variable.
2465 * ```c
2466 * char *string;
2467 * SDDS_GetParameter(&SDDS_dataset, "parameter_name", &string);
2468 * // or
2469 * string = *(char**)SDDS_GetParameter(&SDDS_dataset, "parameter_name", NULL);
2470 * ```
2471 *
2472 * @note
2473 * - The size of the allocated memory corresponds to the parameter's data type, which can be obtained using `SDDS_GetParameterType`.
2474 * - If the dataset's memory mode for the parameter is set to `DONT_TRACK_PARAMETER_MEMORY_AFTER_ACCESS`, the internal data for the parameter may be freed after access.
2475 *
2476 * @sa
2477 * - `SDDS_GetParameters`
2478 * - `SDDS_GetParameterByIndex`
2479 * - `SDDS_SetParameter`
2480 * - `SDDS_GetParameterType`
2481 */
2482void *SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory) {
2483 int32_t index, type, size;
2484 char s[SDDS_MAXLINE];
2485 void *data;
2486 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameter"))
2487 return (NULL);
2488 if (!parameter_name) {
2489 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameter)");
2490 return (NULL);
2491 }
2492 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2493 sprintf(s, "Unable to get parameter value--parameter name %s is unrecognized (SDDS_GetParameter)", parameter_name);
2494 SDDS_SetError(s);
2495 return (NULL);
2496 }
2497 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2498 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameter)");
2499 return (NULL);
2500 }
2501 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2502 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameter)");
2503 return (NULL);
2504 }
2505 size = SDDS_type_size[type - 1];
2506 if (memory)
2507 data = memory;
2508 else if (!(data = SDDS_Malloc(size))) {
2509 SDDS_SetError("Unable to get parameter value--parameter data size is invalid (SDDS_GetParameter)");
2510 return (NULL);
2511 }
2512 if (type != SDDS_STRING)
2513 memcpy(data, SDDS_dataset->parameter[index], size);
2514 else if (!SDDS_CopyString((char **)data, *(char **)SDDS_dataset->parameter[index]))
2515 return (NULL);
2516 return (data);
2517}
2518
2519/**
2520 * @brief Retrieves the value of a specified parameter by its index from the current data table of a data set.
2521 *
2522 * This function accesses the value of a specific parameter (identified by its index) within the current data table of a dataset. The retrieved value is either copied into user-provided memory or returned as a direct pointer to the internal data.
2523 *
2524 * @param SDDS_dataset
2525 * Pointer to the `SDDS_DATASET` structure representing the data set.
2526 * @param index
2527 * Zero-based index of the parameter to retrieve. Must be within the range [0, n_parameters-1].
2528 * @param memory
2529 * Pointer to user-allocated memory where the retrieved parameter value will be stored. If `NULL`, the function allocates memory.
2530 *
2531 * @return
2532 * - **Pointer to the retrieved parameter value** stored in `memory` (if provided) or to newly allocated memory.
2533 * - **NULL** if an error occurs (e.g., invalid dataset, parameter index out of range, undefined data type, memory allocation failure, string copy failure). In this case, an error message is recorded internally.
2534 *
2535 * @warning
2536 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
2537 * - For parameters containing string data (`SDDS_STRING`), the function copies the string into `memory`. A typical usage would involve passing a pointer to a `char*` variable.
2538 * ```c
2539 * char *string;
2540 * SDDS_GetParameterByIndex(&SDDS_dataset, index, &string);
2541 * // or
2542 * string = *(char**)SDDS_GetParameterByIndex(&SDDS_dataset, index, NULL);
2543 * ```
2544 *
2545 * @note
2546 * - The size of the allocated memory corresponds to the parameter's data type, which can be obtained using `SDDS_GetParameterType`.
2547 * - If the dataset's memory mode for the parameter is set to `DONT_TRACK_PARAMETER_MEMORY_AFTER_ACCESS`, the internal data for the parameter may be freed after access.
2548 *
2549 * @sa
2550 * - `SDDS_GetParameters`
2551 * - `SDDS_GetParameter`
2552 * - `SDDS_SetParameter`
2553 * - `SDDS_GetParameterType`
2554 */
2555void *SDDS_GetParameterByIndex(SDDS_DATASET *SDDS_dataset, int32_t index, void *memory) {
2556 int32_t type, size;
2557 void *data;
2558 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameter"))
2559 return (NULL);
2560 if (index < 0 || index >= SDDS_dataset->layout.n_parameters) {
2561 SDDS_SetError("Unable to get parameter value--parameter index is invalid (SDDS_GetParameterByIndex)");
2562 return (NULL);
2563 }
2564 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2565 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterByIndex)");
2566 return (NULL);
2567 }
2568 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2569 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterByIndex)");
2570 return (NULL);
2571 }
2572 size = SDDS_type_size[type - 1];
2573 if (memory)
2574 data = memory;
2575 else if (!(data = SDDS_Malloc(size))) {
2576 SDDS_SetError("Unable to get parameter value--parameter data size is invalid (SDDS_GetParameterByIndex)");
2577 return (NULL);
2578 }
2579 if (type != SDDS_STRING)
2580 memcpy(data, SDDS_dataset->parameter[index], size);
2581 else if (!SDDS_CopyString((char **)data, *(char **)SDDS_dataset->parameter[index]))
2582 return (NULL);
2583 return (data);
2584}
2585
2586/**
2587 * @brief Retrieves the value of a specified parameter as a 32-bit integer from the current data table of a data set.
2588 *
2589 * This function accesses the value of a specific parameter (identified by its name) within the current data table of a dataset and converts it to a 32-bit integer (`int32_t`). The converted value is either stored in user-provided memory or allocated by the function.
2590 *
2591 * @param SDDS_dataset
2592 * Pointer to the `SDDS_DATASET` structure representing the data set.
2593 * @param parameter_name
2594 * NULL-terminated string specifying the name of the parameter from which the value is to be retrieved.
2595 * @param memory
2596 * Pointer to a 32-bit integer where the converted parameter value will be stored. If `NULL`, the function allocates memory.
2597 *
2598 * @return
2599 * - **Pointer to the `int32_t` value** stored in `memory` (if provided) or to newly allocated memory containing the converted value.
2600 * - **NULL** if an error occurs (e.g., invalid dataset, unrecognized parameter name, undefined data type, memory allocation failure, parameter type is `SDDS_STRING`). In this case, an error message is recorded internally.
2601 *
2602 * @warning
2603 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
2604 * - This function does not support parameters of type `SDDS_STRING`. Attempting to retrieve string parameters as long integers will result in an error.
2605 *
2606 * @note
2607 * - The conversion is performed using `SDDS_ConvertToLong`, which handles casting from various numerical types to `int32_t`.
2608 * - Ensure that the parameter's data type is compatible with 32-bit integer conversion to avoid data loss or undefined behavior.
2609 *
2610 * @sa
2611 * - `SDDS_GetParameter`
2612 * - `SDDS_GetParameterByIndex`
2613 * - `SDDS_ConvertToLong`
2614 * - `SDDS_GetParameterType`
2615 */
2616int32_t *SDDS_GetParameterAsLong(SDDS_DATASET *SDDS_dataset, char *parameter_name, int32_t *memory) {
2617 int32_t index, type;
2618 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsLong"))
2619 return (NULL);
2620 if (!parameter_name) {
2621 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsLong)");
2622 return (NULL);
2623 }
2624 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2625 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsLong)");
2626 return (NULL);
2627 }
2628 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2629 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsLong)");
2630 return (NULL);
2631 }
2632 if (type == SDDS_STRING) {
2633 SDDS_SetError("Unable to get parameter value--parameter data type is SDDS_STRING (SDDS_GetParameterAsLong)");
2634 return (NULL);
2635 }
2636 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2637 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterAsLong)");
2638 return (NULL);
2639 }
2640
2641 if (!memory && !(memory = (int32_t *)SDDS_Malloc(sizeof(int32_t)))) {
2642 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsLong)");
2643 return (NULL);
2644 }
2645
2646 *memory = SDDS_ConvertToLong(type, SDDS_dataset->parameter[index], 0);
2647 return (memory);
2648}
2649
2650/**
2651 * @brief Retrieves the value of a specified parameter as a 64-bit integer from the current data table of an SDDS dataset.
2652 *
2653 * This function looks up the parameter by name within the given SDDS dataset and returns its value as an `int64_t`.
2654 * If the `memory` pointer is provided, the value is stored at the given memory location. Otherwise, the function
2655 * allocates memory to store the value, which must be freed by the caller.
2656 *
2657 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2658 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2659 * @param memory Optional pointer to an `int64_t` variable where the parameter value will be stored. If `NULL`,
2660 * memory is allocated internally to hold the value.
2661 *
2662 * @return On success, returns a pointer to the `int64_t` containing the parameter value. On failure, returns `NULL`
2663 * and sets an appropriate error message.
2664 *
2665 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, type mismatch, or memory allocation failure).
2666 * @retval Non-NULL Pointer to the `int64_t` containing the parameter value.
2667 *
2668 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2669 *
2670 * @sa SDDS_GetParameterAsDouble, SDDS_GetParameterAsString
2671 */
2672int64_t *SDDS_GetParameterAsLong64(SDDS_DATASET *SDDS_dataset, char *parameter_name, int64_t *memory) {
2673 int32_t index, type;
2674 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsLong64"))
2675 return (NULL);
2676 if (!parameter_name) {
2677 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsLong64)");
2678 return (NULL);
2679 }
2680 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2681 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsLong64)");
2682 return (NULL);
2683 }
2684 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2685 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsLong64)");
2686 return (NULL);
2687 }
2688 if (type == SDDS_STRING) {
2689 SDDS_SetError("Unable to get parameter value--parameter data type is SDDS_STRING (SDDS_GetParameterAsLong64)");
2690 return (NULL);
2691 }
2692 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2693 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterAsLong64)");
2694 return (NULL);
2695 }
2696
2697 if (!memory && !(memory = (int64_t *)SDDS_Malloc(sizeof(int64_t)))) {
2698 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsLong64)");
2699 return (NULL);
2700 }
2701
2702 *memory = SDDS_ConvertToLong64(type, SDDS_dataset->parameter[index], 0);
2703 return (memory);
2704}
2705
2706/**
2707 * @brief Retrieves the value of a specified parameter as a `long double` from the current data table of an SDDS dataset.
2708 *
2709 * This function searches for the parameter by name within the provided SDDS dataset and retrieves its value as a `long double`.
2710 * If the `memory` pointer is supplied, the value is stored at the specified memory location. If `memory` is `NULL`,
2711 * the function allocates memory for storing the value, which should be freed by the caller.
2712 *
2713 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2714 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2715 * @param memory Optional pointer to a `long double` variable where the parameter value will be stored. If `NULL`,
2716 * memory is allocated internally to hold the value.
2717 *
2718 * @return On success, returns a pointer to the `long double` containing the parameter value. On failure, returns `NULL`
2719 * and sets an appropriate error message.
2720 *
2721 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, type mismatch, or memory allocation failure).
2722 * @retval Non-NULL Pointer to the `long double` containing the parameter value.
2723 *
2724 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2725 *
2726 * @sa SDDS_GetParameterAsDouble, SDDS_GetParameterAsLong64, SDDS_GetParameterAsString
2727 */
2728long double *SDDS_GetParameterAsLongDouble(SDDS_DATASET *SDDS_dataset, char *parameter_name, long double *memory) {
2729 int32_t index = -1, type = -1;
2730 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsLongDouble"))
2731 return (NULL);
2732 if (!parameter_name) {
2733 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsLongDouble)");
2734 return (NULL);
2735 }
2736 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2737 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsLongDouble)");
2738 return (NULL);
2739 }
2740 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2741 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsLongDouble)");
2742 return (NULL);
2743 }
2744 if (type == SDDS_STRING) {
2745 SDDS_SetError("Unable to get parameter value--parameter data type is SDDS_STRING (SDDS_GetParameterAsLongDouble)");
2746 return (NULL);
2747 }
2748 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2749 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterAsLongDouble)");
2750 return (NULL);
2751 }
2752
2753 if (!memory && !(memory = (long double *)SDDS_Malloc(sizeof(long double)))) {
2754 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsLongDouble)");
2755 return (NULL);
2756 }
2757 *memory = SDDS_ConvertToLongDouble(type, SDDS_dataset->parameter[index], 0);
2758 return (memory);
2759}
2760
2761/**
2762 * @brief Retrieves the value of a specified parameter as a `double` from the current data table of an SDDS dataset.
2763 *
2764 * This function searches for the parameter by name within the provided SDDS dataset and retrieves its value as a `double`.
2765 * If the `memory` pointer is supplied, the value is stored at the specified memory location. If `memory` is `NULL`,
2766 * the function allocates memory for storing the value, which should be freed by the caller.
2767 *
2768 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2769 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2770 * @param memory Optional pointer to a `double` variable where the parameter value will be stored. If `NULL`,
2771 * memory is allocated internally to hold the value.
2772 *
2773 * @return On success, returns a pointer to the `double` containing the parameter value. On failure, returns `NULL`
2774 * and sets an appropriate error message.
2775 *
2776 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, type mismatch, or memory allocation failure).
2777 * @retval Non-NULL Pointer to the `double` containing the parameter value.
2778 *
2779 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2780 *
2781 * @sa SDDS_GetParameterAsLong64, SDDS_GetParameterAsLongDouble, SDDS_GetParameterAsString
2782 */
2783double *SDDS_GetParameterAsDouble(SDDS_DATASET *SDDS_dataset, char *parameter_name, double *memory) {
2784 int32_t index = -1, type = -1;
2785 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsDouble"))
2786 return (NULL);
2787 if (!parameter_name) {
2788 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsDouble)");
2789 return (NULL);
2790 }
2791 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2792 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsDouble)");
2793 return (NULL);
2794 }
2795 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2796 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsDouble)");
2797 return (NULL);
2798 }
2799 if (type == SDDS_STRING) {
2800 SDDS_SetError("Unable to get parameter value--parameter data type is SDDS_STRING (SDDS_GetParameterAsDouble)");
2801 return (NULL);
2802 }
2803 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2804 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterAsDouble)");
2805 return (NULL);
2806 }
2807
2808 if (!memory && !(memory = (double *)SDDS_Malloc(sizeof(double)))) {
2809 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsDouble)");
2810 return (NULL);
2811 }
2812 *memory = SDDS_ConvertToDouble(type, SDDS_dataset->parameter[index], 0);
2813 return (memory);
2814}
2815
2816/**
2817 * @brief Retrieves the value of a specified parameter as a string from the current data table of an SDDS dataset.
2818 *
2819 * This function searches for the parameter by name within the provided SDDS dataset and retrieves its value as a string.
2820 * The function formats the parameter's value based on its data type. If the `memory` pointer is provided, the string
2821 * is stored at the specified memory location. Otherwise, the function allocates memory to hold the string, which
2822 * must be freed by the caller.
2823 *
2824 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2825 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2826 * @param memory Optional pointer to a `char*` variable where the string will be stored. If `NULL`, memory is allocated
2827 * internally to hold the string.
2828 *
2829 * @return On success, returns a pointer to the null-terminated string containing the parameter value. On failure, returns `NULL`
2830 * and sets an appropriate error message.
2831 *
2832 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, type mismatch, memory allocation failure, or unknown data type).
2833 * @retval Non-NULL Pointer to the null-terminated string containing the parameter value.
2834 *
2835 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2836 *
2837 * @sa SDDS_GetParameterAsDouble, SDDS_GetParameterAsLong64, SDDS_GetParameterAsLongDouble
2838 */
2839char *SDDS_GetParameterAsString(SDDS_DATASET *SDDS_dataset, char *parameter_name, char **memory) {
2840 int32_t index, type;
2841 char buffer[SDDS_MAXLINE], *parValue;
2842 void *value;
2843
2844 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsString"))
2845 return (NULL);
2846 if (!parameter_name) {
2847 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsString)");
2848 return (NULL);
2849 }
2850 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2851 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsString)");
2852 return (NULL);
2853 }
2854 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2855 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsString)");
2856 return (NULL);
2857 }
2858 value = SDDS_dataset->parameter[index];
2859 switch (type) {
2860 case SDDS_LONGDOUBLE:
2861 if (LDBL_DIG == 18) {
2862 sprintf(buffer, "%.18Le", *(long double *)value);
2863 } else {
2864 sprintf(buffer, "%.15Le", *(long double *)value);
2865 }
2866 break;
2867 case SDDS_DOUBLE:
2868 sprintf(buffer, "%.15le", *(double *)value);
2869 break;
2870 case SDDS_FLOAT:
2871 sprintf(buffer, "%.8e", *(float *)value);
2872 break;
2873 case SDDS_LONG64:
2874 sprintf(buffer, "%" PRId64, *(int64_t *)value);
2875 break;
2876 case SDDS_ULONG64:
2877 sprintf(buffer, "%" PRIu64, *(uint64_t *)value);
2878 break;
2879 case SDDS_LONG:
2880 sprintf(buffer, "%" PRId32, *(int32_t *)value);
2881 break;
2882 case SDDS_ULONG:
2883 sprintf(buffer, "%" PRIu32, *(uint32_t *)value);
2884 break;
2885 case SDDS_SHORT:
2886 sprintf(buffer, "%hd", *(short *)value);
2887 break;
2888 case SDDS_USHORT:
2889 sprintf(buffer, "%hu", *(unsigned short *)value);
2890 break;
2891 case SDDS_CHARACTER:
2892 sprintf(buffer, "%c", *(char *)value);
2893 break;
2894 case SDDS_STRING:
2895 sprintf(buffer, "%s", *(char **)value);
2896 break;
2897 default:
2898 SDDS_SetError("Unknown data type of parameter (SDDS_GetParameterAsString)");
2899 return (NULL);
2900 }
2901 if (!(parValue = malloc(sizeof(char) * (strlen(buffer) + 1)))) {
2902 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsString)");
2903 return (NULL);
2904 }
2905 strcpy(parValue, buffer);
2906 if (memory)
2907 *memory = parValue;
2908 return parValue;
2909}
2910
2911/**
2912 * @brief Retrieves the value of a specified parameter as a formatted string from the current data table of an SDDS dataset.
2913 *
2914 * This function searches for the parameter by name within the provided SDDS dataset, formats its value based on the supplied format string,
2915 * and returns it as a null-terminated string. If `suppliedformat` is `NULL`, the function uses the format string defined in the parameter's
2916 * definition. If the `memory` pointer is provided, the formatted string is stored at the specified memory location. Otherwise, memory is
2917 * allocated internally to hold the string, which must be freed by the caller.
2918 *
2919 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2920 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2921 * @param memory Optional pointer to a `char*` variable where the formatted string will be stored. If `NULL`, memory is allocated
2922 * internally to hold the string.
2923 * @param suppliedformat A null-terminated format string (similar to `printf` format specifiers) to format the parameter value. If `NULL`,
2924 * the function uses the format string defined in the parameter's definition within the dataset.
2925 *
2926 * @return On success, returns a pointer to the null-terminated formatted string containing the parameter value. On failure, returns `NULL`
2927 * and sets an appropriate error message.
2928 *
2929 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, invalid format string, type mismatch, memory allocation failure, or unknown data type).
2930 * @retval Non-NULL Pointer to the null-terminated string containing the formatted parameter value.
2931 *
2932 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2933 *
2934 * @sa SDDS_GetParameterAsDouble, SDDS_GetParameterAsString, SDDS_GetParameterAsLong64, SDDS_GetParameterAsLongDouble
2935 */
2936char *SDDS_GetParameterAsFormattedString(SDDS_DATASET *SDDS_dataset, char *parameter_name, char **memory, char *suppliedformat) {
2937 int32_t index, type;
2938 char buffer[SDDS_MAXLINE], *parValue;
2939 void *value;
2940 char *format = NULL;
2941
2942 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsFormattedString"))
2943 return (NULL);
2944 if (!parameter_name) {
2945 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsFormattedString)");
2946 return (NULL);
2947 }
2948 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2949 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsFormattedString)");
2950 return (NULL);
2951 }
2952 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2953 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsFormattedString)");
2954 return (NULL);
2955 }
2956 if (suppliedformat != NULL) {
2957 format = suppliedformat;
2958 if (!SDDS_VerifyPrintfFormat(format, type)) {
2959 SDDS_SetError("Unable to get parameter value--given format for parameter is invalid (SDDS_GetParameterAsFormattedString)");
2960 return (NULL);
2961 }
2962 } else {
2963 if (SDDS_GetParameterInformation(SDDS_dataset, "format_string", &format, SDDS_GET_BY_INDEX, index) != SDDS_STRING) {
2964 SDDS_SetError("Unable to get parameter value--parameter definition is invalid (SDDS_GetParameterAsFormattedString)");
2965 return (NULL);
2966 }
2967 }
2968 value = SDDS_dataset->parameter[index];
2969
2970 if (!SDDS_StringIsBlank(format)) {
2971 switch (type) {
2972 case SDDS_LONGDOUBLE:
2973 sprintf(buffer, format, *(long double *)value);
2974 break;
2975 case SDDS_DOUBLE:
2976 sprintf(buffer, format, *(double *)value);
2977 break;
2978 case SDDS_FLOAT:
2979 sprintf(buffer, format, *(float *)value);
2980 break;
2981 case SDDS_LONG64:
2982 sprintf(buffer, format, *(int64_t *)value);
2983 break;
2984 case SDDS_ULONG64:
2985 sprintf(buffer, format, *(uint64_t *)value);
2986 break;
2987 case SDDS_LONG:
2988 sprintf(buffer, format, *(int32_t *)value);
2989 break;
2990 case SDDS_ULONG:
2991 sprintf(buffer, format, *(uint32_t *)value);
2992 break;
2993 case SDDS_SHORT:
2994 sprintf(buffer, format, *(short *)value);
2995 break;
2996 case SDDS_USHORT:
2997 sprintf(buffer, format, *(unsigned short *)value);
2998 break;
2999 case SDDS_CHARACTER:
3000 sprintf(buffer, format, *(char *)value);
3001 break;
3002 case SDDS_STRING:
3003 sprintf(buffer, format, *(char **)value);
3004 break;
3005 default:
3006 SDDS_SetError("Unknown data type of parameter (SDDS_GetParameterAsFormattedString)");
3007 return (NULL);
3008 }
3009 } else {
3010 switch (type) {
3011 case SDDS_LONGDOUBLE:
3012 if (LDBL_DIG == 18) {
3013 sprintf(buffer, "%22.18Le", *(long double *)value);
3014 } else {
3015 sprintf(buffer, "%22.15Le", *(long double *)value);
3016 }
3017 break;
3018 case SDDS_DOUBLE:
3019 sprintf(buffer, "%22.15le", *(double *)value);
3020 break;
3021 case SDDS_FLOAT:
3022 sprintf(buffer, "%15.8e", *(float *)value);
3023 break;
3024 case SDDS_LONG64:
3025 sprintf(buffer, "%" PRId64, *(int64_t *)value);
3026 break;
3027 case SDDS_ULONG64:
3028 sprintf(buffer, "%" PRIu64, *(uint64_t *)value);
3029 break;
3030 case SDDS_LONG:
3031 sprintf(buffer, "%" PRId32, *(int32_t *)value);
3032 break;
3033 case SDDS_ULONG:
3034 sprintf(buffer, "%" PRIu32, *(uint32_t *)value);
3035 break;
3036 case SDDS_SHORT:
3037 sprintf(buffer, "%hd", *(short *)value);
3038 break;
3039 case SDDS_USHORT:
3040 sprintf(buffer, "%hu", *(unsigned short *)value);
3041 break;
3042 case SDDS_CHARACTER:
3043 sprintf(buffer, "%c", *(char *)value);
3044 break;
3045 case SDDS_STRING:
3046 sprintf(buffer, "%s", *(char **)value);
3047 break;
3048 default:
3049 SDDS_SetError("Unknown data type of parameter (SDDS_GetParameterAsFormattedString)");
3050 return (NULL);
3051 }
3052 }
3053 if (!(parValue = malloc(sizeof(char) * (strlen(buffer) + 1)))) {
3054 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsFormattedString)");
3055 return (NULL);
3056 }
3057 strcpy(parValue, buffer);
3058 if (memory)
3059 *memory = parValue;
3060 return parValue;
3061}
3062
3063/**
3064 * @brief Retrieves the fixed value of a specified parameter from an SDDS dataset.
3065 *
3066 * This function accesses the fixed value defined for a given parameter in the dataset's layout and converts it to the appropriate data type.
3067 * If the `memory` pointer is provided, the converted value is stored at the specified memory location. Otherwise, memory is allocated
3068 * internally to hold the value, which must be freed by the caller.
3069 *
3070 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3071 * @param parameter_name A null-terminated string specifying the name of the parameter whose fixed value is to be retrieved.
3072 * @param memory Optional pointer to a memory location where the fixed value will be stored. The size of the memory should correspond
3073 * to the size of the parameter's data type. If `NULL`, memory is allocated internally to hold the value.
3074 *
3075 * @return On success, returns a pointer to the memory containing the fixed value. On failure, returns `NULL` and sets an appropriate
3076 * error message.
3077 *
3078 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, invalid data type, memory allocation failure, or scan failure).
3079 * @retval Non-NULL Pointer to the memory containing the fixed parameter value.
3080 *
3081 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
3082 *
3083 * @sa SDDS_SetParameterFixedValue, SDDS_GetParameterAsDouble, SDDS_GetParameterAsString
3084 */
3085void *SDDS_GetFixedValueParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory) {
3086 int32_t index, type, size;
3087 void *data;
3088 char s[SDDS_MAXLINE];
3089
3090 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetFixValueParameter"))
3091 return (NULL);
3092 if (!parameter_name) {
3093 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetFixedValueParameter)");
3094 return (NULL);
3095 }
3096 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
3097 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetFixedValueParameter)");
3098 return (NULL);
3099 }
3100 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
3101 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetFixedValueParameter)");
3102 return (NULL);
3103 }
3104 size = SDDS_type_size[type - 1];
3105 if (memory)
3106 data = memory;
3107 else if (!(data = SDDS_Malloc(size))) {
3108 SDDS_SetError("Unable to get parameter value--parameter data size is invalid (SDDS_GetFixedValueParameter)");
3109 return (NULL);
3110 }
3111 strcpy(s, SDDS_dataset->layout.parameter_definition[index].fixed_value);
3112 if (!SDDS_ScanData(s, type, 0, data, 0, 1)) {
3113 SDDS_SetError("Unable to retrieve fixed-value paramter--scan failed (SDDS_GetFixedValueParameter)");
3114 return (NULL);
3115 }
3116 return (data);
3117}
3118
3119/**
3120 * @brief Extracts a matrix from a specified column in the current data table of an SDDS dataset.
3121 *
3122 * This function retrieves the data from the specified column and organizes it into a matrix with the given dimensions. The
3123 * data is arranged in either row-major or column-major order based on the `mode` parameter. The function allocates memory for
3124 * the matrix, which should be freed by the caller.
3125 *
3126 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3127 * @param column_name A null-terminated string specifying the name of the column from which to extract the matrix.
3128 * @param dimension1 The number of rows in the resulting matrix.
3129 * @param dimension2 The number of columns in the resulting matrix.
3130 * @param mode Specifies the data layout in the matrix. Use `SDDS_ROW_MAJOR_DATA` for row-major order or `SDDS_COLUMN_MAJOR_DATA`
3131 * for column-major order.
3132 *
3133 * @return On success, returns a pointer to the allocated matrix. The matrix is an array of pointers, where each pointer refers to a row
3134 * (for row-major) or a column (for column-major) in the matrix. On failure, returns `NULL` and sets an appropriate error message.
3135 *
3136 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, column not found, dimension mismatch, memory allocation failure).
3137 * @retval Non-NULL Pointer to the allocated matrix.
3138 *
3139 * @note The caller is responsible for freeing the allocated matrix and its contents.
3140 *
3141 * @sa SDDS_GetDoubleMatrixFromColumn, SDDS_GetMatrixFromRow, SDDS_AllocateMatrix
3142 */
3143void *SDDS_GetMatrixFromColumn(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t dimension1, int64_t dimension2, int32_t mode) {
3144 int32_t size, type, index;
3145 int64_t n_rows, i, j;
3146 void **data, *column;
3147 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetMatrixFromColumn"))
3148 return (NULL);
3149 if (!column_name) {
3150 SDDS_SetError("Unable to get matrix--column name is NULL (SDDS_GetMatrixFromColumn)");
3151 return (NULL);
3152 }
3153 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
3154 SDDS_SetError("Unable to get matrix--no rows selected (SDDS_GetMatrixFromColumn)");
3155 return (NULL);
3156 }
3157 if (n_rows != dimension1 * dimension2) {
3158 char s[1024];
3159 sprintf(s, "Unable to get matrix--number of rows (%" PRId64 ") doesn't correspond to given dimensions (%" PRId64 " x %" PRId64 ") (SDDS_GetMatrixFromColumn)", n_rows, dimension1, dimension2);
3160 SDDS_SetError(s);
3161 return (NULL);
3162 }
3163 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0 || (type = SDDS_GetColumnType(SDDS_dataset, index)) < 0 || (size = SDDS_GetTypeSize(type)) <= 0) {
3164 SDDS_SetError("Unable to get matrix--column name is unrecognized (SDDS_GetMatrixFromColumn)");
3165 return (NULL);
3166 }
3167 if (!(column = SDDS_GetColumn(SDDS_dataset, column_name))) {
3168 SDDS_SetError("Unable to get matrix (SDDS_GetMatrixFromColumn)");
3169 return (NULL);
3170 }
3171 if (!(data = SDDS_AllocateMatrix(size, dimension1, dimension2))) {
3172 SDDS_SetError("Unable to allocate matrix (SDDS_GetMatrixFromColumn)");
3173 return (NULL);
3174 }
3175 if (mode & SDDS_ROW_MAJOR_DATA || !(mode & SDDS_COLUMN_MAJOR_DATA)) {
3176 for (i = 0; i < dimension1; i++)
3177 memcpy(data[i], (char *)column + i * dimension2 * size, dimension2 * size);
3178 } else {
3179 for (i = 0; i < dimension1; i++) {
3180 for (j = 0; j < dimension2; j++) {
3181 memcpy((char *)data[i] + size * j, (char *)column + (j * dimension1 + i) * size, size);
3182 }
3183 }
3184 }
3185
3186 free(column);
3187 return (data);
3188}
3189
3190/**
3191 * @brief Extracts a matrix of doubles from a specified column in the current data table of an SDDS dataset.
3192 *
3193 * This function retrieves the data from the specified column as `double` values and organizes it into a matrix with the given dimensions.
3194 * The data is arranged in either row-major or column-major order based on the `mode` parameter. The function allocates memory for
3195 * the matrix, which should be freed by the caller.
3196 *
3197 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3198 * @param column_name A null-terminated string specifying the name of the column from which to extract the matrix.
3199 * @param dimension1 The number of rows in the resulting matrix.
3200 * @param dimension2 The number of columns in the resulting matrix.
3201 * @param mode Specifies the data layout in the matrix. Use `SDDS_ROW_MAJOR_DATA` for row-major order or `SDDS_COLUMN_MAJOR_DATA`
3202 * for column-major order.
3203 *
3204 * @return On success, returns a pointer to the allocated matrix containing `double` values. The matrix is an array of pointers,
3205 * where each pointer refers to a row (for row-major) or a column (for column-major) in the matrix. On failure, returns `NULL`
3206 * and sets an appropriate error message.
3207 *
3208 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, column not found, dimension mismatch, memory allocation failure).
3209 * @retval Non-NULL Pointer to the allocated matrix containing `double` values.
3210 *
3211 * @note The caller is responsible for freeing the allocated matrix and its contents.
3212 *
3213 * @sa SDDS_GetMatrixFromColumn, SDDS_GetDoubleMatrixFromRow, SDDS_AllocateMatrix
3214 */
3215void *SDDS_GetDoubleMatrixFromColumn(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t dimension1, int64_t dimension2, int32_t mode) {
3216 int32_t size, index;
3217 int64_t n_rows, i, j;
3218 void **data, *column;
3219 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetDoubleMatrixFromColumn"))
3220 return (NULL);
3221 if (!column_name) {
3222 SDDS_SetError("Unable to get matrix--column name is NULL (SDDS_GetDoubleMatrixFromColumn)");
3223 return (NULL);
3224 }
3225 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
3226 SDDS_SetError("Unable to get matrix--no rows selected (SDDS_GetDoubleMatrixFromColumn)");
3227 return (NULL);
3228 }
3229 if (n_rows != dimension1 * dimension2) {
3230 char s[1024];
3231 sprintf(s, "Unable to get matrix--number of rows (%" PRId64 ") doesn't correspond to given dimensions (%" PRId64 " x %" PRId64 ") (SDDS_GetDoubleMatrixFromColumn)", n_rows, dimension1, dimension2);
3232 SDDS_SetError(s);
3233 return (NULL);
3234 }
3235 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
3236 SDDS_SetError("Unable to get matrix--column name is unrecognized (SDDS_GetDoubleMatrixFromColumn)");
3237 return (NULL);
3238 }
3239 if (!(column = SDDS_GetColumnInDoubles(SDDS_dataset, column_name))) {
3240 SDDS_SetError("Unable to get matrix (SDDS_GetDoubleMatrixFromColumn)");
3241 return (NULL);
3242 }
3243 size = sizeof(double);
3244 if (!(data = SDDS_AllocateMatrix(size, dimension1, dimension2))) {
3245 SDDS_SetError("Unable to allocate matrix (SDDS_GetDoubleMatrixFromColumn)");
3246 return (NULL);
3247 }
3248 if (mode & SDDS_ROW_MAJOR_DATA || !(mode & SDDS_COLUMN_MAJOR_DATA)) {
3249 for (i = 0; i < dimension1; i++)
3250 memcpy(data[i], (char *)column + i * dimension2 * size, dimension2 * size);
3251 } else {
3252 for (i = 0; i < dimension1; i++) {
3253 for (j = 0; j < dimension2; j++) {
3254 memcpy((char *)data[i] + size * j, (char *)column + (j * dimension1 + i) * size, size);
3255 }
3256 }
3257 }
3258
3259 free(column);
3260 return (data);
3261}
3262
3263/**
3264 * @brief Sets the rows of interest in an SDDS dataset based on various selection criteria.
3265 *
3266 * This function marks rows in the provided SDDS dataset as "of interest" based on the specified selection criteria.
3267 * It supports multiple selection modes, allowing users to specify rows by an array of names, a single string containing
3268 * multiple names, a variadic list of names, or by matching a specific string with logical operations.
3269 *
3270 * **Calling Modes:**
3271 * - **SDDS_NAME_ARRAY**: Specify an array of names.
3272 * ```c
3273 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAME_ARRAY, int32_t n_entries, char **name);
3274 * ```
3275 * - **SDDS_NAMES_STRING**: Provide a single string containing multiple names separated by delimiters.
3276 * ```c
3277 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAMES_STRING, char *names);
3278 * ```
3279 * - **SDDS_NAME_STRINGS**: Pass multiple name strings, terminated by `NULL`.
3280 * ```c
3281 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAME_STRINGS, char *name1, char *name2, ..., NULL);
3282 * ```
3283 * - **SDDS_MATCH_STRING**: Match rows based on a single string and logical operations.
3284 * ```c
3285 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_MATCH_STRING, char *name, int32_t logic_mode);
3286 * ```
3287 *
3288 * Additionally, each of these modes has a case-insensitive variant prefixed with `SDDS_CI_` (e.g., `SDDS_CI_NAME_ARRAY`).
3289 *
3290 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3291 * @param selection_column A null-terminated string specifying the name of the column used for row selection.
3292 * This column must be of string type.
3293 * @param mode An integer representing the selection mode. Supported modes include:
3294 * - `SDDS_NAME_ARRAY`
3295 * - `SDDS_NAMES_STRING`
3296 * - `SDDS_NAME_STRINGS`
3297 * - `SDDS_MATCH_STRING`
3298 * - `SDDS_CI_NAME_ARRAY`
3299 * - `SDDS_CI_NAMES_STRING`
3300 * - `SDDS_CI_NAME_STRINGS`
3301 * - `SDDS_CI_MATCH_STRING`
3302 * @param ... Variable arguments corresponding to the selected mode:
3303 * - **SDDS_NAME_ARRAY** and **SDDS_CI_NAME_ARRAY**:
3304 * - `int32_t n_entries`: Number of names.
3305 * - `char **name`: Array of name strings.
3306 * - **SDDS_NAMES_STRING** and **SDDS_CI_NAMES_STRING**:
3307 * - `char *names`: Single string containing multiple names separated by delimiters.
3308 * - **SDDS_NAME_STRINGS** and **SDDS_CI_NAME_STRINGS**:
3309 * - `char *name1, char *name2, ..., NULL`: Multiple name strings terminated by `NULL`.
3310 * - **SDDS_MATCH_STRING** and **SDDS_CI_MATCH_STRING**:
3311 * - `char *name`: String to match.
3312 * - `int32_t logic_mode`: Logical operation mode.
3313 *
3314 * @return On success, returns the number of rows marked as "of interest". On failure, returns `-1` and sets an appropriate error message.
3315 *
3316 * @retval -1 Indicates that an error occurred (e.g., invalid dataset, unrecognized selection column, memory allocation failure, unknown mode).
3317 * @retval Non-negative Integer representing the count of rows marked as "of interest".
3318 *
3319 * @note
3320 * - The caller must ensure that the `selection_column` exists and is of string type in the dataset.
3321 * - For modes that allocate memory internally (e.g., `SDDS_NAMES_STRING`), the function handles memory management internally.
3322 *
3323 * @sa SDDS_MatchRowsOfInterest, SDDS_FilterRowsOfInterest, SDDS_DeleteUnsetRows
3324 */
3325int64_t SDDS_SetRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *selection_column, int32_t mode, ...)
3326/* This routine has 4 calling modes:
3327 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAME_ARRAY, int32_t n_entries, char **name)
3328 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAMES_STRING, char *names)
3329 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAME_STRINGS, char *name1, char *name2, ..., NULL )
3330 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_MATCH_STRING, char *name, int32_t logic_mode)
3331 */
3332{
3333 va_list argptr;
3334 int32_t retval, type, index, n_names;
3335 int64_t i, j;
3336 char **name, *string, *match_string, *ptr;
3337 int32_t local_memory; /* (0,1,2) --> (none, pointer array, pointer array + strings) locally allocated */
3338 char buffer[SDDS_MAXLINE];
3339 int32_t logic, caseSensitive;
3340 int64_t count;
3341
3342 name = NULL;
3343 n_names = local_memory = logic = 0;
3344
3345 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetRowsOfInterest"))
3346 return (-1);
3347 va_start(argptr, mode);
3348 retval = 1;
3349 caseSensitive = 1;
3350 match_string = NULL;
3351 switch (mode) {
3352 case SDDS_CI_NAME_ARRAY:
3353 caseSensitive = 0;
3354 case SDDS_NAME_ARRAY:
3355 local_memory = 0;
3356 n_names = va_arg(argptr, int32_t);
3357 name = va_arg(argptr, char **);
3358 break;
3359 case SDDS_CI_NAMES_STRING:
3360 caseSensitive = 0;
3361 case SDDS_NAMES_STRING:
3362 local_memory = 2;
3363 n_names = 0;
3364 name = NULL;
3365 ptr = va_arg(argptr, char *);
3366 SDDS_CopyString(&string, ptr);
3367 while (SDDS_GetToken(string, buffer, SDDS_MAXLINE) > 0) {
3368 if (!(name = SDDS_Realloc(name, sizeof(*name) * (n_names + 1))) || !SDDS_CopyString(name + n_names, buffer)) {
3369 SDDS_SetError("Unable to process row selection--memory allocation failure (SDDS_SetRowsOfInterest)");
3370 retval = -1;
3371 break;
3372 }
3373 n_names++;
3374 }
3375 free(string);
3376 break;
3377 case SDDS_CI_NAME_STRINGS:
3378 caseSensitive = 0;
3379 case SDDS_NAME_STRINGS:
3380 local_memory = 1;
3381 n_names = 0;
3382 name = NULL;
3383 while ((string = va_arg(argptr, char *))) {
3384 if (!(name = SDDS_Realloc(name, sizeof(*name) * (n_names + 1)))) {
3385 SDDS_SetError("Unable to process row selection--memory allocation failure (SDDS_SetRowsOfInterest)");
3386 retval = -1;
3387 break;
3388 }
3389 name[n_names++] = string;
3390 }
3391 break;
3392 case SDDS_CI_MATCH_STRING:
3393 caseSensitive = 0;
3394 case SDDS_MATCH_STRING:
3395 local_memory = 0;
3396 n_names = 1;
3397 if ((string = va_arg(argptr, char *)))
3398 match_string = expand_ranges(string);
3399 logic = va_arg(argptr, int32_t);
3400 if (logic & SDDS_NOCASE_COMPARE)
3401 caseSensitive = 0;
3402 break;
3403 default:
3404 SDDS_SetError("Unable to process row selection--unknown mode (SDDS_SetRowsOfInterest)");
3405 retval = -1;
3406 break;
3407 }
3408
3409 va_end(argptr);
3410 if (retval != 1)
3411 return (-1);
3412
3413 if (mode != SDDS_MATCH_STRING && mode != SDDS_CI_MATCH_STRING) {
3414 int (*stringCompare)(const char *s1, const char *s2);
3415 if (caseSensitive)
3416 stringCompare = strcmp;
3417 else
3418 stringCompare = strcmp_ci;
3419 if ((index = SDDS_GetColumnIndex(SDDS_dataset, selection_column)) < 0) {
3420 SDDS_SetError("Unable to process row selection--unrecognized selection column name (SDDS_SetRowsOfInterest)");
3421 return (-1);
3422 }
3423 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) != SDDS_STRING) {
3424 SDDS_SetError("Unable to select rows--selection column is not string type (SDDS_SetRowsOfInterest)");
3425 return (-1);
3426 }
3427 if (n_names == 0) {
3428 SDDS_SetError("Unable to process row selection--no names in call (SDDS_SetRowsOfInterest)");
3429 return (-1);
3430 }
3431 for (j = 0; j < n_names; j++) {
3432 for (i = 0; i < SDDS_dataset->n_rows; i++) {
3433 if ((*stringCompare)(*((char **)SDDS_dataset->data[index] + i), name[j]) == 0)
3434 SDDS_dataset->row_flag[i] = 1;
3435 }
3436 }
3437 } else {
3438 if (selection_column) {
3439 int (*wildMatch)(char *string, char *template);
3440 if (caseSensitive)
3441 wildMatch = wild_match;
3442 else
3443 wildMatch = wild_match_ci;
3444 if (!match_string) {
3445 SDDS_SetError("Unable to select rows--no matching string given (SDDS_SetRowsOfInterest)");
3446 return (-1);
3447 }
3448 if ((index = SDDS_GetColumnIndex(SDDS_dataset, selection_column)) < 0) {
3449 free(match_string);
3450 SDDS_SetError("Unable to process row selection--unrecognized selection column name (SDDS_SetRowsOfInterest)");
3451 return (-1);
3452 }
3453 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) != SDDS_STRING) {
3454 free(match_string);
3455 SDDS_SetError("Unable to select rows--selection column is not string type (SDDS_SetRowsOfInterest)");
3456 return (-1);
3457 }
3458 for (i = 0; i < SDDS_dataset->n_rows; i++)
3459 SDDS_dataset->row_flag[i] = SDDS_Logic(SDDS_dataset->row_flag[i], (*wildMatch)(*((char **)SDDS_dataset->data[index] + i), match_string), logic);
3460 } else {
3461 for (i = 0; i < SDDS_dataset->n_rows; i++)
3462 SDDS_dataset->row_flag[i] = SDDS_Logic(SDDS_dataset->row_flag[i], 0, logic & ~(SDDS_AND | SDDS_OR));
3463 }
3464 }
3465
3466 if (local_memory == 2) {
3467 for (i = 0; i < n_names; i++)
3468 free(name[i]);
3469 }
3470 if (match_string)
3471 free(match_string);
3472 if (local_memory >= 1)
3473 free(name);
3474
3475 for (i = count = 0; i < SDDS_dataset->n_rows; i++)
3476 if (SDDS_dataset->row_flag[i])
3477 count++;
3478 return (count);
3479}
3480
3481/**
3482 * @brief Matches and marks rows of interest in an SDDS dataset based on label matching.
3483 *
3484 * This function marks rows in the provided SDDS dataset as "of interest" by matching labels in a specified column against a target label.
3485 * It supports both direct and indirect matching, as well as case-sensitive and case-insensitive comparisons, based on the provided logic flags.
3486 *
3487 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3488 * @param selection_column A null-terminated string specifying the name of the column used for label matching.
3489 * This column must be of string or character type.
3490 * @param label_to_match A null-terminated string specifying the label to match against the entries in the selection column.
3491 * If `logic` includes `SDDS_INDIRECT_MATCH`, this parameter is treated as the name of another column used for indirect matching.
3492 * @param logic An integer representing logical operation flags. Supported flags include:
3493 * - `SDDS_NOCASE_COMPARE`: Perform case-insensitive comparison.
3494 * - `SDDS_INDIRECT_MATCH`: Use indirect matching via another column.
3495 *
3496 * @return On success, returns the number of rows marked as "of interest". On failure, returns `-1` and sets an appropriate error message.
3497 *
3498 * @retval -1 Indicates that an error occurred (e.g., invalid dataset, unrecognized selection column, type mismatch, unrecognized indirect column).
3499 * @retval Non-negative Integer representing the count of rows marked as "of interest".
3500 *
3501 * @note
3502 * - The selection column must exist and be of string or character type.
3503 * - If using indirect matching (`SDDS_INDIRECT_MATCH`), the indirect column must exist and be of the same type as the selection column.
3504 *
3505 * @sa SDDS_SetRowsOfInterest, SDDS_FilterRowsOfInterest, SDDS_DeleteUnsetRows
3506 */
3507int64_t SDDS_MatchRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *selection_column, char *label_to_match, int32_t logic) {
3508 int32_t match, type, index, indirect_index;
3509 int64_t i, count;
3510 char *match_string;
3511#ifndef tolower
3512# if !defined(_MINGW)
3513 int tolower(int c);
3514# endif
3515#endif
3516
3517 index = type = indirect_index = 0;
3518
3519 match_string = NULL;
3520 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_MatchRowsOfInterest"))
3521 return (-1);
3522 if (selection_column) {
3523 if ((index = SDDS_GetColumnIndex(SDDS_dataset, selection_column)) < 0) {
3524 SDDS_SetError("Unable to select rows--column name is unrecognized (SDDS_MatchRowsOfInterest)");
3525 return (-1);
3526 }
3527 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) != SDDS_STRING && type != SDDS_CHARACTER) {
3528 SDDS_SetError("Unable to select rows--selection column is not a string (SDDS_MatchRowsOfInterest)");
3529 return (-1);
3530 }
3531 if (!label_to_match) {
3532 SDDS_SetError("Unable to select rows--selection label is NULL (SDDS_MatchRowsOfInterest)");
3533 return (-1);
3534 }
3535 if (!(logic & SDDS_INDIRECT_MATCH))
3536 match_string = expand_ranges(label_to_match);
3537 else {
3538 if ((indirect_index = SDDS_GetColumnIndex(SDDS_dataset, label_to_match)) < 0) {
3539 SDDS_SetError("Unable to select rows--indirect column name is unrecognized (SDDS_MatchRowsOfInterest)");
3540 return (-1);
3541 }
3542 if (SDDS_GetColumnType(SDDS_dataset, indirect_index) != type) {
3543 SDDS_SetError("Unable to select rows--indirect column is not same type as main column (SDDS_MatchRowsOfInterest)");
3544 return (-1);
3545 }
3546 }
3547 }
3548 if (type == SDDS_STRING) {
3549 int (*stringCompare)(const char *s, const char *t);
3550 int (*wildMatch)(char *s, char *t);
3551 if (logic & SDDS_NOCASE_COMPARE) {
3552 stringCompare = strcmp_ci;
3553 wildMatch = wild_match_ci;
3554 } else {
3555 stringCompare = strcmp;
3556 wildMatch = wild_match;
3557 }
3558 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3559 if (selection_column)
3560 match = SDDS_Logic(SDDS_dataset->row_flag[i], (logic & SDDS_INDIRECT_MATCH ? (*stringCompare)(*((char **)SDDS_dataset->data[index] + i), *((char **)SDDS_dataset->data[indirect_index] + i)) == 0 : (*wildMatch)(*((char **)SDDS_dataset->data[index] + i), match_string)), logic);
3561 else
3562 match = SDDS_Logic(SDDS_dataset->row_flag[i], 0, logic & ~(SDDS_AND | SDDS_OR));
3563 if ((SDDS_dataset->row_flag[i] = match))
3564 count++;
3565 }
3566 } else {
3567 char c1, c2;
3568 c2 = 0;
3569 if (!(logic & SDDS_INDIRECT_MATCH))
3570 c2 = *match_string;
3571 if (logic & SDDS_NOCASE_COMPARE) {
3572 c2 = tolower(c2);
3573 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3574 c1 = tolower(*((char *)SDDS_dataset->data[index] + i));
3575 if (selection_column)
3576 match = SDDS_Logic(SDDS_dataset->row_flag[i], logic & SDDS_INDIRECT_MATCH ? c1 == tolower(*((char *)SDDS_dataset->data[indirect_index] + i)) : c1 == c2, logic);
3577 else
3578 match = SDDS_Logic(SDDS_dataset->row_flag[i], 0, logic & ~(SDDS_AND | SDDS_OR));
3579 if ((SDDS_dataset->row_flag[i] = match))
3580 count++;
3581 }
3582 } else {
3583 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3584 c1 = *((char *)SDDS_dataset->data[index] + i);
3585 if (selection_column)
3586 match = SDDS_Logic(SDDS_dataset->row_flag[i], logic & SDDS_INDIRECT_MATCH ? c1 == *((char *)SDDS_dataset->data[indirect_index] + i) : c1 == c2, logic);
3587 else
3588 match = SDDS_Logic(SDDS_dataset->row_flag[i], 0, logic & ~(SDDS_AND | SDDS_OR));
3589 if ((SDDS_dataset->row_flag[i] = match))
3590 count++;
3591 }
3592 }
3593 }
3594 if (match_string)
3595 free(match_string);
3596 return (count);
3597}
3598
3599/**
3600 * @brief Filters rows of interest in an SDDS dataset based on numeric ranges in a specified column.
3601 *
3602 * This function marks rows in the provided SDDS dataset as "of interest" if the values in the specified filter column fall
3603 * within the defined numeric range (`lower_limit` to `upper_limit`). Logical operations specified by the `logic` parameter
3604 * determine how the filtering interacts with existing row flags.
3605 *
3606 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3607 * @param filter_column A null-terminated string specifying the name of the column used for numeric filtering.
3608 * This column must be of a numeric type.
3609 * @param lower_limit The lower bound of the numeric range. Rows with values below this limit are excluded.
3610 * @param upper_limit The upper bound of the numeric range. Rows with values above this limit are excluded.
3611 * @param logic An integer representing logical operation flags. Supported flags include:
3612 * - `SDDS_NEGATE_PREVIOUS`: Invert the previous row flag.
3613 * - `SDDS_NEGATE_MATCH`: Invert the match result.
3614 * - `SDDS_AND`: Combine with existing row flags using logical AND.
3615 * - `SDDS_OR`: Combine with existing row flags using logical OR.
3616 * - `SDDS_NEGATE_EXPRESSION`: Invert the entire logical expression.
3617 *
3618 * @return On success, returns the number of rows marked as "of interest" after filtering. On failure, returns `-1` and sets an appropriate error message.
3619 *
3620 * @retval -1 Indicates that an error occurred (e.g., invalid dataset, unrecognized filter column, non-numeric filter column).
3621 * @retval Non-negative Integer representing the count of rows marked as "of interest".
3622 *
3623 * @note
3624 * - The filter column must exist and be of a numeric type (e.g., `SDDS_SHORT`, `SDDS_USHORT`, `SDDS_LONG`, `SDDS_ULONG`, `SDDS_LONG64`, `SDDS_ULONG64`, `SDDS_FLOAT`, `SDDS_DOUBLE`, `SDDS_LONGDOUBLE`).
3625 * - Logical flags determine how the filtering interacts with existing row flags. Multiple flags can be combined using bitwise OR.
3626 *
3627 * @sa SDDS_SetRowsOfInterest, SDDS_MatchRowsOfInterest, SDDS_DeleteUnsetRows
3628 */
3629int64_t SDDS_FilterRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *filter_column, double lower_limit, double upper_limit, int32_t logic) {
3630 int32_t accept, type, index;
3631 int64_t i, count;
3632 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_FilterRowsOfInterest"))
3633 return (-1);
3634 if (!filter_column) {
3635 SDDS_SetError("Unable to filter rows--filter column name not given (SDDS_FilterRowsOfInterest)");
3636 return (-1);
3637 }
3638 if ((index = SDDS_GetColumnIndex(SDDS_dataset, filter_column)) < 0) {
3639 SDDS_SetError("Unable to filter rows--column name is unrecognized (SDDS_FilterRowsOfInterest)");
3640 return (-1);
3641 }
3642 switch (type = SDDS_GetColumnType(SDDS_dataset, index)) {
3643 case SDDS_SHORT:
3644 case SDDS_USHORT:
3645 case SDDS_LONG:
3646 case SDDS_ULONG:
3647 case SDDS_LONG64:
3648 case SDDS_ULONG64:
3649 case SDDS_FLOAT:
3650 case SDDS_DOUBLE:
3651 case SDDS_LONGDOUBLE:
3652 break;
3653 default:
3654 SDDS_SetError("Unable to filter rows--filter column is not a numeric type (SDDS_FilterRowsOfInterest)");
3655 return (-1);
3656 }
3657 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3658 if (logic & SDDS_NEGATE_PREVIOUS)
3659 SDDS_dataset->row_flag[i] = !SDDS_dataset->row_flag[i];
3660 accept = SDDS_ItemInsideWindow(SDDS_dataset->data[index], i, type, lower_limit, upper_limit);
3661 if (logic & SDDS_NEGATE_MATCH)
3662 accept = !accept;
3663 if (logic & SDDS_AND)
3664 accept = accept && SDDS_dataset->row_flag[i];
3665 else if (logic & SDDS_OR)
3666 accept = accept || SDDS_dataset->row_flag[i];
3667 if (logic & SDDS_NEGATE_EXPRESSION)
3668 accept = !accept;
3669 if ((SDDS_dataset->row_flag[i] = accept))
3670 count++;
3671 }
3672 return (count);
3673}
3674
3675/**
3676 * @brief Filters rows of interest in an SDDS dataset based on numeric scanning of a specified column.
3677 *
3678 * This function marks rows in the provided SDDS dataset as "of interest" based on whether the entries in the specified filter
3679 * column can be interpreted as valid numbers. It supports inversion of the filtering criterion through the `mode` parameter.
3680 *
3681 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3682 * @param filter_column A null-terminated string specifying the name of the column used for numeric scanning.
3683 * This column must not be of string type.
3684 * @param mode An unsigned integer representing mode flags. Supported flags include:
3685 * - `NUMSCANFILTER_INVERT`: Invert the filtering criterion (select rows where the entry is not a number).
3686 *
3687 * @return On success, returns the number of rows marked as "of interest" after filtering. On failure, returns `-1` and sets an appropriate error message.
3688 *
3689 * @retval -1 Indicates that an error occurred (e.g., invalid dataset, unrecognized filter column, filter column is of string type).
3690 * @retval Non-negative Integer representing the count of rows marked as "of interest".
3691 *
3692 * @note
3693 * - The filter column must exist and must not be of string type.
3694 * - The function uses `tokenIsNumber` to determine if an entry is a valid number.
3695 *
3696 * @sa SDDS_SetRowsOfInterest, SDDS_MatchRowsOfInterest, SDDS_DeleteUnsetRows
3697 */
3698int64_t SDDS_FilterRowsByNumScan(SDDS_DATASET *SDDS_dataset, char *filter_column, uint32_t mode) {
3699 int32_t accept, index;
3700 int64_t i, count;
3701 short invert;
3702 char *ptr;
3703
3704 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_FilterRowsByNumScan"))
3705 return (-1);
3706 if (!filter_column) {
3707 SDDS_SetError("Unable to filter rows--filter column name not given (SDDS_FilterRowsByNumScan)");
3708 return (-1);
3709 }
3710 if ((index = SDDS_GetColumnIndex(SDDS_dataset, filter_column)) < 0) {
3711 SDDS_SetError("Unable to filter rows--column name is unrecognized (SDDS_FilterRowsByNumScan)");
3712 return (-1);
3713 }
3714 switch (SDDS_GetColumnType(SDDS_dataset, index)) {
3715 case SDDS_SHORT:
3716 case SDDS_USHORT:
3717 case SDDS_LONG:
3718 case SDDS_ULONG:
3719 case SDDS_LONG64:
3720 case SDDS_ULONG64:
3721 case SDDS_FLOAT:
3722 case SDDS_DOUBLE:
3723 case SDDS_LONGDOUBLE:
3724 case SDDS_CHARACTER:
3725 SDDS_SetError("Unable to filter rows--filter column is not string type (SDDS_FilterRowsByNumScan)");
3726 return (-1);
3727 default:
3728 break;
3729 }
3730 invert = mode & NUMSCANFILTER_INVERT ? 1 : 0;
3731 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3732 ptr = ((char **)(SDDS_dataset->data[index]))[i];
3733 accept = !invert;
3734 if (!tokenIsNumber(ptr))
3735 accept = invert;
3736 if ((SDDS_dataset->row_flag[i] = accept))
3737 count++;
3738 }
3739 return (count);
3740}
3741
3742/**
3743 * @brief Deletes rows from an SDDS dataset that are not marked as "of interest".
3744 *
3745 * This function removes all rows in the provided SDDS dataset that have not been flagged as "of interest" using prior selection functions.
3746 * It effectively compacts the dataset by retaining only the desired rows and updating the row count accordingly.
3747 *
3748 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3749 *
3750 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3751 *
3752 * @retval 1 Indicates that rows were successfully deleted.
3753 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, problem copying rows).
3754 *
3755 * @note
3756 * - This operation modifies the dataset in place by removing unset rows.
3757 * - It is recommended to perform row selection before calling this function to ensure that only desired rows are retained.
3758 *
3759 * @sa SDDS_SetRowsOfInterest, SDDS_MatchRowsOfInterest, SDDS_FilterRowsOfInterest
3760 */
3761int32_t SDDS_DeleteUnsetRows(SDDS_DATASET *SDDS_dataset) {
3762 int64_t i, j;
3763 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DeleteUnsetRows"))
3764 return (0);
3765
3766 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
3767 if (SDDS_dataset->row_flag[i]) {
3768 if (i != j) {
3769 SDDS_dataset->row_flag[j] = SDDS_dataset->row_flag[i];
3770 if (!SDDS_TransferRow(SDDS_dataset, j, i)) {
3771 SDDS_SetError("Unable to delete unset rows--problem copying row (SDDS_DeleteUnsetRows)");
3772 return (0);
3773 }
3774 }
3775 j++;
3776 }
3777 }
3778 SDDS_dataset->n_rows = j;
3779 return (1);
3780}
3781
3782/**
3783 * @brief Transfers data from a source row to a target row within an SDDS dataset.
3784 *
3785 * This function copies all column data from the specified source row to the target row in the provided SDDS dataset.
3786 * It handles both string and non-string data types appropriately, ensuring that memory is managed correctly for string entries.
3787 *
3788 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3789 * @param target The index of the target row where data will be copied to.
3790 * @param source The index of the source row from which data will be copied.
3791 *
3792 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3793 *
3794 * @retval 1 Indicates that the row transfer was successful.
3795 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, out-of-range indices, memory allocation failure, string copy failure).
3796 *
3797 * @note
3798 * - Both `target` and `source` must be valid row indices within the dataset.
3799 * - The function does not allocate or deallocate rows; it only copies data between existing rows.
3800 *
3801 * @sa SDDS_DeleteUnsetRows, SDDS_CopyColumn
3802 */
3803int32_t SDDS_TransferRow(SDDS_DATASET *SDDS_dataset, int64_t target, int64_t source) {
3804 int32_t size;
3805 int64_t i;
3806 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_TransferRow"))
3807 return (0);
3808 for (i = 0; i < SDDS_dataset->layout.n_columns; i++) {
3809 if (SDDS_dataset->layout.column_definition[i].type != SDDS_STRING) {
3810 size = SDDS_type_size[SDDS_dataset->layout.column_definition[i].type - 1];
3811 memcpy((char *)SDDS_dataset->data[i] + target * size, (char *)SDDS_dataset->data[i] + source * size, size);
3812 } else {
3813 if (((char ***)SDDS_dataset->data)[i][target])
3814 free(((char ***)SDDS_dataset->data)[i][target]);
3815 ((char ***)SDDS_dataset->data)[i][target] = NULL;
3816 if (!SDDS_CopyString(((char ***)SDDS_dataset->data)[i] + target, ((char ***)SDDS_dataset->data)[i][source]))
3817 return ((int32_t)0);
3818 }
3819 }
3820 return (1);
3821}
3822
3823/**
3824 * @brief Deletes a specified column from an SDDS dataset.
3825 *
3826 * **Note:** This function is currently non-functional and will abort execution if called.
3827 *
3828 * This function is intended to remove a column identified by `column_name` from the provided SDDS dataset.
3829 * It handles the reordering of remaining columns and updates the dataset's layout accordingly. However, as indicated
3830 * by the current implementation, the function is not operational and will terminate the program when invoked.
3831 *
3832 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3833 * @param column_name A null-terminated string specifying the name of the column to be deleted.
3834 *
3835 * @return This function does not return as it aborts execution. If it were functional, it would return `1` on success
3836 * and `0` on failure.
3837 *
3838 * @warning
3839 * - **Currently Non-Functional:** The function will terminate the program with an error message when called.
3840 *
3841 * @todo
3842 * - Implement the functionality to delete a column without aborting.
3843 *
3844 * @sa SDDS_DeleteUnsetColumns, SDDS_CopyColumn
3845 */
3846int32_t SDDS_DeleteColumn(SDDS_DATASET *SDDS_dataset, char *column_name) {
3847 int32_t index;
3848 int64_t i, j;
3849
3850 SDDS_Bomb("SDDS_DeleteColumn is presently not functional.");
3851
3852 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DeleteColumn"))
3853 return (0);
3854 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
3855 SDDS_SetError("Unable to delete column--unrecognized column name (SDDS_DeleteColumn)");
3856 return (0);
3857 }
3858 for (i = index + 1; i < SDDS_dataset->layout.n_columns; i++) {
3859 if (!SDDS_CopyColumn(SDDS_dataset, i - 1, i)) {
3860 SDDS_SetError("Unable to delete column--error copying column (SDDS_DeleteColumn)");
3861 return (0);
3862 }
3863 for (j = 0; j < SDDS_dataset->n_of_interest; j++)
3864 if (SDDS_dataset->column_order[j] == index) {
3865 memcpy((char *)(SDDS_dataset->column_order + j), (char *)(SDDS_dataset->column_order + j + 1), sizeof(*SDDS_dataset->column_order) * (SDDS_dataset->n_of_interest - j - 1));
3866 SDDS_dataset->n_of_interest--;
3867 } else if (SDDS_dataset->column_order[j] > index)
3868 SDDS_dataset->column_order[j] -= 1;
3869 }
3870 if ((SDDS_dataset->layout.n_columns -= 1) == 0)
3871 SDDS_dataset->n_rows = 0;
3872 return (1);
3873}
3874
3875/**
3876 * @brief Deletes all columns from an SDDS dataset that are not marked as "of interest".
3877 *
3878 * This function iterates through all columns in the provided SDDS dataset and removes those that have not been flagged as "of interest".
3879 * It ensures that only desired columns are retained, updating the dataset's layout and column order accordingly.
3880 *
3881 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3882 *
3883 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3884 *
3885 * @retval 1 Indicates that columns were successfully deleted.
3886 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, failure to delete a column).
3887 *
3888 * @note
3889 * - This operation modifies the dataset in place by removing unset columns.
3890 * - It is recommended to perform column selection before calling this function to ensure that only desired columns are retained.
3891 *
3892 * @sa SDDS_SetColumnsOfInterest, SDDS_DeleteColumn, SDDS_CopyColumn
3893 */
3895 int64_t i;
3896 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DeleteUnsetColumns"))
3897 return (0);
3898 for (i = 0; i < SDDS_dataset->layout.n_columns; i++)
3899 if (!SDDS_dataset->column_flag[i]) {
3900 if (!SDDS_DeleteColumn(SDDS_dataset, SDDS_dataset->layout.column_definition[i].name))
3901 return (0);
3902 else
3903 i--;
3904 }
3905 return (1);
3906}
3907
3908/**
3909 * @brief Copies data from a source column to a target column within an SDDS dataset.
3910 *
3911 * This function duplicates the data from the specified source column to the target column in the provided SDDS dataset.
3912 * It handles both string and non-string data types appropriately, ensuring that memory is managed correctly for string entries.
3913 *
3914 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3915 * @param target The index of the target column where data will be copied to.
3916 * @param source The index of the source column from which data will be copied.
3917 *
3918 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3919 *
3920 * @retval 1 Indicates that the column copy was successful.
3921 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, out-of-range indices, memory allocation failure, string copy failure).
3922 *
3923 * @note
3924 * - Both `target` and `source` must be valid column indices within the dataset.
3925 * - The function does not handle the allocation of new columns; it assumes that the target column already exists.
3926 *
3927 * @sa SDDS_DeleteColumn, SDDS_DeleteUnsetColumns, SDDS_TransferRow
3928 */
3929int32_t SDDS_CopyColumn(SDDS_DATASET *SDDS_dataset, int32_t target, int32_t source) {
3930 COLUMN_DEFINITION *cd_target, *cd_source;
3931 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_CopyColumn"))
3932 return (0);
3933 if (target < 0 || source < 0 || target >= SDDS_dataset->layout.n_columns || source >= SDDS_dataset->layout.n_columns) {
3934 SDDS_SetError("Unable to copy column--target or source index out of range (SDDS_CopyColumn");
3935 return (0);
3936 }
3937 cd_target = SDDS_dataset->layout.column_definition + target;
3938 cd_source = SDDS_dataset->layout.column_definition + source;
3939 SDDS_dataset->column_flag[target] = SDDS_dataset->column_flag[source];
3940 if (SDDS_dataset->n_rows_allocated) {
3941 if (cd_target->type != cd_source->type) {
3942 if (!(SDDS_dataset->data[target] = SDDS_Realloc(SDDS_dataset->data[target], SDDS_type_size[cd_source->type - 1] * SDDS_dataset->n_rows_allocated))) {
3943 SDDS_SetError("Unable to copy column--memory allocation failure (SDDS_CopyColumn)");
3944 return (0);
3945 }
3946 }
3947 if (cd_source->type != SDDS_STRING)
3948 memcpy(SDDS_dataset->data[target], SDDS_dataset->data[source], SDDS_type_size[cd_source->type - 1] * SDDS_dataset->n_rows);
3949 else if (!SDDS_CopyStringArray(SDDS_dataset->data[target], SDDS_dataset->data[source], SDDS_dataset->n_rows)) {
3950 SDDS_SetError("Unable to copy column--string copy failure (SDDS_CopyColumn)");
3951 return (0);
3952 }
3953 }
3954 memcpy((char *)cd_target, (char *)cd_source, sizeof(*cd_target));
3955 return (1);
3956}
3957
3958/**
3959 * @brief Deletes a specified parameter from an SDDS dataset.
3960 *
3961 * This function removes a parameter identified by `parameter_name` from the provided SDDS dataset.
3962 * It shifts all subsequent parameters up to fill the gap left by the deleted parameter and updates the
3963 * dataset's parameter count accordingly.
3964 *
3965 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3966 * @param parameter_name A null-terminated string specifying the name of the parameter to be deleted.
3967 *
3968 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3969 *
3970 * @retval 1 Indicates that the parameter was successfully deleted.
3971 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, unrecognized parameter name, error copying parameters).
3972 *
3973 * @note
3974 * - This operation modifies the dataset by removing the specified parameter.
3975 * - It is recommended to ensure that the parameter to be deleted is not essential for further operations.
3976 *
3977 * @sa SDDS_CopyParameter, SDDS_DeleteUnsetParameters
3978 */
3979int32_t SDDS_DeleteParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name) {
3980 int32_t i, index;
3981 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DeleteParameter"))
3982 return (0);
3983 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
3984 SDDS_SetError("Unable to delete parameter--unrecognized parameter name (SDDS_DeleteParameter)");
3985 return (0);
3986 }
3987 for (i = index + 1; i < SDDS_dataset->layout.n_parameters; i++) {
3988 if (!SDDS_CopyParameter(SDDS_dataset, i - 1, i)) {
3989 SDDS_SetError("Unable to delete parameter--error copying parameter (SDDS_DeleteParameter)");
3990 return (0);
3991 }
3992 }
3993 SDDS_dataset->layout.n_parameters -= 1;
3994 return (1);
3995}
3996
3997/**
3998 * @brief Copies a parameter from a source index to a target index within an SDDS dataset.
3999 *
4000 * This function duplicates the parameter data from the source index to the target index in the provided SDDS dataset.
4001 * It handles both string and non-string data types appropriately, ensuring that memory is managed correctly for string entries.
4002 *
4003 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4004 * @param target The index of the target parameter where data will be copied to.
4005 * @param source The index of the source parameter from which data will be copied.
4006 *
4007 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
4008 *
4009 * @retval 1 Indicates that the parameter copy was successful.
4010 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, out-of-range indices, memory allocation failure, string copy failure).
4011 *
4012 * @note
4013 * - Both `target` and `source` must be valid parameter indices within the dataset.
4014 * - The function assumes that the target parameter already exists and is intended to be overwritten.
4015 *
4016 * @sa SDDS_DeleteParameter, SDDS_CopyArray
4017 */
4018int32_t SDDS_CopyParameter(SDDS_DATASET *SDDS_dataset, int32_t target, int32_t source) {
4019 PARAMETER_DEFINITION *cd_target, *cd_source;
4020 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_CopyParameter"))
4021 return (0);
4022 if (target < 0 || source < 0 || target >= SDDS_dataset->layout.n_parameters || source >= SDDS_dataset->layout.n_parameters) {
4023 SDDS_SetError("Unable to copy parameter--target or source index out of range (SDDS_CopyParameter");
4024 return (0);
4025 }
4026 cd_target = SDDS_dataset->layout.parameter_definition + target;
4027 cd_source = SDDS_dataset->layout.parameter_definition + source;
4028 if (SDDS_dataset->parameter) {
4029 if (cd_target->type != cd_source->type) {
4030 if (!(SDDS_dataset->parameter[target] = SDDS_Realloc(SDDS_dataset->data[target], SDDS_type_size[cd_source->type - 1]))) {
4031 SDDS_SetError("Unable to copy parameter--memory allocation failure (SDDS_CopyParameter)");
4032 return (0);
4033 }
4034 }
4035 if (cd_source->type != SDDS_STRING)
4036 memcpy(SDDS_dataset->parameter[target], SDDS_dataset->parameter[source], SDDS_type_size[cd_source->type - 1]);
4037 else if (!SDDS_CopyStringArray(SDDS_dataset->parameter[target], SDDS_dataset->parameter[source], 1)) {
4038 SDDS_SetError("Unable to copy parameter--string copy failure (SDDS_CopyParameter)");
4039 return (0);
4040 }
4041 }
4042 memcpy((char *)cd_target, (char *)cd_source, sizeof(*cd_target));
4043 return (1);
4044}
4045
4046/**
4047 * @brief Checks whether a data item is within a specified numeric window.
4048 *
4049 * This function determines if the data item at the given index within the data array falls within the range defined by
4050 * `lower_limit` and `upper_limit`. It handles various numeric data types and ensures that the value is neither NaN nor infinity.
4051 *
4052 * @param data Pointer to the data array.
4053 * @param index The index of the item within the data array to be checked.
4054 * @param type The data type of the item. Supported types include:
4055 * - `SDDS_SHORT`
4056 * - `SDDS_USHORT`
4057 * - `SDDS_LONG`
4058 * - `SDDS_ULONG`
4059 * - `SDDS_LONG64`
4060 * - `SDDS_ULONG64`
4061 * - `SDDS_FLOAT`
4062 * - `SDDS_DOUBLE`
4063 * - `SDDS_LONGDOUBLE`
4064 * @param lower_limit The lower bound of the numeric window.
4065 * @param upper_limit The upper bound of the numeric window.
4066 *
4067 * @return Returns `1` if the item is within the window and valid, otherwise returns `0`.
4068 *
4069 * @retval 1 Indicates that the item is within the specified numeric window and is a valid number.
4070 * @retval 0 Indicates that the item is outside the specified window, is NaN, is infinite, or the data type is non-numeric.
4071 *
4072 * @note
4073 * - The function sets an error message if the data type is non-numeric.
4074 * - It is essential to ensure that the `data` array is properly initialized and contains valid data before calling this function.
4075 *
4076 * @sa SDDS_FilterRowsOfInterest, SDDS_GetParameterAsDouble
4077 */
4078int32_t SDDS_ItemInsideWindow(void *data, int64_t index, int32_t type, double lower_limit, double upper_limit) {
4079 short short_val;
4080 unsigned short ushort_val;
4081 int32_t long_val;
4082 uint32_t ulong_val;
4083 int64_t long64_val;
4084 uint64_t ulong64_val;
4085 long double ldouble_val;
4086 double double_val;
4087 float float_val;
4088
4089 switch (type) {
4090 case SDDS_SHORT:
4091 if ((short_val = *((short *)data + index)) < lower_limit || short_val > upper_limit)
4092 return (0);
4093 return (1);
4094 case SDDS_USHORT:
4095 if ((ushort_val = *((unsigned short *)data + index)) < lower_limit || ushort_val > upper_limit)
4096 return (0);
4097 return (1);
4098 case SDDS_LONG:
4099 if ((long_val = *((int32_t *)data + index)) < lower_limit || long_val > upper_limit)
4100 return (0);
4101 return (1);
4102 case SDDS_ULONG:
4103 if ((ulong_val = *((uint32_t *)data + index)) < lower_limit || ulong_val > upper_limit)
4104 return (0);
4105 return (1);
4106 case SDDS_LONG64:
4107 if ((long64_val = *((int64_t *)data + index)) < lower_limit || long64_val > upper_limit)
4108 return (0);
4109 return (1);
4110 case SDDS_ULONG64:
4111 if ((ulong64_val = *((uint64_t *)data + index)) < lower_limit || ulong64_val > upper_limit)
4112 return (0);
4113 return (1);
4114 case SDDS_FLOAT:
4115 if ((float_val = *((float *)data + index)) < lower_limit || float_val > upper_limit)
4116 return (0);
4117 if (isnan(float_val) || isinf(float_val))
4118 return 0;
4119 return (1);
4120 case SDDS_DOUBLE:
4121 if ((double_val = *((double *)data + index)) < lower_limit || double_val > upper_limit)
4122 return 0;
4123 if (isnan(double_val) || isinf(double_val))
4124 return 0;
4125 return (1);
4126 case SDDS_LONGDOUBLE:
4127 if ((ldouble_val = *((long double *)data + index)) < lower_limit || ldouble_val > upper_limit)
4128 return 0;
4129 if (isnan(ldouble_val) || isinf(ldouble_val))
4130 return 0;
4131 return (1);
4132 default:
4133 SDDS_SetError("Unable to complete window check--item type is non-numeric (SDDS_ItemInsideWindow)");
4134 return (0);
4135 }
4136}
4137
4138/**
4139 * @brief Applies logical operations to determine the new state of a row flag based on previous and current match conditions.
4140 *
4141 * This function evaluates logical conditions between a previous flag (`previous`) and a current match flag (`match`) based on the
4142 * provided `logic` flags. It supports various logical operations such as AND, OR, negation of previous flags, and negation of match results.
4143 *
4144 * @param previous The previous state of the row flag (typically `0` or `1`).
4145 * @param match The current match result to be combined with the previous flag.
4146 * @param logic An unsigned integer representing logical operation flags. Supported flags include:
4147 * - `SDDS_0_PREVIOUS`: Set the previous flag to `0`.
4148 * - `SDDS_1_PREVIOUS`: Set the previous flag to `1`.
4149 * - `SDDS_NEGATE_PREVIOUS`: Negate the previous flag.
4150 * - `SDDS_NEGATE_MATCH`: Negate the current match result.
4151 * - `SDDS_AND`: Perform a logical AND between the previous flag and the match result.
4152 * - `SDDS_OR`: Perform a logical OR between the previous flag and the match result.
4153 * - `SDDS_NEGATE_EXPRESSION`: Negate the final logical expression result.
4154 *
4155 * @return Returns the result of the logical operation as an integer (`0` or `1`).
4156 *
4157 * @retval 1 Indicates that the final logical condition evaluates to true.
4158 * @retval 0 Indicates that the final logical condition evaluates to false.
4159 *
4160 * @note
4161 * - Multiple logic flags can be combined using bitwise OR to perform complex logical operations.
4162 * - The order of operations follows the precedence defined within the function implementation.
4163 *
4164 * @sa SDDS_SetRowsOfInterest, SDDS_MatchRowsOfInterest
4165 */
4166int32_t SDDS_Logic(int32_t previous, int32_t match, uint32_t logic) {
4167 if (logic & SDDS_0_PREVIOUS)
4168 previous = 0;
4169 else if (logic & SDDS_1_PREVIOUS)
4170 previous = 1;
4171 if (logic & SDDS_NEGATE_PREVIOUS)
4172 previous = !previous;
4173 if (logic & SDDS_NEGATE_MATCH)
4174 match = !match;
4175 if (logic & SDDS_AND)
4176 match = match && previous;
4177 else if (logic & SDDS_OR)
4178 match = match || previous;
4179 else
4180 match = previous;
4181 if (logic & SDDS_NEGATE_EXPRESSION)
4182 match = !match;
4183 return (match);
4184}
4185
4186/**
4187 * @brief Retrieves an array from the current data table of an SDDS dataset.
4188 *
4189 * This function returns a pointer to a `SDDS_ARRAY` structure containing the data and other information about a specified array
4190 * within the current data table of an SDDS dataset. The function can either populate a provided `SDDS_ARRAY` structure or allocate
4191 * a new one if `memory` is `NULL`.
4192 *
4193 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4194 * @param array_name A null-terminated string specifying the name of the SDDS array to retrieve.
4195 * @param memory Optional pointer to an existing `SDDS_ARRAY` structure where the array information will be stored. If `NULL`,
4196 * a new `SDDS_ARRAY` structure is allocated and returned.
4197 *
4198 * @return On success, returns a pointer to a `SDDS_ARRAY` structure containing the array data and metadata. If `memory` is not `NULL`,
4199 * the function populates the provided structure. On failure, returns `NULL` and sets an appropriate error message.
4200 *
4201 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, memory allocation failure).
4202 * @retval Non-NULL Pointer to a `SDDS_ARRAY` structure containing the array data and metadata.
4203 *
4204 * @note
4205 * - The caller is responsible for freeing the allocated memory for the `SDDS_ARRAY` structure if `memory` is `NULL`.
4206 * - The `definition` field in the returned structure points to the internal copy of the array definition.
4207 *
4208 * @sa SDDS_GetArrayInDoubles, SDDS_GetArrayInString, SDDS_GetArrayInLong
4209 */
4210SDDS_ARRAY *SDDS_GetArray(SDDS_DATASET *SDDS_dataset, char *array_name, SDDS_ARRAY *memory) {
4211 int32_t index, type, size;
4212 SDDS_ARRAY *copy, *original;
4213
4214 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetArray"))
4215 return (NULL);
4216 if (!array_name) {
4217 SDDS_SetError("Unable to get array--array name pointer is NULL (SDDS_GetArray)");
4218 return (NULL);
4219 }
4220 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4221 SDDS_SetError("Unable to get array--array name is unrecognized (SDDS_GetArray)");
4222 return (NULL);
4223 }
4224 if (memory)
4225 copy = memory;
4226 else if (!(copy = (SDDS_ARRAY *)calloc(1, sizeof(*copy)))) {
4227 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArray)");
4228 return (NULL);
4229 }
4230 original = SDDS_dataset->array + index;
4231 if (copy->definition && !SDDS_FreeArrayDefinition(copy->definition)) {
4232 SDDS_SetError("Unable to get array--array definition corrupted (SDDS_GetArray)");
4233 return (NULL);
4234 }
4235 if (!SDDS_CopyArrayDefinition(&copy->definition, original->definition)) {
4236 SDDS_SetError("Unable to get array--array definition missing (SDDS_GetArray)");
4237 return (NULL);
4238 }
4239 type = copy->definition->type;
4240 size = SDDS_type_size[copy->definition->type - 1];
4241 if (!(copy->dimension = SDDS_Realloc(copy->dimension, sizeof(*copy->dimension) * copy->definition->dimensions))) {
4242 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArray)");
4243 return (NULL);
4244 }
4245 memcpy((void *)copy->dimension, (void *)original->dimension, sizeof(*copy->dimension) * copy->definition->dimensions);
4246 if (!(copy->elements = original->elements))
4247 return (copy);
4248 if (!(copy->data = SDDS_Realloc(copy->data, size * original->elements))) {
4249 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArray)");
4250 return (NULL);
4251 }
4252
4253 if (copy->definition->type != SDDS_STRING)
4254 memcpy(copy->data, original->data, size * copy->elements);
4255 else if (!SDDS_CopyStringArray((char **)copy->data, (char **)original->data, original->elements)) {
4256 SDDS_SetError("Unable to get array--string copy failure (SDDS_GetArray)");
4257 return (NULL);
4258 }
4259
4260 /* should free existing subpointers here, but probably not worth the trouble */
4261 if (copy->pointer && copy->definition->dimensions != 1)
4262 free(copy->pointer);
4263 if (!(copy->pointer = SDDS_MakePointerArray(copy->data, type, copy->definition->dimensions, copy->dimension))) {
4264 SDDS_SetError("Unable to get array--couldn't make pointer array (SDDS_GetArray)");
4265 return (NULL);
4266 }
4267 return (copy);
4268}
4269
4270/**
4271 * @brief Retrieves an array from the current data table of an SDDS dataset and converts its elements to strings.
4272 *
4273 * This function extracts the specified array from the provided SDDS dataset and converts each of its elements into a null-terminated
4274 * string representation. The conversion respects the data type of the array elements, ensuring accurate string formatting.
4275 *
4276 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4277 * @param array_name A null-terminated string specifying the name of the SDDS array to retrieve and convert.
4278 * @param values Pointer to an integer where the number of elements in the array will be stored upon successful completion.
4279 *
4280 * @return On success, returns a pointer to an array of null-terminated strings (`char **`). Each string represents an element of the
4281 * original SDDS array. On failure, returns `NULL` and sets an appropriate error message.
4282 *
4283 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, memory allocation failure).
4284 * @retval Non-NULL Pointer to an array of strings representing the SDDS array elements.
4285 *
4286 * @note
4287 * - The caller is responsible for freeing each string in the returned array as well as the array itself.
4288 * - The function handles different data types, including numeric types and strings, ensuring proper formatting for each type.
4289 *
4290 * @sa SDDS_GetArray, SDDS_GetArrayInDoubles, SDDS_GetArrayInLong
4291 */
4292char **SDDS_GetArrayInString(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t *values) {
4293 int32_t index, type, i, elements;
4294 SDDS_ARRAY *original;
4295 char **data;
4296 char buffer[SDDS_MAXLINE];
4297 void *rawData;
4298
4299 *values = 0;
4300 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetArrayInString"))
4301 return (NULL);
4302 if (!array_name) {
4303 SDDS_SetError("Unable to get array--array name pointer is NULL (SDDS_GetArrayInString)");
4304 return (NULL);
4305 }
4306 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4307 SDDS_SetError("Unable to get array--array name is unrecognized (SDDS_GetArrayInString)");
4308 return (NULL);
4309 }
4310 original = SDDS_dataset->array + index;
4311 type = original->definition->type;
4312 elements = original->elements;
4313 if (!(data = (char **)SDDS_Malloc(sizeof(*data) * elements))) {
4314 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArrayInString)");
4315 return (NULL);
4316 }
4317 rawData = original->data;
4318 switch (type) {
4319 case SDDS_LONGDOUBLE:
4320 for (i = 0; i < elements; i++) {
4321 if (LDBL_DIG == 18) {
4322 sprintf(buffer, "%22.18Le", ((long double *)rawData)[i]);
4323 } else {
4324 sprintf(buffer, "%22.15Le", ((long double *)rawData)[i]);
4325 }
4326 SDDS_CopyString(&data[i], buffer);
4327 }
4328 break;
4329 case SDDS_DOUBLE:
4330 for (i = 0; i < elements; i++) {
4331 sprintf(buffer, "%22.15le", ((double *)rawData)[i]);
4332 SDDS_CopyString(&data[i], buffer);
4333 }
4334 break;
4335 case SDDS_FLOAT:
4336 for (i = 0; i < elements; i++) {
4337 sprintf(buffer, "%15.8e", ((float *)rawData)[i]);
4338 SDDS_CopyString(&data[i], buffer);
4339 }
4340 break;
4341 case SDDS_LONG64:
4342 for (i = 0; i < elements; i++) {
4343 sprintf(buffer, "%" PRId64, ((int64_t *)rawData)[i]);
4344 SDDS_CopyString(&data[i], buffer);
4345 }
4346 break;
4347 case SDDS_ULONG64:
4348 for (i = 0; i < elements; i++) {
4349 sprintf(buffer, "%" PRIu64, ((uint64_t *)rawData)[i]);
4350 SDDS_CopyString(&data[i], buffer);
4351 }
4352 break;
4353 case SDDS_LONG:
4354 for (i = 0; i < elements; i++) {
4355 sprintf(buffer, "%" PRId32, ((int32_t *)rawData)[i]);
4356 SDDS_CopyString(&data[i], buffer);
4357 }
4358 break;
4359 case SDDS_ULONG:
4360 for (i = 0; i < elements; i++) {
4361 sprintf(buffer, "%" PRIu32, ((uint32_t *)rawData)[i]);
4362 SDDS_CopyString(&data[i], buffer);
4363 }
4364 break;
4365 case SDDS_SHORT:
4366 for (i = 0; i < elements; i++) {
4367 sprintf(buffer, "%hd", ((short *)rawData)[i]);
4368 SDDS_CopyString(&data[i], buffer);
4369 }
4370 break;
4371 case SDDS_USHORT:
4372 for (i = 0; i < elements; i++) {
4373 sprintf(buffer, "%hu", ((unsigned short *)rawData)[i]);
4374 SDDS_CopyString(&data[i], buffer);
4375 }
4376 break;
4377 case SDDS_CHARACTER:
4378 for (i = 0; i < elements; i++) {
4379 sprintf(buffer, "%c", ((char *)rawData)[i]);
4380 SDDS_CopyString(&data[i], buffer);
4381 }
4382 break;
4383 case SDDS_STRING:
4384 for (i = 0; i < elements; i++) {
4385 SDDS_CopyString(&data[i], ((char **)rawData)[i]);
4386 }
4387 break;
4388 }
4389 *values = elements;
4390 return data;
4391}
4392
4393/**
4394 * @brief Retrieves an array from the current data table of an SDDS dataset and converts its elements to doubles.
4395 *
4396 * This function extracts the specified array from the provided SDDS dataset and converts each of its elements into a `double` value.
4397 * It ensures that the array is of a compatible numeric type before performing the conversion.
4398 *
4399 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4400 * @param array_name A null-terminated string specifying the name of the SDDS array to retrieve and convert.
4401 * @param values Pointer to an integer where the number of elements in the array will be stored upon successful completion.
4402 *
4403 * @return On success, returns a pointer to an array of `double` values representing the SDDS array elements. On failure, returns `NULL` and sets an appropriate error message.
4404 *
4405 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, incompatible array type, memory allocation failure).
4406 * @retval Non-NULL Pointer to an array of `double` values representing the SDDS array elements.
4407 *
4408 * @note
4409 * - The caller is responsible for freeing the allocated memory for the returned `double` array.
4410 * - The function does not handle string-type arrays; attempting to retrieve a string array will result in an error.
4411 *
4412 * @sa SDDS_GetArray, SDDS_GetArrayInString, SDDS_GetArrayInLong
4413 */
4414double *SDDS_GetArrayInDoubles(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t *values) {
4415 int32_t index, type, i, elements;
4416 SDDS_ARRAY *original;
4417 double *data;
4418 void *rawData;
4419
4420 *values = 0;
4421 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetArrayInDoubles"))
4422 return (NULL);
4423 if (!array_name) {
4424 SDDS_SetError("Unable to get array--array name pointer is NULL (SDDS_GetArrayInDoubles)");
4425 return (NULL);
4426 }
4427 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4428 SDDS_SetError("Unable to get array--array name is unrecognized (SDDS_GetArrayInDoubles)");
4429 return (NULL);
4430 }
4431 original = SDDS_dataset->array + index;
4432 if ((type = original->definition->type) == SDDS_STRING) {
4433 SDDS_SetError("Unable to get array--string type (SDDS_GetArrayInDoubles)");
4434 return (NULL);
4435 }
4436 elements = original->elements;
4437 if (!(data = SDDS_Malloc(sizeof(*data) * elements))) {
4438 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArrayInDoubles)");
4439 return (NULL);
4440 }
4441 rawData = original->data;
4442 switch (type) {
4443 case SDDS_LONGDOUBLE:
4444 for (i = 0; i < elements; i++) {
4445 data[i] = ((long double *)rawData)[i];
4446 }
4447 break;
4448 case SDDS_DOUBLE:
4449 for (i = 0; i < elements; i++) {
4450 data[i] = ((double *)rawData)[i];
4451 }
4452 break;
4453 case SDDS_FLOAT:
4454 for (i = 0; i < elements; i++) {
4455 data[i] = ((float *)rawData)[i];
4456 }
4457 break;
4458 case SDDS_LONG64:
4459 for (i = 0; i < elements; i++) {
4460 data[i] = ((int64_t *)rawData)[i];
4461 }
4462 break;
4463 case SDDS_ULONG64:
4464 for (i = 0; i < elements; i++) {
4465 data[i] = ((uint64_t *)rawData)[i];
4466 }
4467 break;
4468 case SDDS_LONG:
4469 for (i = 0; i < elements; i++) {
4470 data[i] = ((int32_t *)rawData)[i];
4471 }
4472 break;
4473 case SDDS_ULONG:
4474 for (i = 0; i < elements; i++) {
4475 data[i] = ((uint32_t *)rawData)[i];
4476 }
4477 break;
4478 case SDDS_SHORT:
4479 for (i = 0; i < elements; i++) {
4480 data[i] = ((short *)rawData)[i];
4481 }
4482 break;
4483 case SDDS_USHORT:
4484 for (i = 0; i < elements; i++) {
4485 data[i] = ((unsigned short *)rawData)[i];
4486 }
4487 break;
4488 case SDDS_CHARACTER:
4489 for (i = 0; i < elements; i++) {
4490 data[i] = ((char *)rawData)[i];
4491 }
4492 break;
4493 }
4494 *values = elements;
4495 return data;
4496}
4497
4498/**
4499 * @brief Retrieves an array from the current data table of an SDDS dataset and converts its elements to 32-bit integers.
4500 *
4501 * This function extracts the specified array from the provided SDDS dataset and converts each of its elements into a 32-bit integer (`int32_t`).
4502 * It ensures that the array is of a compatible numeric type before performing the conversion.
4503 *
4504 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4505 * @param array_name A null-terminated string specifying the name of the SDDS array to retrieve and convert.
4506 * @param values Pointer to an integer where the number of elements in the array will be stored upon successful completion.
4507 *
4508 * @return On success, returns a pointer to an array of `int32_t` values representing the SDDS array elements. On failure, returns `NULL` and sets an appropriate error message.
4509 *
4510 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, incompatible array type, memory allocation failure).
4511 * @retval Non-NULL Pointer to an array of `int32_t` values representing the SDDS array elements.
4512 *
4513 * @note
4514 * - The caller is responsible for freeing the allocated memory for the returned `int32_t` array.
4515 * - The function does not handle string-type arrays; attempting to retrieve a string array will result in an error.
4516 *
4517 * @sa SDDS_GetArray, SDDS_GetArrayInDoubles, SDDS_GetArrayInString
4518 */
4519int32_t *SDDS_GetArrayInLong(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t *values) {
4520 int32_t index, type, i, elements;
4521 SDDS_ARRAY *original;
4522 int32_t *data;
4523 void *rawData;
4524
4525 *values = 0;
4526 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetArrayInLong"))
4527 return (NULL);
4528 if (!array_name) {
4529 SDDS_SetError("Unable to get array--array name pointer is NULL (SDDS_GetArrayInLong)");
4530 return (NULL);
4531 }
4532 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4533 SDDS_SetError("Unable to get array--array name is unrecognized (SDDS_GetArrayInLong)");
4534 return (NULL);
4535 }
4536 original = SDDS_dataset->array + index;
4537 if ((type = original->definition->type) == SDDS_STRING) {
4538 SDDS_SetError("Unable to get array--string type (SDDS_GetArrayInLong)");
4539 return (NULL);
4540 }
4541 elements = original->elements;
4542 if (!(data = SDDS_Malloc(sizeof(*data) * elements))) {
4543 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArrayInLong)");
4544 return (NULL);
4545 }
4546 rawData = original->data;
4547 switch (type) {
4548 case SDDS_LONGDOUBLE:
4549 for (i = 0; i < elements; i++) {
4550 data[i] = ((long double *)rawData)[i];
4551 }
4552 break;
4553 case SDDS_DOUBLE:
4554 for (i = 0; i < elements; i++) {
4555 data[i] = ((double *)rawData)[i];
4556 }
4557 break;
4558 case SDDS_FLOAT:
4559 for (i = 0; i < elements; i++) {
4560 data[i] = ((float *)rawData)[i];
4561 }
4562 break;
4563 case SDDS_LONG64:
4564 for (i = 0; i < elements; i++) {
4565 data[i] = ((int64_t *)rawData)[i];
4566 }
4567 break;
4568 case SDDS_ULONG64:
4569 for (i = 0; i < elements; i++) {
4570 data[i] = ((uint64_t *)rawData)[i];
4571 }
4572 break;
4573 case SDDS_LONG:
4574 for (i = 0; i < elements; i++) {
4575 data[i] = ((int32_t *)rawData)[i];
4576 }
4577 break;
4578 case SDDS_ULONG:
4579 for (i = 0; i < elements; i++) {
4580 data[i] = ((uint32_t *)rawData)[i];
4581 }
4582 break;
4583 case SDDS_SHORT:
4584 for (i = 0; i < elements; i++) {
4585 data[i] = ((short *)rawData)[i];
4586 }
4587 break;
4588 case SDDS_USHORT:
4589 for (i = 0; i < elements; i++) {
4590 data[i] = ((unsigned short *)rawData)[i];
4591 }
4592 break;
4593 case SDDS_CHARACTER:
4594 for (i = 0; i < elements; i++) {
4595 data[i] = ((char *)rawData)[i];
4596 }
4597 break;
4598 }
4599 *values = elements;
4600 return data;
4601}
4602
4603/**
4604 * @brief Retrieves the text and contents descriptions from an SDDS dataset.
4605 *
4606 * This function extracts the text description and contents description from the specified SDDS dataset.
4607 * The descriptions are copied into the provided pointers if they are not `NULL`. This allows users to
4608 * obtain metadata information about the dataset's content and purpose.
4609 *
4610 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4611 * @param text Pointer to a `char*` variable where the text description will be copied.
4612 * If `NULL`, the text description is not retrieved.
4613 * @param contents Pointer to a `char*` variable where the contents description will be copied.
4614 * If `NULL`, the contents description is not retrieved.
4615 *
4616 * @return Returns `1` on successful retrieval of the descriptions. On failure, returns `0` and sets an appropriate error message.
4617 *
4618 * @retval 1 Indicates that the descriptions were successfully retrieved and copied.
4619 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, memory allocation failure).
4620 *
4621 * @note
4622 * - The caller is responsible for freeing the memory allocated for `text` and `contents` if they are not `NULL`.
4623 * - Ensure that the dataset is properly initialized before calling this function.
4624 *
4625 * @sa SDDS_SetDescription, SDDS_GetArray, SDDS_GetParameter
4626 */
4627int32_t SDDS_GetDescription(SDDS_DATASET *SDDS_dataset, char **text, char **contents) {
4628 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetDescription"))
4629 return (0);
4630 if (text) {
4631 *text = NULL;
4632 if (!SDDS_CopyString(text, SDDS_dataset->layout.description)) {
4633 SDDS_SetError("Unable to retrieve description data (SDDS_GetDescription)");
4634 return (0);
4635 }
4636 }
4637 if (contents) {
4638 *contents = NULL;
4639 if (!SDDS_CopyString(contents, SDDS_dataset->layout.contents)) {
4640 SDDS_SetError("Unable to retrieve description data (SDDS_GetDescription)");
4641 return (0);
4642 }
4643 }
4644
4645 return (1);
4646}
4647
4648/**
4649 * @brief Sets unit conversions for a specified array in an SDDS dataset.
4650 *
4651 * This function updates the units of the specified array within the SDDS dataset and applies a conversion factor
4652 * to all its elements if the dataset has already been read (i.e., `pages_read > 0`). The function ensures that
4653 * the new units are consistent with the old units if provided.
4654 *
4655 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4656 * @param array_name A null-terminated string specifying the name of the array to update.
4657 * @param new_units A null-terminated string specifying the new units to assign to the array.
4658 * This parameter must not be `NULL`.
4659 * @param old_units A null-terminated string specifying the expected current units of the array.
4660 * If `NULL`, the function does not verify the existing units.
4661 * @param factor A `double` representing the conversion factor to apply to each element of the array.
4662 * Each element will be multiplied by this factor.
4663 *
4664 * @return Returns `1` on successful unit conversion and update. On failure, returns `0` and sets an appropriate error message.
4665 *
4666 * @retval 1 Indicates that the unit conversion was successfully applied.
4667 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, type undefined, memory allocation failure).
4668 *
4669 * @note
4670 * - The `new_units` parameter must not be `NULL`. Passing `NULL` will result in an error.
4671 * - If the dataset has not been read yet (`pages_read == 0`), the conversion factor is stored but not applied immediately.
4672 * - The function handles various data types, ensuring that the conversion factor is appropriately applied based on the array's type.
4673 *
4674 * @sa SDDS_SetColumnUnitsConversion, SDDS_SetParameterUnitsConversion, SDDS_GetArray
4675 */
4676int32_t SDDS_SetArrayUnitsConversion(SDDS_DATASET *SDDS_dataset, char *array_name, char *new_units, char *old_units, double factor) {
4677 int32_t index, type;
4678 int64_t i;
4679 void *rawData;
4680 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetArrayUnitsConversion"))
4681 return(0);
4682 if (new_units == NULL) {
4683 SDDS_SetError("new_units is NULL (SDDS_SetArrayUnitsConversion)");
4684 return(0);
4685 }
4686 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4687 SDDS_SetError("Unable to get array--name is not recognized (SDDS_SetArrayUnitsConversion)");
4688 return(0);
4689 }
4690 if (!(type = SDDS_GetArrayType(SDDS_dataset, index))) {
4691 SDDS_SetError("Unable to get array--data type undefined (SDDS_SetArrayUnitsConversion)");
4692 return(0);
4693 }
4694 if (SDDS_dataset->layout.array_definition[index].units != NULL) {
4695 if (strcmp(new_units, SDDS_dataset->layout.array_definition[index].units) != 0) {
4696 if ((old_units != NULL) && (strcmp(old_units, SDDS_dataset->layout.array_definition[index].units) != 0)) {
4697 SDDS_SetError("Unexpected units value found (SDDS_SetArrayUnitsConversion)");
4698 return(0);
4699 }
4700 /* free(SDDS_dataset->layout.array_definition[index].units); */
4701 cp_str(&(SDDS_dataset->layout.array_definition[index].units), new_units);
4702 }
4703 } else {
4704 cp_str(&(SDDS_dataset->layout.array_definition[index].units), new_units);
4705 }
4706
4707 if (SDDS_dataset->pages_read == 0) {
4708 return(1);
4709 }
4710 rawData = SDDS_dataset->array[index].data;
4711 switch (type) {
4712 case SDDS_LONGDOUBLE:
4713 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4714 ((long double *)rawData)[i] *= factor;
4715 }
4716 break;
4717 case SDDS_DOUBLE:
4718 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4719 ((double *)rawData)[i] *= factor;
4720 }
4721 break;
4722 case SDDS_FLOAT:
4723 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4724 ((float *)rawData)[i] *= factor;
4725 }
4726 break;
4727 case SDDS_LONG:
4728 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4729 ((int32_t *)rawData)[i] *= factor;
4730 }
4731 break;
4732 case SDDS_ULONG:
4733 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4734 ((uint32_t *)rawData)[i] *= factor;
4735 }
4736 break;
4737 case SDDS_LONG64:
4738 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4739 ((int64_t *)rawData)[i] *= factor;
4740 }
4741 break;
4742 case SDDS_ULONG64:
4743 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4744 ((uint64_t *)rawData)[i] *= factor;
4745 }
4746 break;
4747 case SDDS_SHORT:
4748 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4749 ((short *)rawData)[i] *= factor;
4750 }
4751 break;
4752 case SDDS_USHORT:
4753 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4754 ((unsigned short *)rawData)[i] *= factor;
4755 }
4756 break;
4757 }
4758 return(1);
4759}
4760
4761/**
4762 * @brief Sets unit conversions for a specified column in an SDDS dataset.
4763 *
4764 * This function updates the units of the specified column within the SDDS dataset and applies a conversion factor
4765 * to all its elements if the dataset has already been read (i.e., `pages_read > 0`). The function ensures that
4766 * the new units are consistent with the old units if provided.
4767 *
4768 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4769 * @param column_name A null-terminated string specifying the name of the column to update.
4770 * @param new_units A null-terminated string specifying the new units to assign to the column.
4771 * This parameter must not be `NULL`.
4772 * @param old_units A null-terminated string specifying the expected current units of the column.
4773 * If `NULL`, the function does not verify the existing units.
4774 * @param factor A `double` representing the conversion factor to apply to each element of the column.
4775 * Each element will be multiplied by this factor.
4776 *
4777 * @return Returns `1` on successful unit conversion and update. On failure, returns `0` and sets an appropriate error message.
4778 *
4779 * @retval 1 Indicates that the unit conversion was successfully applied.
4780 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, unrecognized column name, type undefined, memory allocation failure).
4781 *
4782 * @note
4783 * - The `new_units` parameter must not be `NULL`. Passing `NULL` will result in an error.
4784 * - If the dataset has not been read yet (`pages_read == 0`), the conversion factor is stored but not applied immediately.
4785 * - The function handles various data types, ensuring that the conversion factor is appropriately applied based on the column's type.
4786 *
4787 * @sa SDDS_SetArrayUnitsConversion, SDDS_SetParameterUnitsConversion, SDDS_GetColumn
4788 */
4789int32_t SDDS_SetColumnUnitsConversion(SDDS_DATASET *SDDS_dataset, char *column_name, char *new_units, char *old_units, double factor) {
4790 int32_t index, type;
4791 int64_t i;
4792 void *rawData;
4793 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetColumnUnitsConversion"))
4794 return(0);
4795 if (new_units == NULL) {
4796 SDDS_SetError("new_units is NULL (SDDS_SetColumnUnitsConversion)");
4797 return(0);
4798 }
4799 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
4800 SDDS_SetError("Unable to get column--name is not recognized (SDDS_SetColumnUnitsConversion)");
4801 return(0);
4802 }
4803 if (!(type = SDDS_GetColumnType(SDDS_dataset, index))) {
4804 SDDS_SetError("Unable to get column--data type undefined (SDDS_SetColumnUnitsConversion)");
4805 return(0);
4806 }
4807 if (SDDS_dataset->layout.column_definition[index].units != NULL) {
4808 if (strcmp(new_units, SDDS_dataset->layout.column_definition[index].units) != 0) {
4809 if ((old_units != NULL) && (strcmp(old_units, SDDS_dataset->layout.column_definition[index].units) != 0)) {
4810 SDDS_SetError("Unexpected units value found (SDDS_SetColumnUnitsConversion)");
4811 return(0);
4812 }
4813 free(SDDS_dataset->layout.column_definition[index].units);
4814 cp_str(&(SDDS_dataset->original_layout.column_definition[index].units), new_units);
4815 cp_str(&(SDDS_dataset->layout.column_definition[index].units), new_units);
4816 }
4817 } else {
4818 cp_str(&(SDDS_dataset->original_layout.column_definition[index].units), new_units);
4819 cp_str(&(SDDS_dataset->layout.column_definition[index].units), new_units);
4820 }
4821
4822 if (SDDS_dataset->pages_read == 0) {
4823 return(1);
4824 }
4825 rawData = SDDS_dataset->data[index];
4826 switch (type) {
4827 case SDDS_LONGDOUBLE:
4828 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4829 ((long double *)rawData)[i] *= factor;
4830 }
4831 break;
4832 case SDDS_DOUBLE:
4833 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4834 ((double *)rawData)[i] *= factor;
4835 }
4836 break;
4837 case SDDS_FLOAT:
4838 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4839 ((float *)rawData)[i] *= factor;
4840 }
4841 break;
4842 case SDDS_LONG:
4843 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4844 ((int32_t *)rawData)[i] *= factor;
4845 }
4846 break;
4847 case SDDS_ULONG:
4848 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4849 ((uint32_t *)rawData)[i] *= factor;
4850 }
4851 break;
4852 case SDDS_LONG64:
4853 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4854 ((int64_t *)rawData)[i] *= factor;
4855 }
4856 break;
4857 case SDDS_ULONG64:
4858 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4859 ((uint64_t *)rawData)[i] *= factor;
4860 }
4861 break;
4862 case SDDS_SHORT:
4863 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4864 ((short *)rawData)[i] *= factor;
4865 }
4866 break;
4867 case SDDS_USHORT:
4868 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4869 ((unsigned short *)rawData)[i] *= factor;
4870 }
4871 break;
4872 }
4873 return(1);
4874}
4875
4876/**
4877 * @brief Sets unit conversions for a specified parameter in an SDDS dataset.
4878 *
4879 * This function updates the units of the specified parameter within the SDDS dataset and applies a conversion factor
4880 * to its value if the dataset has already been read (i.e., `pages_read > 0`). The function ensures that the new units
4881 * are consistent with the old units if provided.
4882 *
4883 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4884 * @param parameter_name A null-terminated string specifying the name of the parameter to update.
4885 * @param new_units A null-terminated string specifying the new units to assign to the parameter.
4886 * This parameter must not be `NULL`.
4887 * @param old_units A null-terminated string specifying the expected current units of the parameter.
4888 * If `NULL`, the function does not verify the existing units.
4889 * @param factor A `double` representing the conversion factor to apply to the parameter's value.
4890 * The parameter's value will be multiplied by this factor.
4891 *
4892 * @return Returns `1` on successful unit conversion and update. On failure, returns `0` and sets an appropriate error message.
4893 *
4894 * @retval 1 Indicates that the unit conversion was successfully applied.
4895 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, unrecognized parameter name, type undefined, memory allocation failure).
4896 *
4897 * @note
4898 * - The `new_units` parameter must not be `NULL`. Passing `NULL` will result in an error.
4899 * - If the dataset has not been read yet (`pages_read == 0`), the conversion factor is stored but not applied immediately.
4900 * - The function handles various data types, ensuring that the conversion factor is appropriately applied based on the parameter's type.
4901 *
4902 * @sa SDDS_SetArrayUnitsConversion, SDDS_SetColumnUnitsConversion, SDDS_GetParameter
4903 */
4904int32_t SDDS_SetParameterUnitsConversion(SDDS_DATASET *SDDS_dataset, char *parameter_name, char *new_units, char *old_units, double factor) {
4905 int32_t index, type;
4906 void *rawData;
4907 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetParameterUnitsConversion"))
4908 return(0);
4909 if (new_units == NULL) {
4910 SDDS_SetError("new_units is NULL (SDDS_SetParameterUnitsConversion)");
4911 return(0);
4912 }
4913 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
4914 SDDS_SetError("Unable to get parameter--name is not recognized (SDDS_SetParameterUnitsConversion)");
4915 return(0);
4916 }
4917 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
4918 SDDS_SetError("Unable to get parameter--data type undefined (SDDS_SetParameterUnitsConversion)");
4919 return(0);
4920 }
4921 if (SDDS_dataset->layout.parameter_definition[index].units != NULL) {
4922 if (strcmp(new_units, SDDS_dataset->layout.parameter_definition[index].units) != 0) {
4923 if ((old_units != NULL) && (strcmp(old_units, SDDS_dataset->layout.parameter_definition[index].units) != 0)) {
4924 SDDS_SetError("Unexpected units value found (SDDS_SetParameterUnitsConversion)");
4925 return(0);
4926 }
4927 /* free(SDDS_dataset->layout.parameter_definition[index].units); */
4928 cp_str(&(SDDS_dataset->layout.parameter_definition[index].units), new_units);
4929 }
4930 } else {
4931 cp_str(&(SDDS_dataset->layout.parameter_definition[index].units), new_units);
4932 }
4933
4934 if (SDDS_dataset->pages_read == 0) {
4935 return(1);
4936 }
4937 rawData = SDDS_dataset->parameter[index];
4938 switch (type) {
4939 case SDDS_LONGDOUBLE:
4940 *((long double *)rawData) *= factor;
4941 break;
4942 case SDDS_DOUBLE:
4943 *((double *)rawData) *= factor;
4944 break;
4945 case SDDS_FLOAT:
4946 *((float *)rawData) *= factor;
4947 break;
4948 case SDDS_LONG:
4949 *((int32_t *)rawData) *= factor;
4950 break;
4951 case SDDS_ULONG:
4952 *((uint32_t *)rawData) *= factor;
4953 break;
4954 case SDDS_LONG64:
4955 *((int64_t *)rawData) *= factor;
4956 break;
4957 case SDDS_ULONG64:
4958 *((uint64_t *)rawData) *= factor;
4959 break;
4960 case SDDS_SHORT:
4961 *((short *)rawData) *= factor;
4962 break;
4963 case SDDS_USHORT:
4964 *((unsigned short *)rawData) *= factor;
4965 break;
4966 }
4967 return(1);
4968}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_ScanData(char *string, int32_t type, int32_t field_length, void *data, int64_t index, int32_t is_parameter)
Scans a string and saves the parsed value into a data pointer according to the specified data type.
int32_t SDDS_type_size[SDDS_NUM_TYPES]
Array of sizes for each supported data type.
Definition SDDS_data.c:62
int32_t SDDS_AllocateColumnFlags(SDDS_DATASET *SDDS_target)
int64_t SDDS_GetSelectedRowIndex(SDDS_DATASET *SDDS_dataset, int64_t srow_index)
Retrieves the actual row index corresponding to a selected row position within the current data table...
int32_t SDDS_TransferRow(SDDS_DATASET *SDDS_dataset, int64_t target, int64_t source)
Transfers data from a source row to a target row within an SDDS dataset.
int32_t SDDS_CountColumnsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of columns marked as "of interest" in the current data table.
char * SDDS_GetParameterAsFormattedString(SDDS_DATASET *SDDS_dataset, char *parameter_name, char **memory, char *suppliedformat)
Retrieves the value of a specified parameter as a formatted string from the current data table of an ...
char ** SDDS_GetArrayInString(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t *values)
Retrieves an array from the current data table of an SDDS dataset and converts its elements to string...
int32_t SDDS_AssertRowFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode,...)
Sets acceptance flags for rows based on specified criteria.
int32_t * SDDS_GetParameterAsLong(SDDS_DATASET *SDDS_dataset, char *parameter_name, int32_t *memory)
Retrieves the value of a specified parameter as a 32-bit integer from the current data table of a dat...
void * SDDS_GetNumericColumn(SDDS_DATASET *SDDS_dataset, char *column_name, int32_t desiredType)
Retrieves the data of a specified numerical column as an array of a desired numerical type,...
int32_t SDDS_AssertColumnFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode,...)
Sets acceptance flags for columns based on specified criteria.
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
double * SDDS_GetParameterAsDouble(SDDS_DATASET *SDDS_dataset, char *parameter_name, double *memory)
Retrieves the value of a specified parameter as a double from the current data table of an SDDS datas...
void * SDDS_GetDoubleMatrixFromColumn(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t dimension1, int64_t dimension2, int32_t mode)
Extracts a matrix of doubles from a specified column in the current data table of an SDDS dataset.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
int32_t SDDS_GetRowFlag(SDDS_DATASET *SDDS_dataset, int64_t row)
Retrieves the acceptance flag of a specific row in the current data table.
void * SDDS_GetCastMatrixOfRows(SDDS_DATASET *SDDS_dataset, int64_t *n_rows, int32_t sddsType)
Retrieves all rows marked as "of interest" as a matrix, casting each value to a specified numerical t...
double SDDS_GetValueAsDouble(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t srow_index)
Retrieves the value from a specified column and selected row, casting it to a double.
int64_t SDDS_FilterRowsByNumScan(SDDS_DATASET *SDDS_dataset, char *filter_column, uint32_t mode)
Filters rows of interest in an SDDS dataset based on numeric scanning of a specified column.
long double * SDDS_GetColumnInLongDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of long doubles, considering only rows...
void * SDDS_GetFixedValueParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the fixed value of a specified parameter from an SDDS dataset.
int32_t SDDS_SetParameterUnitsConversion(SDDS_DATASET *SDDS_dataset, char *parameter_name, char *new_units, char *old_units, double factor)
Sets unit conversions for a specified parameter in an SDDS dataset.
void * SDDS_GetRow(SDDS_DATASET *SDDS_dataset, int64_t srow_index, void *memory)
Retrieves the data of a specific selected row as an array, considering only columns marked as "of int...
int32_t SDDS_SetColumnUnitsConversion(SDDS_DATASET *SDDS_dataset, char *column_name, char *new_units, char *old_units, double factor)
Sets unit conversions for a specified column in an SDDS dataset.
int32_t SDDS_GetRowType(SDDS_DATASET *SDDS_dataset)
Determines the data type of the rows based on selected columns in the current data table.
int32_t SDDS_SetRowFlags(SDDS_DATASET *SDDS_dataset, int32_t row_flag_value)
Sets the acceptance flags for all rows in the current data table of a data set.
double SDDS_GetValueByIndexAsDouble(SDDS_DATASET *SDDS_dataset, int32_t column_index, int64_t srow_index)
Retrieves the value from a specified column and selected row, casting it to a double.
int32_t SDDS_DeleteUnsetColumns(SDDS_DATASET *SDDS_dataset)
Deletes all columns from an SDDS dataset that are not marked as "of interest".
int32_t SDDS_SetColumnsOfInterest(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Sets the acceptance flags for columns based on specified naming criteria.
int32_t SDDS_ItemInsideWindow(void *data, int64_t index, int32_t type, double lower_limit, double upper_limit)
Checks whether a data item is within a specified numeric window.
SDDS_ARRAY * SDDS_GetArray(SDDS_DATASET *SDDS_dataset, char *array_name, SDDS_ARRAY *memory)
Retrieves an array from the current data table of an SDDS dataset.
int64_t SDDS_MatchRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *selection_column, char *label_to_match, int32_t logic)
Matches and marks rows of interest in an SDDS dataset based on label matching.
int32_t * SDDS_GetColumnInLong(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of 32-bit integers,...
int32_t SDDS_Logic(int32_t previous, int32_t match, uint32_t logic)
Applies logical operations to determine the new state of a row flag based on previous and current mat...
void * SDDS_GetInternalColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves an internal pointer to the data of a specified column, including all rows.
char * SDDS_GetParameterAsString(SDDS_DATASET *SDDS_dataset, char *parameter_name, char **memory)
Retrieves the value of a specified parameter as a string from the current data table of an SDDS datas...
char ** SDDS_GetColumnInString(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified column as an array of strings, considering only rows marked as "of ...
void * SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory)
Retrieves the value of a specified parameter from the current data table of a data set.
int32_t SDDS_DeleteColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Deletes a specified column from an SDDS dataset.
int32_t SDDS_DeleteUnsetRows(SDDS_DATASET *SDDS_dataset)
Deletes rows from an SDDS dataset that are not marked as "of interest".
long double * SDDS_GetParameterAsLongDouble(SDDS_DATASET *SDDS_dataset, char *parameter_name, long double *memory)
Retrieves the value of a specified parameter as a long double from the current data table of an SDDS ...
void * SDDS_GetParameterByIndex(SDDS_DATASET *SDDS_dataset, int32_t index, void *memory)
Retrieves the value of a specified parameter by its index from the current data table of a data set.
void * SDDS_GetMatrixFromColumn(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t dimension1, int64_t dimension2, int32_t mode)
Extracts a matrix from a specified column in the current data table of an SDDS dataset.
float * SDDS_GetColumnInFloats(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of floats, considering only rows marke...
void * SDDS_GetValueByAbsIndex(SDDS_DATASET *SDDS_dataset, int32_t column_index, int64_t row_index, void *memory)
Retrieves the value from a specified column and absolute row index, optionally storing it in provided...
int32_t SDDS_DeleteParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name)
Deletes a specified parameter from an SDDS dataset.
int32_t SDDS_SetColumnFlags(SDDS_DATASET *SDDS_dataset, int32_t column_flag_value)
Sets the acceptance flags for all columns in the current data table of a data set.
int32_t SDDS_GetDescription(SDDS_DATASET *SDDS_dataset, char **text, char **contents)
Retrieves the text and contents descriptions from an SDDS dataset.
int32_t SDDS_GetRowFlags(SDDS_DATASET *SDDS_dataset, int32_t *flag, int64_t rows)
Retrieves the acceptance flags for all rows in the current data table.
int32_t * SDDS_GetArrayInLong(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t *values)
Retrieves an array from the current data table of an SDDS dataset and converts its elements to 32-bit...
void * SDDS_GetValue(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t srow_index, void *memory)
Retrieves the value from a specified column and selected row, optionally storing it in provided memor...
int32_t SDDS_GetParameters(SDDS_DATASET *SDDS_dataset,...)
Retrieves multiple parameter values from the current data table of a data set.
short * SDDS_GetColumnInShort(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of short integers, considering only ro...
int32_t SDDS_CopyParameter(SDDS_DATASET *SDDS_dataset, int32_t target, int32_t source)
Copies a parameter from a source index to a target index within an SDDS dataset.
double * SDDS_GetArrayInDoubles(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t *values)
Retrieves an array from the current data table of an SDDS dataset and converts its elements to double...
int64_t * SDDS_GetParameterAsLong64(SDDS_DATASET *SDDS_dataset, char *parameter_name, int64_t *memory)
Retrieves the value of a specified parameter as a 64-bit integer from the current data table of an SD...
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
int32_t SDDS_CopyColumn(SDDS_DATASET *SDDS_dataset, int32_t target, int32_t source)
Copies data from a source column to a target column within an SDDS dataset.
int32_t SDDS_SetArrayUnitsConversion(SDDS_DATASET *SDDS_dataset, char *array_name, char *new_units, char *old_units, double factor)
Sets unit conversions for a specified array in an SDDS dataset.
void * SDDS_GetMatrixOfRows(SDDS_DATASET *SDDS_dataset, int64_t *n_rows)
Retrieves all rows marked as "of interest" as a matrix (array of row arrays).
int64_t SDDS_FilterRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *filter_column, double lower_limit, double upper_limit, int32_t logic)
Filters rows of interest in an SDDS dataset based on numeric ranges in a specified column.
int64_t SDDS_SetRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *selection_column, int32_t mode,...)
Sets the rows of interest in an SDDS dataset based on various selection criteria.
void * SDDS_GetValueByIndex(SDDS_DATASET *SDDS_dataset, int32_t column_index, int64_t srow_index, void *memory)
Retrieves the value from a specified column and selected row, optionally storing it in provided memor...
int32_t SDDS_GetParameterInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified parameter in the SDDS dataset.
Definition SDDS_info.c:117
int32_t SDDS_GetColumnMemoryMode(SDDS_DATASET *SDDS_dataset)
Internal definitions and function declarations for SDDS with LZMA support.
int64_t SDDS_ConvertToLong64(int32_t type, void *data, int64_t index)
Converts a value to a 64-bit integer based on its type.
Definition SDDS_rpn.c:239
double SDDS_ConvertToDouble(int32_t type, void *data, int64_t index)
Converts a value to double based on its type.
Definition SDDS_rpn.c:199
long double SDDS_ConvertToLongDouble(int32_t type, void *data, int64_t index)
Converts a value to long double based on its type.
Definition SDDS_rpn.c:159
int32_t SDDS_ConvertToLong(int32_t type, void *data, int64_t index)
Converts a value to a 32-bit integer based on its type.
Definition SDDS_rpn.c:279
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:421
int32_t SDDS_GetParameterType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a parameter in the SDDS dataset by its index.
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:816
int32_t SDDS_FreeArrayDefinition(ARRAY_DEFINITION *source)
Frees memory allocated for an array definition.
int32_t SDDS_GetArrayIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named array in the SDDS dataset.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
void * SDDS_CastValue(void *data, int64_t index, int32_t data_type, int32_t desired_type, void *memory)
Casts a value from one SDDS data type to another.
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.
void * SDDS_AllocateMatrix(int32_t size, int64_t dim1, int64_t dim2)
Allocates a two-dimensional matrix with zero-initialized elements.
int32_t SDDS_GetArrayType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of an array in the SDDS dataset by its index.
int32_t SDDS_CheckDataset(SDDS_DATASET *SDDS_dataset, const char *caller)
Validates the SDDS dataset pointer.
Definition SDDS_utils.c:618
int32_t SDDS_CopyStringArray(char **target, char **source, int64_t n_strings)
Copies an array of strings from source to target.
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:705
int32_t SDDS_GetTypeSize(int32_t type)
Retrieves the size in bytes of a specified SDDS data type.
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
int32_t SDDS_GetToken(char *s, char *buffer, int32_t buflen)
Extracts the next token from a string, handling quoted substrings and escape characters.
ARRAY_DEFINITION * SDDS_CopyArrayDefinition(ARRAY_DEFINITION **target, ARRAY_DEFINITION *source)
Creates a copy of an array definition.
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:380
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:922
int32_t SDDS_CheckTabularData(SDDS_DATASET *SDDS_dataset, const char *caller)
Validates the consistency of tabular data within an SDDS dataset.
Definition SDDS_utils.c:643
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:743
void * SDDS_MakePointerArray(void *data, int32_t type, int32_t dimensions, int32_t *dimension)
Creates a multi-dimensional pointer array from a contiguous data block.
#define SDDS_ULONG
Identifier for the unsigned 32-bit integer data type.
Definition SDDStypes.h:67
#define SDDS_FLOAT
Identifier for the float data type.
Definition SDDStypes.h:43
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_ULONG64
Identifier for the unsigned 64-bit integer data type.
Definition SDDStypes.h:55
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_SHORT
Identifier for the signed short integer data type.
Definition SDDStypes.h:73
#define SDDS_CHARACTER
Identifier for the character data type.
Definition SDDStypes.h:91
#define SDDS_USHORT
Identifier for the unsigned short integer data type.
Definition SDDStypes.h:79
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
#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
char * cp_str(char **s, char *t)
Copies a string, allocating memory for storage.
Definition cp_str.c:28
long tokenIsNumber(char *token)
Checks if the given token represents a valid number.
Definition data_scan.c:530
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int wild_match_ci(char *string, char *template)
Determine whether one string is a case-insensitive wildcard match for another.
Definition wild_match.c:220
int strcmp_ci(const char *s, const char *t)
Compare two strings case-insensitively.
Definition wild_match.c:396
char * expand_ranges(char *template)
Expand range specifiers in a wildcard template into explicit character lists.
Definition wild_match.c:429
int wild_match(char *string, char *template)
Determine whether one string is a wildcard match for another.
Definition wild_match.c:49