SDDSlib
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 case SDDS_STRING:
1553 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1554 if (SDDS_dataset->row_flag[i]) {
1555 SDDS_CopyString(&data[j++], ((char **)rawData)[i]);
1556 }
1557 }
1558 break;
1559 }
1560 if (j != n_rows) {
1561 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetColumnInString)");
1562 return (NULL);
1563 }
1564 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
1565 SDDS_dataset->column_track_memory[index] = 0;
1566 //Free internal copy now under the assumption that the program will not ask for it again.
1567 if (type == SDDS_STRING) {
1568 if (0) {
1569 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
1570 char **ptr = (char **)SDDS_dataset->data[index];
1571 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
1572 if (*ptr)
1573 free(*ptr);
1574 free(SDDS_dataset->data[index]);
1575 SDDS_dataset->data[index] = NULL;
1576 }
1577 } else {
1578 free(SDDS_dataset->data[index]);
1579 SDDS_dataset->data[index] = NULL;
1580 }
1581 }
1582 return (data);
1583}
1584
1585/**
1586 * @brief Retrieves the data of a specified numerical column as an array of a desired numerical type, considering only rows marked as "of interest".
1587 *
1588 * 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.
1589 *
1590 * @param SDDS_dataset
1591 * Pointer to the `SDDS_DATASET` structure representing the data set.
1592 * @param column_name
1593 * NULL-terminated string specifying the name of the column from which data is to be retrieved.
1594 * @param desiredType
1595 * 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.).
1596 *
1597 * @return
1598 * - **Pointer to an array of the desired numerical type** containing the data from the specified column for all rows marked as "of interest".
1599 * - **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.
1600 *
1601 * @warning
1602 * - The caller is responsible for freeing the allocated memory to prevent memory leaks.
1603 * - 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.
1604 *
1605 * @note
1606 * - 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`.
1607 * - 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.
1608 * - If the `desiredType` matches the column's data type, this function internally calls `SDDS_GetColumn`. Otherwise, it performs type casting using `SDDS_CastValue`.
1609 *
1610 * @sa
1611 * - `SDDS_GetColumnInLongDoubles`
1612 * - `SDDS_GetColumnInDoubles`
1613 * - `SDDS_GetColumnInFloats`
1614 * - `SDDS_GetColumn`
1615 * - `SDDS_CountRowsOfInterest`
1616 */
1617void *SDDS_GetNumericColumn(SDDS_DATASET *SDDS_dataset, char *column_name, int32_t desiredType) {
1618 int32_t size, type, desiredTypeSize, index;
1619 int64_t i, j, n_rows;
1620 void *data;
1621 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetNumericColumn"))
1622 return (NULL);
1623 if (!SDDS_NUMERIC_TYPE(desiredType) && desiredType != SDDS_CHARACTER) {
1624 SDDS_SetError("Unable to get column--desired type is nonnumeric (SDDS_GetNumericColumn)");
1625 return (NULL);
1626 }
1627 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1628 SDDS_SetError("Unable to get column--name is not recognized (SDDS_GetNumericColumn)");
1629 return (NULL);
1630 }
1631 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) <= 0 || (size = SDDS_GetTypeSize(type)) <= 0 || (!SDDS_NUMERIC_TYPE(type) && type != SDDS_CHARACTER)) {
1632 SDDS_SetError("Unable to get column--data size or type undefined or non-numeric (SDDS_GetNumericColumn)");
1633 return (NULL);
1634 }
1635 if (type == desiredType)
1636 return SDDS_GetColumn(SDDS_dataset, column_name);
1637 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
1638 SDDS_SetError("Unable to get column--no rows left (SDDS_GetNumericColumn)");
1639 return (NULL);
1640 }
1641 if (!(data = (void *)SDDS_Malloc((desiredTypeSize = SDDS_GetTypeSize(desiredType)) * n_rows))) {
1642 SDDS_SetError("Unable to get column--memory allocation failure (SDDS_GetNumericColumn)");
1643 return (NULL);
1644 }
1645 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1646 if (SDDS_dataset->row_flag[i] && !SDDS_CastValue(SDDS_dataset->data[index], i, type, desiredType, (char *)data + desiredTypeSize * j++)) {
1647 SDDS_SetError("Unable to get column--cast to double failed (SDDS_GetNumericColumn)");
1648 return (NULL);
1649 }
1650 }
1651 if (j != n_rows) {
1652 SDDS_SetError("Unable to get column--row number mismatch (SDDS_GetNumericColumn)");
1653 return (NULL);
1654 }
1655 if (SDDS_GetColumnMemoryMode(SDDS_dataset) == DONT_TRACK_COLUMN_MEMORY_AFTER_ACCESS) {
1656 SDDS_dataset->column_track_memory[index] = 0;
1657 //Free internal copy now under the assumption that the program will not ask for it again.
1658 if (type == SDDS_STRING) {
1659 if (0) {
1660 //FIX this. It currently causes a memory error in SDDS_ScanData2 with multipage files
1661 char **ptr = (char **)SDDS_dataset->data[index];
1662 for (i = 0; i < SDDS_dataset->n_rows_allocated; i++, ptr++)
1663 if (*ptr)
1664 free(*ptr);
1665 free(SDDS_dataset->data[index]);
1666 SDDS_dataset->data[index] = NULL;
1667 }
1668 } else {
1669 free(SDDS_dataset->data[index]);
1670 SDDS_dataset->data[index] = NULL;
1671 }
1672 }
1673 return (data);
1674}
1675
1676/**
1677 * @brief Retrieves the actual row index corresponding to a selected row position within the current data table.
1678 *
1679 * 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.
1680 *
1681 * @param SDDS_dataset
1682 * Pointer to the `SDDS_DATASET` structure representing the data set.
1683 * @param srow_index
1684 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1685 *
1686 * @return
1687 * - **Non-negative integer** representing the actual row index within the dataset's data table.
1688 * - **-1** if an error occurs (e.g., invalid dataset, tabular data not present, `srow_index` out of range).
1689 *
1690 * @warning
1691 * - Ensure that `srow_index` is within the valid range [0, `SDDS_CountRowsOfInterest(SDDS_dataset)` - 1] to avoid out-of-range errors.
1692 *
1693 * @note
1694 * - This function is useful when iterating over selected rows and needing to access their actual positions within the dataset.
1695 *
1696 * @sa
1697 * - `SDDS_CountRowsOfInterest`
1698 * - `SDDS_GetValue`
1699 * - `SDDS_GetValueAsDouble`
1700 */
1701int64_t SDDS_GetSelectedRowIndex(SDDS_DATASET *SDDS_dataset, int64_t srow_index) {
1702 int64_t i, j;
1703 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetSelectedRowIndex"))
1704 return (-1);
1705 if (!SDDS_CheckTabularData(SDDS_dataset, "SDDS_GetSelectedRowIndex"))
1706 return (-1);
1707 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
1708 if (SDDS_dataset->row_flag[i] && j++ == srow_index)
1709 break;
1710 }
1711 if (i == SDDS_dataset->n_rows)
1712 return (-1);
1713 return (i);
1714}
1715
1716/**
1717 * @brief Retrieves the value from a specified column and selected row, optionally storing it in provided memory.
1718 *
1719 * 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.
1720 *
1721 * @param SDDS_dataset
1722 * Pointer to the `SDDS_DATASET` structure representing the data set.
1723 * @param column_name
1724 * NULL-terminated string specifying the name of the column from which the value is to be retrieved.
1725 * @param srow_index
1726 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1727 * @param memory
1728 * 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.
1729 *
1730 * @return
1731 * - **Pointer to the retrieved value** stored in `memory` (if provided) or in newly allocated memory.
1732 * - **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.
1733 *
1734 * @warning
1735 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
1736 * - The function does not perform type casting. Ensure that the provided `memory` is of the appropriate type matching the column's data type.
1737 * - Modifying the data through the returned pointer affects the internal state of the dataset. Use with caution to avoid unintended side effects.
1738 *
1739 * @note
1740 * - 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.
1741 * ```c
1742 * char *string;
1743 * SDDS_GetValue(&SDDS_dataset, "name", index, &string);
1744 * // or
1745 * string = *(char**)SDDS_GetValue(&SDDS_dataset, "name", index, NULL);
1746 * ```
1747 * - The number of rows marked as "of interest" can be obtained using `SDDS_CountRowsOfInterest`.
1748 *
1749 * @sa
1750 * - `SDDS_GetValueAsDouble`
1751 * - `SDDS_GetSelectedRowIndex`
1752 * - `SDDS_CountRowsOfInterest`
1753 */
1754void *SDDS_GetValue(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t srow_index, void *memory) {
1755 int32_t type, size, column_index;
1756 int64_t row_index;
1757 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValue"))
1758 return (NULL);
1759 if ((column_index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1760 SDDS_SetError("Unable to get value--column name is not recognized (SDDS_GetValue)");
1761 return (NULL);
1762 }
1763 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
1764 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValue)");
1765 return (NULL);
1766 }
1767 size = SDDS_type_size[type - 1];
1768 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
1769 SDDS_SetError("Unable to get value--row index out of range (SDDS_GetValue)");
1770 return (NULL);
1771 }
1772 if (type != SDDS_STRING) {
1773 if (!memory && !(memory = SDDS_Malloc(size))) {
1774 SDDS_SetError("Unable to get value--memory allocation failure (SDDS_GetValue)");
1775 return (NULL);
1776 }
1777 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
1778 return (memory);
1779 }
1780 /* for character string data, a typical call would be
1781 * char *string;
1782 * SDDS_GetValue(&SDDS_dataset, "name", index, &string) or
1783 * string = *(char**)SDDS_GetValue(&SDDS_dataset, "name", index, NULL)
1784 */
1785 if (!memory && !(memory = SDDS_Malloc(size))) {
1786 SDDS_SetError("Unable to get value--memory allocation failure (SDDS_GetValue)");
1787 return (NULL);
1788 }
1789 if (SDDS_CopyString(memory, ((char **)SDDS_dataset->data[column_index])[row_index]))
1790 return (memory);
1791 return (NULL);
1792}
1793
1794/**
1795 * @brief Retrieves the value from a specified column and selected row, casting it to a double.
1796 *
1797 * 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.
1798 *
1799 * @param SDDS_dataset
1800 * Pointer to the `SDDS_DATASET` structure representing the data set.
1801 * @param column_name
1802 * NULL-terminated string specifying the name of the column from which the value is to be retrieved.
1803 * @param srow_index
1804 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1805 *
1806 * @return
1807 * - **Double** representing the casted value from the specified column and row.
1808 * - **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.
1809 *
1810 * @warning
1811 * - 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.
1812 *
1813 * @note
1814 * - The function internally allocates temporary memory to store the value before casting. This memory is freed before the function returns.
1815 *
1816 * @sa
1817 * - `SDDS_GetValue`
1818 * - `SDDS_GetSelectedRowIndex`
1819 * - `SDDS_CountRowsOfInterest`
1820 */
1821double SDDS_GetValueAsDouble(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t srow_index) {
1822 int32_t type, size, column_index;
1823 int64_t row_index;
1824 void *memory;
1825 double value = 0;
1826 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValueAsDouble"))
1827 return (0);
1828 if ((column_index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
1829 SDDS_SetError("Unable to get value--column name is not recognized (SDDS_GetValueAsDouble)");
1830 return (0);
1831 }
1832 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
1833 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValueAsDouble)");
1834 return (0);
1835 }
1836 size = SDDS_type_size[type - 1];
1837 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
1838 SDDS_SetError("Unable to get value--row index out of range (SDDS_GetValueAsDouble)");
1839 return (0);
1840 }
1841 if ((type != SDDS_STRING) && (type != SDDS_CHARACTER)) {
1842 memory = SDDS_Malloc(size);
1843 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
1844 switch (type) {
1845 case SDDS_SHORT:
1846 value = *(short *)memory;
1847 break;
1848 case SDDS_USHORT:
1849 value = *(unsigned short *)memory;
1850 break;
1851 case SDDS_LONG:
1852 value = *(int32_t *)memory;
1853 break;
1854 case SDDS_ULONG:
1855 value = *(uint32_t *)memory;
1856 break;
1857 case SDDS_LONG64:
1858 value = *(int64_t *)memory;
1859 break;
1860 case SDDS_ULONG64:
1861 value = *(uint64_t *)memory;
1862 break;
1863 case SDDS_FLOAT:
1864 value = *(float *)memory;
1865 break;
1866 case SDDS_DOUBLE:
1867 value = *(double *)memory;
1868 break;
1869 case SDDS_LONGDOUBLE:
1870 value = *(long double *)memory;
1871 break;
1872 }
1873 free(memory);
1874 return (value);
1875 }
1876 SDDS_SetError("Unable to get non-numeric value as double (SDDS_GetValueAsDouble)");
1877 return (0);
1878}
1879
1880/**
1881 * @brief Retrieves the value from a specified column and selected row, casting it to a double.
1882 *
1883 * This function accesses the value of a specific column (identified by its index) and a selected row (identified by its
1884 * selected row index among rows marked as "of interest") within the current data table of a dataset. It casts the retrieved
1885 * value to a `double` before returning it.
1886 *
1887 * @param SDDS_dataset
1888 * Pointer to the `SDDS_DATASET` structure representing the data set.
1889 * @param column_index
1890 * Zero-based index of the column from which the value is to be retrieved. Must be within the range [0, n_columns-1].
1891 * @param srow_index
1892 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1893 *
1894 * @return
1895 * - **Double** representing the casted value from the specified column and row.
1896 * - **0.0** if an error occurs (e.g., invalid dataset, column index out of range, undefined data type, row index out of range,
1897 * non-numeric column type). In this case, an error message is recorded internally.
1898 *
1899 * @warning
1900 * - This function only supports numerical data types. Attempting to retrieve and cast data from non-numeric columns (excluding `SDDS_CHARACTER`)
1901 * will result in an error.
1902 * - 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.
1903 *
1904 * @note
1905 * - The number of rows marked as "of interest" can be obtained using `SDDS_CountRowsOfInterest`.
1906 * - 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.
1907 *
1908 * @sa
1909 * - `SDDS_GetValue`
1910 * - `SDDS_GetValueAsDouble`
1911 * - `SDDS_GetSelectedRowIndex`
1912 * - `SDDS_CountRowsOfInterest`
1913 */
1914double SDDS_GetValueByIndexAsDouble(SDDS_DATASET *SDDS_dataset, int32_t column_index, int64_t srow_index) {
1915 int32_t type, size;
1916 int64_t row_index;
1917 void *memory;
1918 double value = 0;
1919 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValueByIndexAsDouble"))
1920 return (0);
1921 if (column_index < 0 || column_index >= SDDS_dataset->layout.n_columns) {
1922 SDDS_SetError("Unable to get value--column index out of range (SDDS_GetValueByIndexAsDouble)");
1923 return (0);
1924 }
1925 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
1926 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValueByIndexAsDouble)");
1927 return (0);
1928 }
1929 size = SDDS_type_size[type - 1];
1930 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
1931 SDDS_SetError("Unable to get value--row index out of range (SDDS_GetValueByIndexAsDouble)");
1932 return (0);
1933 }
1934 if ((type != SDDS_STRING) && (type != SDDS_CHARACTER)) {
1935 memory = SDDS_Malloc(size);
1936 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
1937 switch (type) {
1938 case SDDS_SHORT:
1939 value = *(short *)memory;
1940 break;
1941 case SDDS_USHORT:
1942 value = *(unsigned short *)memory;
1943 break;
1944 case SDDS_LONG:
1945 value = *(int32_t *)memory;
1946 break;
1947 case SDDS_ULONG:
1948 value = *(uint32_t *)memory;
1949 break;
1950 case SDDS_LONG64:
1951 value = *(int64_t *)memory;
1952 break;
1953 case SDDS_ULONG64:
1954 value = *(uint64_t *)memory;
1955 break;
1956 case SDDS_FLOAT:
1957 value = *(float *)memory;
1958 break;
1959 case SDDS_DOUBLE:
1960 value = *(double *)memory;
1961 break;
1962 case SDDS_LONGDOUBLE:
1963 value = *(long double *)memory;
1964 break;
1965 }
1966 free(memory);
1967 return (value);
1968 }
1969 SDDS_SetError("Unable to get non-numeric value as double (SDDS_GetValueByIndexAsDouble)");
1970 return (0);
1971}
1972
1973/**
1974 * @brief Retrieves the value from a specified column and selected row, optionally storing it in provided memory.
1975 *
1976 * This function accesses the value of a specific column (identified by its index) and a selected row (identified by its
1977 * selected row index among rows marked as "of interest") within the current data table of a dataset. The retrieved value is either
1978 * copied into user-provided memory or returned as a direct pointer to the internal data.
1979 *
1980 * @param SDDS_dataset
1981 * Pointer to the `SDDS_DATASET` structure representing the data set.
1982 * @param column_index
1983 * Zero-based index of the column from which the value is to be retrieved. Must be within the range [0, n_columns-1].
1984 * @param srow_index
1985 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
1986 * @param memory
1987 * Pointer to user-allocated memory where the retrieved value will be stored. If `NULL`, the function returns a pointer to the internal data.
1988 *
1989 * @return
1990 * - **Pointer to the retrieved value** stored in `memory` (if provided) or to the internal data.
1991 * - **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.
1992 *
1993 * @warning
1994 * - 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.
1995 * - If `memory` is provided, ensure that it points to sufficient memory to hold the data type of the column.
1996 * - This function does not perform type casting. Ensure that the `memory` type matches the column's data type.
1997 *
1998 * @note
1999 * - 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.
2000 * ```c
2001 * char *string;
2002 * SDDS_GetValueByIndex(&SDDS_dataset, column_index, index, &string);
2003 * // or
2004 * string = *(char**)SDDS_GetValueByIndex(&SDDS_dataset, column_index, index, NULL);
2005 * ```
2006 * - The number of rows marked as "of interest" can be obtained using `SDDS_CountRowsOfInterest`.
2007 *
2008 * @sa
2009 * - `SDDS_GetValue`
2010 * - `SDDS_GetValueAsDouble`
2011 * - `SDDS_GetSelectedRowIndex`
2012 * - `SDDS_CountRowsOfInterest`
2013 */
2014void *SDDS_GetValueByIndex(SDDS_DATASET *SDDS_dataset, int32_t column_index, int64_t srow_index, void *memory) {
2015 int32_t type, size;
2016 int64_t row_index;
2017 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValueByIndex"))
2018 return (NULL);
2019 if (column_index < 0 || column_index >= SDDS_dataset->layout.n_columns) {
2020 SDDS_SetError("Unable to get value--column index out of range (SDDS_GetValueByIndex)");
2021 return (NULL);
2022 }
2023 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
2024 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValueByIndex)");
2025 return (NULL);
2026 }
2027 size = SDDS_type_size[type - 1];
2028 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
2029 SDDS_SetError("Unable to get value--row index out of range (SDDS_GetValueByIndex)");
2030 return (NULL);
2031 }
2032 if (type != SDDS_STRING) {
2033 if (memory) {
2034 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
2035 return (memory);
2036 }
2037 return ((char *)SDDS_dataset->data[column_index] + row_index * size);
2038 }
2039 /* for character string data, a typical call would be
2040 * char *string;
2041 * SDDS_GetValueByIndex(&SDDS_dataset, cindex, index, &string) or
2042 * string = *(char**)SDDS_GetValue(&SDDS_dataset, cindex, index, NULL)
2043 */
2044 if (!memory)
2045 memory = SDDS_Malloc(size);
2046 if (SDDS_CopyString(memory, ((char **)SDDS_dataset->data[column_index])[row_index]))
2047 return (memory);
2048 return (NULL);
2049}
2050
2051/**
2052 * @brief Retrieves the value from a specified column and absolute row index, optionally storing it in provided memory.
2053 *
2054 * This function accesses the value of a specific column (identified by its index) and an absolute row index within the current
2055 * 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.
2056 *
2057 * @param SDDS_dataset
2058 * Pointer to the `SDDS_DATASET` structure representing the data set.
2059 * @param column_index
2060 * Zero-based index of the column from which the value is to be retrieved. Must be within the range [0, n_columns-1].
2061 * @param row_index
2062 * Absolute zero-based row index within the dataset's data table. Must be within the range [0, n_rows-1].
2063 * @param memory
2064 * Pointer to user-allocated memory where the retrieved value will be stored. If `NULL`, the function returns a pointer to the internal data.
2065 *
2066 * @return
2067 * - **Pointer to the retrieved value** stored in `memory` (if provided) or to the internal data.
2068 * - **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.
2069 *
2070 * @warning
2071 * - 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.
2072 * - If `memory` is provided, ensure that it points to sufficient memory to hold the data type of the column.
2073 * - This function does not perform type casting. Ensure that the `memory` type matches the column's data type.
2074 *
2075 * @note
2076 * - Unlike `SDDS_GetValueByIndex`, this function uses an absolute row index rather than a selected row index among rows marked as "of interest".
2077 * - 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.
2078 * ```c
2079 * char *string;
2080 * SDDS_GetValueByAbsIndex(&SDDS_dataset, column_index, row_index, &string);
2081 * // or
2082 * string = *(char**)SDDS_GetValueByAbsIndex(&SDDS_dataset, column_index, row_index, NULL);
2083 * ```
2084 *
2085 * @sa
2086 * - `SDDS_GetValue`
2087 * - `SDDS_GetValueAsDouble`
2088 * - `SDDS_CountRowsOfInterest`
2089 */
2090void *SDDS_GetValueByAbsIndex(SDDS_DATASET *SDDS_dataset, int32_t column_index, int64_t row_index, void *memory) {
2091 int32_t type, size;
2092 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetValueByAbsIndex"))
2093 return (NULL);
2094 if (column_index < 0 || column_index >= SDDS_dataset->layout.n_columns) {
2095 SDDS_SetError("Unable to get value--column index out of range (SDDS_GetValueByAbsIndex)");
2096 return (NULL);
2097 }
2098 if (row_index < 0 || row_index >= SDDS_dataset->n_rows) {
2099 SDDS_SetError("Unable to get value--index out of range (SDDS_GetValueByAbsIndex)");
2100 return (NULL);
2101 }
2102 if (!(type = SDDS_GetColumnType(SDDS_dataset, column_index))) {
2103 SDDS_SetError("Unable to get value--data type undefined (SDDS_GetValueByAbsIndex)");
2104 return (NULL);
2105 }
2106 size = SDDS_type_size[type - 1];
2107 if (type != SDDS_STRING) {
2108 if (memory) {
2109 memcpy(memory, (char *)SDDS_dataset->data[column_index] + row_index * size, size);
2110 return (memory);
2111 }
2112 return ((char *)SDDS_dataset->data[column_index] + row_index * size);
2113 }
2114 /* for character string data, a typical call would be
2115 * char *string;
2116 * SDDS_GetValueByAbsIndex(&SDDS_dataset, cindex, index, &string) or
2117 * string = *(char**)SDDS_GetValue(&SDDS_dataset, cindex, index, NULL)
2118 */
2119 if (!memory)
2120 memory = SDDS_Malloc(size);
2121 if (SDDS_CopyString(memory, ((char **)SDDS_dataset->data[column_index])[row_index]))
2122 return (memory);
2123 return (NULL);
2124}
2125
2126/**
2127 * @brief Determines the data type of the rows based on selected columns in the current data table.
2128 *
2129 * 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.
2130 *
2131 * @param SDDS_dataset
2132 * Pointer to the `SDDS_DATASET` structure representing the data set.
2133 *
2134 * @return
2135 * - **Integer representing the data type** (as defined by SDDS constants) if all selected columns have the same data type.
2136 * - **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.
2137 *
2138 * @warning
2139 * - Ensure that at least one column is marked as "of interest" before calling this function to avoid unexpected results.
2140 *
2141 * @note
2142 * - This function is useful for operations that require uniform data types across all selected columns.
2143 *
2144 * @sa
2145 * - `SDDS_GetRow`
2146 * - `SDDS_SetColumnFlags`
2147 * - `SDDS_GetColumnType`
2148 */
2149int32_t SDDS_GetRowType(SDDS_DATASET *SDDS_dataset) {
2150 int64_t i;
2151 int32_t type;
2152 type = -1;
2153 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetRowType"))
2154 return (0);
2155 for (i = 0; i < SDDS_dataset->layout.n_columns; i++) {
2156 if (!SDDS_dataset->column_flag[i])
2157 continue;
2158 if (type == -1)
2159 type = SDDS_dataset->layout.column_definition[i].type;
2160 else if (type != SDDS_dataset->layout.column_definition[i].type) {
2161 SDDS_SetError("Unable to get row type--inconsistent data type for selected columns (SDDS_GetRowType)");
2162 return (0);
2163 }
2164 }
2165 return (type);
2166}
2167
2168/**
2169 * @brief Retrieves the data of a specific selected row as an array, considering only columns marked as "of interest".
2170 *
2171 * This function extracts data from a specific selected row (identified by its selected row index among rows marked as "of interest")
2172 * 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
2173 * as a newly allocated array or stores it in user-provided memory.
2174 *
2175 * @param SDDS_dataset
2176 * Pointer to the `SDDS_DATASET` structure representing the data set.
2177 * @param srow_index
2178 * Zero-based index representing the position of the selected row among all rows marked as "of interest".
2179 * @param memory
2180 * Pointer to user-allocated memory where the retrieved row data will be stored. If `NULL`, the function allocates memory.
2181 *
2182 * @return
2183 * - **Pointer to the retrieved row data array** stored in `memory` (if provided) or to newly allocated memory.
2184 * - **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.
2185 *
2186 * @warning
2187 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
2188 * - All selected columns must have the same data type. If there is an inconsistency, the function will fail.
2189 * - 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.
2190 *
2191 * @note
2192 * - 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`.
2193 * - 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.
2194 *
2195 * @sa
2196 * - `SDDS_GetRowType`
2197 * - `SDDS_SetColumnFlags`
2198 * - `SDDS_GetValue`
2199 * - `SDDS_CountColumnsOfInterest`
2200 */
2201void *SDDS_GetRow(SDDS_DATASET *SDDS_dataset, int64_t srow_index, void *memory) {
2202 void *data;
2203 int32_t size, type;
2204 int64_t i, row_index;
2205
2206 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetRow"))
2207 return (NULL);
2208 if ((row_index = SDDS_GetSelectedRowIndex(SDDS_dataset, srow_index)) < 0) {
2209 SDDS_SetError("Unable to get row--row index out of range (SDDS_GetRow)");
2210 return (NULL);
2211 }
2212 if (SDDS_dataset->n_of_interest <= 0) {
2213 SDDS_SetError("Unable to get row--no columns selected (SDDS_GetRow)");
2214 return (NULL);
2215 }
2216 if ((type = SDDS_GetRowType(SDDS_dataset)) <= 0) {
2217 SDDS_SetError("Unable to get row--inconsistent data type in selected columns (SDDS_GetRow)");
2218 return (NULL);
2219 }
2220 size = SDDS_type_size[type - 1];
2221 if (memory)
2222 data = memory;
2223 else if (!(data = SDDS_Malloc(size * SDDS_dataset->n_of_interest))) {
2224 SDDS_SetError("Unable to get row--memory allocation failure (SDDS_GetRow)");
2225 return (NULL);
2226 }
2227 if (type != SDDS_STRING)
2228 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2229 memcpy((char *)data + i * size, (char *)SDDS_dataset->data[SDDS_dataset->column_order[i]] + row_index * size, size);
2230 else
2231 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2232 if (!SDDS_CopyString((char **)data + i, ((char **)SDDS_dataset->data[SDDS_dataset->column_order[i]])[row_index]))
2233 return (NULL);
2234 return (data);
2235}
2236
2237/**
2238 * @brief Retrieves all rows marked as "of interest" as a matrix (array of row arrays).
2239 *
2240 * 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.
2241 *
2242 * @param SDDS_dataset
2243 * Pointer to the `SDDS_DATASET` structure representing the data set.
2244 * @param n_rows
2245 * Pointer to an `int64_t` variable where the number of rows retrieved will be stored.
2246 *
2247 * @return
2248 * - **Pointer to an array of pointers**, where each pointer references a row's data array.
2249 * - **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.
2250 *
2251 * @warning
2252 * - 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.
2253 * - All selected columns must have the same data type. If there is an inconsistency, the function will fail.
2254 *
2255 * @note
2256 * - The number of rows retrieved is stored in the variable pointed to by `n_rows`.
2257 * - For columns containing string data (`SDDS_STRING`), each element in the row arrays is a dynamically allocated string that must be freed individually.
2258 * - 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.
2259 *
2260 * @sa
2261 * - `SDDS_GetRowType`
2262 * - `SDDS_SetColumnFlags`
2263 * - `SDDS_GetRow`
2264 * - `SDDS_CountRowsOfInterest`
2265 */
2266void *SDDS_GetMatrixOfRows(SDDS_DATASET *SDDS_dataset, int64_t *n_rows) {
2267 void **data;
2268 int32_t size, type;
2269 int64_t i, j, k;
2270 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetMatrixOfRows"))
2271 return (NULL);
2272 if (SDDS_dataset->n_of_interest <= 0) {
2273 SDDS_SetError("Unable to get matrix of rows--no columns selected (SDDS_GetMatrixOfRows)");
2274 return (NULL);
2275 }
2276 if (!SDDS_CheckTabularData(SDDS_dataset, "SDDS_GetMatrixOfRows"))
2277 return (NULL);
2278 if ((type = SDDS_GetRowType(SDDS_dataset)) <= 0) {
2279 SDDS_SetError("Unable to get row--inconsistent data type in selected columns (SDDS_GetMatrixOfRows)");
2280 return (NULL);
2281 }
2282 size = SDDS_type_size[type - 1];
2283 if ((*n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
2284 SDDS_SetError("Unable to get matrix of rows--no rows of interest (SDDS_GetMatrixOfRows)");
2285 return (NULL);
2286 }
2287 if (!(data = (void **)SDDS_Malloc(sizeof(*data) * (*n_rows)))) {
2288 SDDS_SetError("Unable to get matrix of rows--memory allocation failure (SDDS_GetMatrixOfRows)");
2289 return (NULL);
2290 }
2291 for (j = k = 0; j < SDDS_dataset->n_rows; j++) {
2292 if (SDDS_dataset->row_flag[j]) {
2293 if (!(data[k] = SDDS_Malloc(size * SDDS_dataset->n_of_interest))) {
2294 SDDS_SetError("Unable to get matrix of rows--memory allocation failure (SDDS_GetMatrixOfRows)");
2295 return (NULL);
2296 }
2297 if (type != SDDS_STRING)
2298 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2299 memcpy((char *)data[k] + i * size, (char *)SDDS_dataset->data[SDDS_dataset->column_order[i]] + j * size, size);
2300 else
2301 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2302 if (!SDDS_CopyString((char **)(data[k]) + i, ((char **)SDDS_dataset->data[SDDS_dataset->column_order[i]])[j]))
2303 return (NULL);
2304 k++;
2305 }
2306 }
2307 return (data);
2308}
2309
2310/**
2311 * @brief Retrieves all rows marked as "of interest" as a matrix, casting each value to a specified numerical type.
2312 *
2313 * 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.
2314 *
2315 * @param SDDS_dataset
2316 * Pointer to the `SDDS_DATASET` structure representing the data set.
2317 * @param n_rows
2318 * Pointer to an `int64_t` variable where the number of rows retrieved will be stored.
2319 * @param sddsType
2320 * 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.
2321 *
2322 * @return
2323 * - **Pointer to an array of pointers**, where each pointer references a row's data array cast to the specified type.
2324 * - **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.
2325 *
2326 * @warning
2327 * - 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.
2328 * - All selected columns must have numerical data types. If any selected column is non-numeric, the function will fail.
2329 * - Ensure that `sddsType` is a valid numerical type supported by SDDS.
2330 *
2331 * @note
2332 * - The number of rows retrieved is stored in the variable pointed to by `n_rows`.
2333 * - This function performs type casting using `SDDS_CastValue`. If casting fails for any value, the function will terminate and return `NULL`.
2334 * - 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.
2335 *
2336 * @sa
2337 * - `SDDS_GetMatrixOfRows`
2338 * - `SDDS_CastValue`
2339 * - `SDDS_GetRowType`
2340 * - `SDDS_SetColumnFlags`
2341 * - `SDDS_CountRowsOfInterest`
2342 */
2343void *SDDS_GetCastMatrixOfRows(SDDS_DATASET *SDDS_dataset, int64_t *n_rows, int32_t sddsType) {
2344 void **data;
2345 int32_t size;
2346 int64_t i, j, k;
2347
2348 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetCastMatrixOfRows"))
2349 return (NULL);
2350 if (!SDDS_NUMERIC_TYPE(sddsType)) {
2351 SDDS_SetError("Unable to get matrix of rows--no columns selected (SDDS_GetCastMatrixOfRows)");
2352 return NULL;
2353 }
2354 if (SDDS_dataset->n_of_interest <= 0) {
2355 SDDS_SetError("Unable to get matrix of rows--no columns selected (SDDS_GetCastMatrixOfRows)");
2356 return (NULL);
2357 }
2358 if (!SDDS_CheckTabularData(SDDS_dataset, "SDDS_GetCastMatrixOfRows"))
2359 return (NULL);
2360 size = SDDS_type_size[sddsType - 1];
2361 if ((*n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
2362 SDDS_SetError("Unable to get matrix of rows--no rows of interest (SDDS_GetCastMatrixOfRows)");
2363 return (NULL);
2364 }
2365 if (!(data = (void **)SDDS_Malloc(sizeof(*data) * (*n_rows)))) {
2366 SDDS_SetError("Unable to get matrix of rows--memory allocation failure (SDDS_GetCastMatrixOfRows)");
2367 return (NULL);
2368 }
2369 for (i = 0; i < SDDS_dataset->n_of_interest; i++) {
2370 if (!SDDS_NUMERIC_TYPE(SDDS_dataset->layout.column_definition[SDDS_dataset->column_order[i]].type)) {
2371 SDDS_SetError("Unable to get matrix of rows--not all columns are numeric (SDDS_GetCastMatrixOfRows)");
2372 return NULL;
2373 }
2374 }
2375 for (j = k = 0; j < SDDS_dataset->n_rows; j++) {
2376 if (SDDS_dataset->row_flag[j]) {
2377 if (!(data[k] = SDDS_Malloc(size * SDDS_dataset->n_of_interest))) {
2378 SDDS_SetError("Unable to get matrix of rows--memory allocation failure (SDDS_GetCastMatrixOfRows)");
2379 return (NULL);
2380 }
2381 for (i = 0; i < SDDS_dataset->n_of_interest; i++)
2382 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));
2383 k++;
2384 }
2385 }
2386 return (data);
2387}
2388
2389/**
2390 * @brief Retrieves multiple parameter values from the current data table of a data set.
2391 *
2392 * 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.
2393 *
2394 * @param SDDS_dataset
2395 * Pointer to the `SDDS_DATASET` structure representing the data set.
2396 * @param ...
2397 * Variable arguments consisting of pairs of:
2398 * - `char *parameter_name`: NULL-terminated string specifying the name of the parameter.
2399 * - `void *memory`: Pointer to memory where the parameter's value will be stored. If `NULL`, the function will fail for that parameter.
2400 * - The argument list should be terminated when `parameter_name` is `NULL`.
2401 *
2402 * @return
2403 * - **1** on successful retrieval of all specified parameters.
2404 * - **0** if any parameter retrieval fails. An error message is recorded for the first failure encountered.
2405 *
2406 * @warning
2407 * - The function expects an even number of arguments (pairs of parameter names and memory pointers). An odd number may result in undefined behavior.
2408 * - Ensure that the `memory` pointers provided are of appropriate types and have sufficient space to hold the parameter values.
2409 *
2410 * @note
2411 * - To terminate the argument list, pass a `NULL` as the parameter name.
2412 * ```c
2413 * SDDS_GetParameters(&SDDS_dataset, "param1", &value1, "param2", &value2, NULL);
2414 * ```
2415 *
2416 * @sa
2417 * - `SDDS_GetParameter`
2418 * - `SDDS_GetParameterByIndex`
2419 */
2420int32_t SDDS_GetParameters(SDDS_DATASET *SDDS_dataset, ...) {
2421 va_list argptr;
2422 char *name;
2423 void *data;
2424 int32_t retval;
2425 char s[SDDS_MAXLINE];
2426
2427 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameters"))
2428 return 0;
2429 va_start(argptr, SDDS_dataset);
2430 retval = 1;
2431 do {
2432 if (!(name = va_arg(argptr, char *)))
2433 break;
2434 if (!(data = va_arg(argptr, void *)))
2435 retval = 0;
2436 if (!SDDS_GetParameter(SDDS_dataset, name, data)) {
2437 sprintf(s, "Unable to get value of parameter %s (SDDS_GetParameters)", name);
2438 SDDS_SetError(s);
2439 }
2440 } while (retval);
2441 va_end(argptr);
2442 return retval;
2443}
2444
2445/**
2446 * @brief Retrieves the value of a specified parameter from the current data table of a data set.
2447 *
2448 * 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.
2449 *
2450 * @param SDDS_dataset
2451 * Pointer to the `SDDS_DATASET` structure representing the data set.
2452 * @param parameter_name
2453 * NULL-terminated string specifying the name of the parameter from which the value is to be retrieved.
2454 * @param memory
2455 * Pointer to user-allocated memory where the retrieved parameter value will be stored. If `NULL`, the function allocates memory.
2456 *
2457 * @return
2458 * - **Pointer to the retrieved parameter value** stored in `memory` (if provided) or to newly allocated memory.
2459 * - **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.
2460 *
2461 * @warning
2462 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
2463 * - 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.
2464 * ```c
2465 * char *string;
2466 * SDDS_GetParameter(&SDDS_dataset, "parameter_name", &string);
2467 * // or
2468 * string = *(char**)SDDS_GetParameter(&SDDS_dataset, "parameter_name", NULL);
2469 * ```
2470 *
2471 * @note
2472 * - The size of the allocated memory corresponds to the parameter's data type, which can be obtained using `SDDS_GetParameterType`.
2473 * - 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.
2474 *
2475 * @sa
2476 * - `SDDS_GetParameters`
2477 * - `SDDS_GetParameterByIndex`
2478 * - `SDDS_SetParameter`
2479 * - `SDDS_GetParameterType`
2480 */
2481void *SDDS_GetParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory) {
2482 int32_t index, type, size;
2483 char s[SDDS_MAXLINE];
2484 void *data;
2485 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameter"))
2486 return (NULL);
2487 if (!parameter_name) {
2488 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameter)");
2489 return (NULL);
2490 }
2491 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2492 sprintf(s, "Unable to get parameter value--parameter name %s is unrecognized (SDDS_GetParameter)", parameter_name);
2493 SDDS_SetError(s);
2494 return (NULL);
2495 }
2496 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2497 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameter)");
2498 return (NULL);
2499 }
2500 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2501 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameter)");
2502 return (NULL);
2503 }
2504 size = SDDS_type_size[type - 1];
2505 if (memory)
2506 data = memory;
2507 else if (!(data = SDDS_Malloc(size))) {
2508 SDDS_SetError("Unable to get parameter value--parameter data size is invalid (SDDS_GetParameter)");
2509 return (NULL);
2510 }
2511 if (type != SDDS_STRING)
2512 memcpy(data, SDDS_dataset->parameter[index], size);
2513 else if (!SDDS_CopyString((char **)data, *(char **)SDDS_dataset->parameter[index]))
2514 return (NULL);
2515 return (data);
2516}
2517
2518/**
2519 * @brief Retrieves the value of a specified parameter by its index from the current data table of a data set.
2520 *
2521 * 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.
2522 *
2523 * @param SDDS_dataset
2524 * Pointer to the `SDDS_DATASET` structure representing the data set.
2525 * @param index
2526 * Zero-based index of the parameter to retrieve. Must be within the range [0, n_parameters-1].
2527 * @param memory
2528 * Pointer to user-allocated memory where the retrieved parameter value will be stored. If `NULL`, the function allocates memory.
2529 *
2530 * @return
2531 * - **Pointer to the retrieved parameter value** stored in `memory` (if provided) or to newly allocated memory.
2532 * - **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.
2533 *
2534 * @warning
2535 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
2536 * - 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.
2537 * ```c
2538 * char *string;
2539 * SDDS_GetParameterByIndex(&SDDS_dataset, index, &string);
2540 * // or
2541 * string = *(char**)SDDS_GetParameterByIndex(&SDDS_dataset, index, NULL);
2542 * ```
2543 *
2544 * @note
2545 * - The size of the allocated memory corresponds to the parameter's data type, which can be obtained using `SDDS_GetParameterType`.
2546 * - 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.
2547 *
2548 * @sa
2549 * - `SDDS_GetParameters`
2550 * - `SDDS_GetParameter`
2551 * - `SDDS_SetParameter`
2552 * - `SDDS_GetParameterType`
2553 */
2554void *SDDS_GetParameterByIndex(SDDS_DATASET *SDDS_dataset, int32_t index, void *memory) {
2555 int32_t type, size;
2556 void *data;
2557 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameter"))
2558 return (NULL);
2559 if (index < 0 || index >= SDDS_dataset->layout.n_parameters) {
2560 SDDS_SetError("Unable to get parameter value--parameter index is invalid (SDDS_GetParameterByIndex)");
2561 return (NULL);
2562 }
2563 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2564 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterByIndex)");
2565 return (NULL);
2566 }
2567 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2568 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterByIndex)");
2569 return (NULL);
2570 }
2571 size = SDDS_type_size[type - 1];
2572 if (memory)
2573 data = memory;
2574 else if (!(data = SDDS_Malloc(size))) {
2575 SDDS_SetError("Unable to get parameter value--parameter data size is invalid (SDDS_GetParameterByIndex)");
2576 return (NULL);
2577 }
2578 if (type != SDDS_STRING)
2579 memcpy(data, SDDS_dataset->parameter[index], size);
2580 else if (!SDDS_CopyString((char **)data, *(char **)SDDS_dataset->parameter[index]))
2581 return (NULL);
2582 return (data);
2583}
2584
2585/**
2586 * @brief Retrieves the value of a specified parameter as a 32-bit integer from the current data table of a data set.
2587 *
2588 * 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.
2589 *
2590 * @param SDDS_dataset
2591 * Pointer to the `SDDS_DATASET` structure representing the data set.
2592 * @param parameter_name
2593 * NULL-terminated string specifying the name of the parameter from which the value is to be retrieved.
2594 * @param memory
2595 * Pointer to a 32-bit integer where the converted parameter value will be stored. If `NULL`, the function allocates memory.
2596 *
2597 * @return
2598 * - **Pointer to the `int32_t` value** stored in `memory` (if provided) or to newly allocated memory containing the converted value.
2599 * - **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.
2600 *
2601 * @warning
2602 * - If `memory` is `NULL`, the function allocates memory that the caller must free to prevent memory leaks.
2603 * - This function does not support parameters of type `SDDS_STRING`. Attempting to retrieve string parameters as long integers will result in an error.
2604 *
2605 * @note
2606 * - The conversion is performed using `SDDS_ConvertToLong`, which handles casting from various numerical types to `int32_t`.
2607 * - Ensure that the parameter's data type is compatible with 32-bit integer conversion to avoid data loss or undefined behavior.
2608 *
2609 * @sa
2610 * - `SDDS_GetParameter`
2611 * - `SDDS_GetParameterByIndex`
2612 * - `SDDS_ConvertToLong`
2613 * - `SDDS_GetParameterType`
2614 */
2615int32_t *SDDS_GetParameterAsLong(SDDS_DATASET *SDDS_dataset, char *parameter_name, int32_t *memory) {
2616 int32_t index, type;
2617 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsLong"))
2618 return (NULL);
2619 if (!parameter_name) {
2620 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsLong)");
2621 return (NULL);
2622 }
2623 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2624 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsLong)");
2625 return (NULL);
2626 }
2627 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2628 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsLong)");
2629 return (NULL);
2630 }
2631 if (type == SDDS_STRING) {
2632 SDDS_SetError("Unable to get parameter value--parameter data type is SDDS_STRING (SDDS_GetParameterAsLong)");
2633 return (NULL);
2634 }
2635 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2636 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterAsLong)");
2637 return (NULL);
2638 }
2639
2640 if (!memory && !(memory = (int32_t *)SDDS_Malloc(sizeof(int32_t)))) {
2641 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsLong)");
2642 return (NULL);
2643 }
2644
2645 *memory = SDDS_ConvertToLong(type, SDDS_dataset->parameter[index], 0);
2646 return (memory);
2647}
2648
2649/**
2650 * @brief Retrieves the value of a specified parameter as a 64-bit integer from the current data table of an SDDS dataset.
2651 *
2652 * This function looks up the parameter by name within the given SDDS dataset and returns its value as an `int64_t`.
2653 * If the `memory` pointer is provided, the value is stored at the given memory location. Otherwise, the function
2654 * allocates memory to store the value, which must be freed by the caller.
2655 *
2656 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2657 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2658 * @param memory Optional pointer to an `int64_t` variable where the parameter value will be stored. If `NULL`,
2659 * memory is allocated internally to hold the value.
2660 *
2661 * @return On success, returns a pointer to the `int64_t` containing the parameter value. On failure, returns `NULL`
2662 * and sets an appropriate error message.
2663 *
2664 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, type mismatch, or memory allocation failure).
2665 * @retval Non-NULL Pointer to the `int64_t` containing the parameter value.
2666 *
2667 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2668 *
2669 * @sa SDDS_GetParameterAsDouble, SDDS_GetParameterAsString
2670 */
2671int64_t *SDDS_GetParameterAsLong64(SDDS_DATASET *SDDS_dataset, char *parameter_name, int64_t *memory) {
2672 int32_t index, type;
2673 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsLong64"))
2674 return (NULL);
2675 if (!parameter_name) {
2676 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsLong64)");
2677 return (NULL);
2678 }
2679 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2680 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsLong64)");
2681 return (NULL);
2682 }
2683 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2684 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsLong64)");
2685 return (NULL);
2686 }
2687 if (type == SDDS_STRING) {
2688 SDDS_SetError("Unable to get parameter value--parameter data type is SDDS_STRING (SDDS_GetParameterAsLong64)");
2689 return (NULL);
2690 }
2691 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2692 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterAsLong64)");
2693 return (NULL);
2694 }
2695
2696 if (!memory && !(memory = (int64_t *)SDDS_Malloc(sizeof(int64_t)))) {
2697 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsLong64)");
2698 return (NULL);
2699 }
2700
2701 *memory = SDDS_ConvertToLong64(type, SDDS_dataset->parameter[index], 0);
2702 return (memory);
2703}
2704
2705/**
2706 * @brief Retrieves the value of a specified parameter as a `long double` from the current data table of an SDDS dataset.
2707 *
2708 * This function searches for the parameter by name within the provided SDDS dataset and retrieves its value as a `long double`.
2709 * If the `memory` pointer is supplied, the value is stored at the specified memory location. If `memory` is `NULL`,
2710 * the function allocates memory for storing the value, which should be freed by the caller.
2711 *
2712 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2713 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2714 * @param memory Optional pointer to a `long double` variable where the parameter value will be stored. If `NULL`,
2715 * memory is allocated internally to hold the value.
2716 *
2717 * @return On success, returns a pointer to the `long double` containing the parameter value. On failure, returns `NULL`
2718 * and sets an appropriate error message.
2719 *
2720 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, type mismatch, or memory allocation failure).
2721 * @retval Non-NULL Pointer to the `long double` containing the parameter value.
2722 *
2723 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2724 *
2725 * @sa SDDS_GetParameterAsDouble, SDDS_GetParameterAsLong64, SDDS_GetParameterAsString
2726 */
2727long double *SDDS_GetParameterAsLongDouble(SDDS_DATASET *SDDS_dataset, char *parameter_name, long double *memory) {
2728 int32_t index = -1, type = -1;
2729 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsLongDouble"))
2730 return (NULL);
2731 if (!parameter_name) {
2732 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsLongDouble)");
2733 return (NULL);
2734 }
2735 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2736 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsLongDouble)");
2737 return (NULL);
2738 }
2739 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2740 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsLongDouble)");
2741 return (NULL);
2742 }
2743 if (type == SDDS_STRING) {
2744 SDDS_SetError("Unable to get parameter value--parameter data type is SDDS_STRING (SDDS_GetParameterAsLongDouble)");
2745 return (NULL);
2746 }
2747 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2748 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterAsLongDouble)");
2749 return (NULL);
2750 }
2751
2752 if (!memory && !(memory = (long double *)SDDS_Malloc(sizeof(long double)))) {
2753 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsLongDouble)");
2754 return (NULL);
2755 }
2756 *memory = SDDS_ConvertToLongDouble(type, SDDS_dataset->parameter[index], 0);
2757 return (memory);
2758}
2759
2760/**
2761 * @brief Retrieves the value of a specified parameter as a `double` from the current data table of an SDDS dataset.
2762 *
2763 * This function searches for the parameter by name within the provided SDDS dataset and retrieves its value as a `double`.
2764 * If the `memory` pointer is supplied, the value is stored at the specified memory location. If `memory` is `NULL`,
2765 * the function allocates memory for storing the value, which should be freed by the caller.
2766 *
2767 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2768 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2769 * @param memory Optional pointer to a `double` variable where the parameter value will be stored. If `NULL`,
2770 * memory is allocated internally to hold the value.
2771 *
2772 * @return On success, returns a pointer to the `double` containing the parameter value. On failure, returns `NULL`
2773 * and sets an appropriate error message.
2774 *
2775 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, type mismatch, or memory allocation failure).
2776 * @retval Non-NULL Pointer to the `double` containing the parameter value.
2777 *
2778 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2779 *
2780 * @sa SDDS_GetParameterAsLong64, SDDS_GetParameterAsLongDouble, SDDS_GetParameterAsString
2781 */
2782double *SDDS_GetParameterAsDouble(SDDS_DATASET *SDDS_dataset, char *parameter_name, double *memory) {
2783 int32_t index = -1, type = -1;
2784 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsDouble"))
2785 return (NULL);
2786 if (!parameter_name) {
2787 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsDouble)");
2788 return (NULL);
2789 }
2790 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2791 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsDouble)");
2792 return (NULL);
2793 }
2794 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2795 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsDouble)");
2796 return (NULL);
2797 }
2798 if (type == SDDS_STRING) {
2799 SDDS_SetError("Unable to get parameter value--parameter data type is SDDS_STRING (SDDS_GetParameterAsDouble)");
2800 return (NULL);
2801 }
2802 if (!SDDS_dataset->parameter || !SDDS_dataset->parameter[index]) {
2803 SDDS_SetError("Unable to get parameter value--parameter data array is NULL (SDDS_GetParameterAsDouble)");
2804 return (NULL);
2805 }
2806
2807 if (!memory && !(memory = (double *)SDDS_Malloc(sizeof(double)))) {
2808 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsDouble)");
2809 return (NULL);
2810 }
2811 *memory = SDDS_ConvertToDouble(type, SDDS_dataset->parameter[index], 0);
2812 return (memory);
2813}
2814
2815/**
2816 * @brief Retrieves the value of a specified parameter as a string from the current data table of an SDDS dataset.
2817 *
2818 * This function searches for the parameter by name within the provided SDDS dataset and retrieves its value as a string.
2819 * The function formats the parameter's value based on its data type. If the `memory` pointer is provided, the string
2820 * is stored at the specified memory location. Otherwise, the function allocates memory to hold the string, which
2821 * must be freed by the caller.
2822 *
2823 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2824 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2825 * @param memory Optional pointer to a `char*` variable where the string will be stored. If `NULL`, memory is allocated
2826 * internally to hold the string.
2827 *
2828 * @return On success, returns a pointer to the null-terminated string containing the parameter value. On failure, returns `NULL`
2829 * and sets an appropriate error message.
2830 *
2831 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, type mismatch, memory allocation failure, or unknown data type).
2832 * @retval Non-NULL Pointer to the null-terminated string containing the parameter value.
2833 *
2834 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2835 *
2836 * @sa SDDS_GetParameterAsDouble, SDDS_GetParameterAsLong64, SDDS_GetParameterAsLongDouble
2837 */
2838char *SDDS_GetParameterAsString(SDDS_DATASET *SDDS_dataset, char *parameter_name, char **memory) {
2839 int32_t index, type;
2840 char buffer[SDDS_MAXLINE], *parValue;
2841 void *value;
2842
2843 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsString"))
2844 return (NULL);
2845 if (!parameter_name) {
2846 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsString)");
2847 return (NULL);
2848 }
2849 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2850 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsString)");
2851 return (NULL);
2852 }
2853 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2854 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsString)");
2855 return (NULL);
2856 }
2857 value = SDDS_dataset->parameter[index];
2858 switch (type) {
2859 case SDDS_LONGDOUBLE:
2860 if (LDBL_DIG == 18) {
2861 sprintf(buffer, "%.18Le", *(long double *)value);
2862 } else {
2863 sprintf(buffer, "%.15Le", *(long double *)value);
2864 }
2865 break;
2866 case SDDS_DOUBLE:
2867 sprintf(buffer, "%.15le", *(double *)value);
2868 break;
2869 case SDDS_FLOAT:
2870 sprintf(buffer, "%.8e", *(float *)value);
2871 break;
2872 case SDDS_LONG64:
2873 sprintf(buffer, "%" PRId64, *(int64_t *)value);
2874 break;
2875 case SDDS_ULONG64:
2876 sprintf(buffer, "%" PRIu64, *(uint64_t *)value);
2877 break;
2878 case SDDS_LONG:
2879 sprintf(buffer, "%" PRId32, *(int32_t *)value);
2880 break;
2881 case SDDS_ULONG:
2882 sprintf(buffer, "%" PRIu32, *(uint32_t *)value);
2883 break;
2884 case SDDS_SHORT:
2885 sprintf(buffer, "%hd", *(short *)value);
2886 break;
2887 case SDDS_USHORT:
2888 sprintf(buffer, "%hu", *(unsigned short *)value);
2889 break;
2890 case SDDS_CHARACTER:
2891 sprintf(buffer, "%c", *(char *)value);
2892 break;
2893 case SDDS_STRING:
2894 sprintf(buffer, "%s", *(char **)value);
2895 break;
2896 default:
2897 SDDS_SetError("Unknown data type of parameter (SDDS_GetParameterAsString)");
2898 return (NULL);
2899 }
2900 if (!(parValue = malloc(sizeof(char) * (strlen(buffer) + 1)))) {
2901 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsString)");
2902 return (NULL);
2903 }
2904 strcpy(parValue, buffer);
2905 if (memory)
2906 *memory = parValue;
2907 return parValue;
2908}
2909
2910/**
2911 * @brief Retrieves the value of a specified parameter as a formatted string from the current data table of an SDDS dataset.
2912 *
2913 * This function searches for the parameter by name within the provided SDDS dataset, formats its value based on the supplied format string,
2914 * and returns it as a null-terminated string. If `suppliedformat` is `NULL`, the function uses the format string defined in the parameter's
2915 * definition. If the `memory` pointer is provided, the formatted string is stored at the specified memory location. Otherwise, memory is
2916 * allocated internally to hold the string, which must be freed by the caller.
2917 *
2918 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
2919 * @param parameter_name A null-terminated string specifying the name of the parameter to retrieve.
2920 * @param memory Optional pointer to a `char*` variable where the formatted string will be stored. If `NULL`, memory is allocated
2921 * internally to hold the string.
2922 * @param suppliedformat A null-terminated format string (similar to `printf` format specifiers) to format the parameter value. If `NULL`,
2923 * the function uses the format string defined in the parameter's definition within the dataset.
2924 *
2925 * @return On success, returns a pointer to the null-terminated formatted string containing the parameter value. On failure, returns `NULL`
2926 * and sets an appropriate error message.
2927 *
2928 * @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).
2929 * @retval Non-NULL Pointer to the null-terminated string containing the formatted parameter value.
2930 *
2931 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
2932 *
2933 * @sa SDDS_GetParameterAsDouble, SDDS_GetParameterAsString, SDDS_GetParameterAsLong64, SDDS_GetParameterAsLongDouble
2934 */
2935char *SDDS_GetParameterAsFormattedString(SDDS_DATASET *SDDS_dataset, char *parameter_name, char **memory, char *suppliedformat) {
2936 int32_t index, type;
2937 char buffer[SDDS_MAXLINE], *parValue;
2938 void *value;
2939 char *format = NULL;
2940
2941 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetParameterAsFormattedString"))
2942 return (NULL);
2943 if (!parameter_name) {
2944 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetParameterAsFormattedString)");
2945 return (NULL);
2946 }
2947 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
2948 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetParameterAsFormattedString)");
2949 return (NULL);
2950 }
2951 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
2952 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetParameterAsFormattedString)");
2953 return (NULL);
2954 }
2955 if (suppliedformat != NULL) {
2956 format = suppliedformat;
2957 if (!SDDS_VerifyPrintfFormat(format, type)) {
2958 SDDS_SetError("Unable to get parameter value--given format for parameter is invalid (SDDS_GetParameterAsFormattedString)");
2959 return (NULL);
2960 }
2961 } else {
2962 if (SDDS_GetParameterInformation(SDDS_dataset, "format_string", &format, SDDS_GET_BY_INDEX, index) != SDDS_STRING) {
2963 SDDS_SetError("Unable to get parameter value--parameter definition is invalid (SDDS_GetParameterAsFormattedString)");
2964 return (NULL);
2965 }
2966 }
2967 value = SDDS_dataset->parameter[index];
2968
2969 if (!SDDS_StringIsBlank(format)) {
2970 switch (type) {
2971 case SDDS_LONGDOUBLE:
2972 sprintf(buffer, format, *(long double *)value);
2973 break;
2974 case SDDS_DOUBLE:
2975 sprintf(buffer, format, *(double *)value);
2976 break;
2977 case SDDS_FLOAT:
2978 sprintf(buffer, format, *(float *)value);
2979 break;
2980 case SDDS_LONG64:
2981 sprintf(buffer, format, *(int64_t *)value);
2982 break;
2983 case SDDS_ULONG64:
2984 sprintf(buffer, format, *(uint64_t *)value);
2985 break;
2986 case SDDS_LONG:
2987 sprintf(buffer, format, *(int32_t *)value);
2988 break;
2989 case SDDS_ULONG:
2990 sprintf(buffer, format, *(uint32_t *)value);
2991 break;
2992 case SDDS_SHORT:
2993 sprintf(buffer, format, *(short *)value);
2994 break;
2995 case SDDS_USHORT:
2996 sprintf(buffer, format, *(unsigned short *)value);
2997 break;
2998 case SDDS_CHARACTER:
2999 sprintf(buffer, format, *(char *)value);
3000 break;
3001 case SDDS_STRING:
3002 sprintf(buffer, format, *(char **)value);
3003 break;
3004 default:
3005 SDDS_SetError("Unknown data type of parameter (SDDS_GetParameterAsFormattedString)");
3006 return (NULL);
3007 }
3008 } else {
3009 switch (type) {
3010 case SDDS_LONGDOUBLE:
3011 if (LDBL_DIG == 18) {
3012 sprintf(buffer, "%22.18Le", *(long double *)value);
3013 } else {
3014 sprintf(buffer, "%22.15Le", *(long double *)value);
3015 }
3016 break;
3017 case SDDS_DOUBLE:
3018 sprintf(buffer, "%22.15le", *(double *)value);
3019 break;
3020 case SDDS_FLOAT:
3021 sprintf(buffer, "%15.8e", *(float *)value);
3022 break;
3023 case SDDS_LONG64:
3024 sprintf(buffer, "%" PRId64, *(int64_t *)value);
3025 break;
3026 case SDDS_ULONG64:
3027 sprintf(buffer, "%" PRIu64, *(uint64_t *)value);
3028 break;
3029 case SDDS_LONG:
3030 sprintf(buffer, "%" PRId32, *(int32_t *)value);
3031 break;
3032 case SDDS_ULONG:
3033 sprintf(buffer, "%" PRIu32, *(uint32_t *)value);
3034 break;
3035 case SDDS_SHORT:
3036 sprintf(buffer, "%hd", *(short *)value);
3037 break;
3038 case SDDS_USHORT:
3039 sprintf(buffer, "%hu", *(unsigned short *)value);
3040 break;
3041 case SDDS_CHARACTER:
3042 sprintf(buffer, "%c", *(char *)value);
3043 break;
3044 case SDDS_STRING:
3045 sprintf(buffer, "%s", *(char **)value);
3046 break;
3047 default:
3048 SDDS_SetError("Unknown data type of parameter (SDDS_GetParameterAsFormattedString)");
3049 return (NULL);
3050 }
3051 }
3052 if (!(parValue = malloc(sizeof(char) * (strlen(buffer) + 1)))) {
3053 SDDS_SetError("Unable to get parameter value--memory allocation failure (SDDS_GetParameterAsFormattedString)");
3054 return (NULL);
3055 }
3056 strcpy(parValue, buffer);
3057 if (memory)
3058 *memory = parValue;
3059 return parValue;
3060}
3061
3062/**
3063 * @brief Retrieves the fixed value of a specified parameter from an SDDS dataset.
3064 *
3065 * This function accesses the fixed value defined for a given parameter in the dataset's layout and converts it to the appropriate data type.
3066 * If the `memory` pointer is provided, the converted value is stored at the specified memory location. Otherwise, memory is allocated
3067 * internally to hold the value, which must be freed by the caller.
3068 *
3069 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3070 * @param parameter_name A null-terminated string specifying the name of the parameter whose fixed value is to be retrieved.
3071 * @param memory Optional pointer to a memory location where the fixed value will be stored. The size of the memory should correspond
3072 * to the size of the parameter's data type. If `NULL`, memory is allocated internally to hold the value.
3073 *
3074 * @return On success, returns a pointer to the memory containing the fixed value. On failure, returns `NULL` and sets an appropriate
3075 * error message.
3076 *
3077 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, parameter not found, invalid data type, memory allocation failure, or scan failure).
3078 * @retval Non-NULL Pointer to the memory containing the fixed parameter value.
3079 *
3080 * @note The caller is responsible for freeing the allocated memory if the `memory` parameter is `NULL`.
3081 *
3082 * @sa SDDS_SetParameterFixedValue, SDDS_GetParameterAsDouble, SDDS_GetParameterAsString
3083 */
3084void *SDDS_GetFixedValueParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name, void *memory) {
3085 int32_t index, type, size;
3086 void *data;
3087 char s[SDDS_MAXLINE];
3088
3089 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetFixValueParameter"))
3090 return (NULL);
3091 if (!parameter_name) {
3092 SDDS_SetError("Unable to get parameter value--parameter name pointer is NULL (SDDS_GetFixedValueParameter)");
3093 return (NULL);
3094 }
3095 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
3096 SDDS_SetError("Unable to get parameter value--parameter name is unrecognized (SDDS_GetFixedValueParameter)");
3097 return (NULL);
3098 }
3099 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
3100 SDDS_SetError("Unable to get parameter value--parameter data type is invalid (SDDS_GetFixedValueParameter)");
3101 return (NULL);
3102 }
3103 size = SDDS_type_size[type - 1];
3104 if (memory)
3105 data = memory;
3106 else if (!(data = SDDS_Malloc(size))) {
3107 SDDS_SetError("Unable to get parameter value--parameter data size is invalid (SDDS_GetFixedValueParameter)");
3108 return (NULL);
3109 }
3110 strcpy(s, SDDS_dataset->layout.parameter_definition[index].fixed_value);
3111 if (!SDDS_ScanData(s, type, 0, data, 0, 1)) {
3112 SDDS_SetError("Unable to retrieve fixed-value paramter--scan failed (SDDS_GetFixedValueParameter)");
3113 return (NULL);
3114 }
3115 return (data);
3116}
3117
3118/**
3119 * @brief Extracts a matrix from a specified column in the current data table of an SDDS dataset.
3120 *
3121 * This function retrieves the data from the specified column and organizes it into a matrix with the given dimensions. The
3122 * data is arranged in either row-major or column-major order based on the `mode` parameter. The function allocates memory for
3123 * the matrix, which should be freed by the caller.
3124 *
3125 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3126 * @param column_name A null-terminated string specifying the name of the column from which to extract the matrix.
3127 * @param dimension1 The number of rows in the resulting matrix.
3128 * @param dimension2 The number of columns in the resulting matrix.
3129 * @param mode Specifies the data layout in the matrix. Use `SDDS_ROW_MAJOR_DATA` for row-major order or `SDDS_COLUMN_MAJOR_DATA`
3130 * for column-major order.
3131 *
3132 * @return On success, returns a pointer to the allocated matrix. The matrix is an array of pointers, where each pointer refers to a row
3133 * (for row-major) or a column (for column-major) in the matrix. On failure, returns `NULL` and sets an appropriate error message.
3134 *
3135 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, column not found, dimension mismatch, memory allocation failure).
3136 * @retval Non-NULL Pointer to the allocated matrix.
3137 *
3138 * @note The caller is responsible for freeing the allocated matrix and its contents.
3139 *
3140 * @sa SDDS_GetDoubleMatrixFromColumn, SDDS_GetMatrixFromRow, SDDS_AllocateMatrix
3141 */
3142void *SDDS_GetMatrixFromColumn(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t dimension1, int64_t dimension2, int32_t mode) {
3143 int32_t size, type, index;
3144 int64_t n_rows, i, j;
3145 void **data, *column;
3146 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetMatrixFromColumn"))
3147 return (NULL);
3148 if (!column_name) {
3149 SDDS_SetError("Unable to get matrix--column name is NULL (SDDS_GetMatrixFromColumn)");
3150 return (NULL);
3151 }
3152 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
3153 SDDS_SetError("Unable to get matrix--no rows selected (SDDS_GetMatrixFromColumn)");
3154 return (NULL);
3155 }
3156 if (n_rows != dimension1 * dimension2) {
3157 char s[1024];
3158 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);
3159 SDDS_SetError(s);
3160 return (NULL);
3161 }
3162 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0 || (type = SDDS_GetColumnType(SDDS_dataset, index)) < 0 || (size = SDDS_GetTypeSize(type)) <= 0) {
3163 SDDS_SetError("Unable to get matrix--column name is unrecognized (SDDS_GetMatrixFromColumn)");
3164 return (NULL);
3165 }
3166 if (!(column = SDDS_GetColumn(SDDS_dataset, column_name))) {
3167 SDDS_SetError("Unable to get matrix (SDDS_GetMatrixFromColumn)");
3168 return (NULL);
3169 }
3170 if (!(data = SDDS_AllocateMatrix(size, dimension1, dimension2))) {
3171 SDDS_SetError("Unable to allocate matrix (SDDS_GetMatrixFromColumn)");
3172 return (NULL);
3173 }
3174 if (mode & SDDS_ROW_MAJOR_DATA || !(mode & SDDS_COLUMN_MAJOR_DATA)) {
3175 for (i = 0; i < dimension1; i++)
3176 memcpy(data[i], (char *)column + i * dimension2 * size, dimension2 * size);
3177 } else {
3178 for (i = 0; i < dimension1; i++) {
3179 for (j = 0; j < dimension2; j++) {
3180 memcpy((char *)data[i] + size * j, (char *)column + (j * dimension1 + i) * size, size);
3181 }
3182 }
3183 }
3184
3185 free(column);
3186 return (data);
3187}
3188
3189/**
3190 * @brief Extracts a matrix of doubles from a specified column in the current data table of an SDDS dataset.
3191 *
3192 * This function retrieves the data from the specified column as `double` values and organizes it into a matrix with the given dimensions.
3193 * The data is arranged in either row-major or column-major order based on the `mode` parameter. The function allocates memory for
3194 * the matrix, which should be freed by the caller.
3195 *
3196 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3197 * @param column_name A null-terminated string specifying the name of the column from which to extract the matrix.
3198 * @param dimension1 The number of rows in the resulting matrix.
3199 * @param dimension2 The number of columns in the resulting matrix.
3200 * @param mode Specifies the data layout in the matrix. Use `SDDS_ROW_MAJOR_DATA` for row-major order or `SDDS_COLUMN_MAJOR_DATA`
3201 * for column-major order.
3202 *
3203 * @return On success, returns a pointer to the allocated matrix containing `double` values. The matrix is an array of pointers,
3204 * where each pointer refers to a row (for row-major) or a column (for column-major) in the matrix. On failure, returns `NULL`
3205 * and sets an appropriate error message.
3206 *
3207 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, column not found, dimension mismatch, memory allocation failure).
3208 * @retval Non-NULL Pointer to the allocated matrix containing `double` values.
3209 *
3210 * @note The caller is responsible for freeing the allocated matrix and its contents.
3211 *
3212 * @sa SDDS_GetMatrixFromColumn, SDDS_GetDoubleMatrixFromRow, SDDS_AllocateMatrix
3213 */
3214void *SDDS_GetDoubleMatrixFromColumn(SDDS_DATASET *SDDS_dataset, char *column_name, int64_t dimension1, int64_t dimension2, int32_t mode) {
3215 int32_t size, index;
3216 int64_t n_rows, i, j;
3217 void **data, *column;
3218 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetDoubleMatrixFromColumn"))
3219 return (NULL);
3220 if (!column_name) {
3221 SDDS_SetError("Unable to get matrix--column name is NULL (SDDS_GetDoubleMatrixFromColumn)");
3222 return (NULL);
3223 }
3224 if ((n_rows = SDDS_CountRowsOfInterest(SDDS_dataset)) <= 0) {
3225 SDDS_SetError("Unable to get matrix--no rows selected (SDDS_GetDoubleMatrixFromColumn)");
3226 return (NULL);
3227 }
3228 if (n_rows != dimension1 * dimension2) {
3229 char s[1024];
3230 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);
3231 SDDS_SetError(s);
3232 return (NULL);
3233 }
3234 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
3235 SDDS_SetError("Unable to get matrix--column name is unrecognized (SDDS_GetDoubleMatrixFromColumn)");
3236 return (NULL);
3237 }
3238 if (!(column = SDDS_GetColumnInDoubles(SDDS_dataset, column_name))) {
3239 SDDS_SetError("Unable to get matrix (SDDS_GetDoubleMatrixFromColumn)");
3240 return (NULL);
3241 }
3242 size = sizeof(double);
3243 if (!(data = SDDS_AllocateMatrix(size, dimension1, dimension2))) {
3244 SDDS_SetError("Unable to allocate matrix (SDDS_GetDoubleMatrixFromColumn)");
3245 return (NULL);
3246 }
3247 if (mode & SDDS_ROW_MAJOR_DATA || !(mode & SDDS_COLUMN_MAJOR_DATA)) {
3248 for (i = 0; i < dimension1; i++)
3249 memcpy(data[i], (char *)column + i * dimension2 * size, dimension2 * size);
3250 } else {
3251 for (i = 0; i < dimension1; i++) {
3252 for (j = 0; j < dimension2; j++) {
3253 memcpy((char *)data[i] + size * j, (char *)column + (j * dimension1 + i) * size, size);
3254 }
3255 }
3256 }
3257
3258 free(column);
3259 return (data);
3260}
3261
3262/**
3263 * @brief Sets the rows of interest in an SDDS dataset based on various selection criteria.
3264 *
3265 * This function marks rows in the provided SDDS dataset as "of interest" based on the specified selection criteria.
3266 * It supports multiple selection modes, allowing users to specify rows by an array of names, a single string containing
3267 * multiple names, a variadic list of names, or by matching a specific string with logical operations.
3268 *
3269 * **Calling Modes:**
3270 * - **SDDS_NAME_ARRAY**: Specify an array of names.
3271 * ```c
3272 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAME_ARRAY, int32_t n_entries, char **name);
3273 * ```
3274 * - **SDDS_NAMES_STRING**: Provide a single string containing multiple names separated by delimiters.
3275 * ```c
3276 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAMES_STRING, char *names);
3277 * ```
3278 * - **SDDS_NAME_STRINGS**: Pass multiple name strings, terminated by `NULL`.
3279 * ```c
3280 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAME_STRINGS, char *name1, char *name2, ..., NULL);
3281 * ```
3282 * - **SDDS_MATCH_STRING**: Match rows based on a single string and logical operations.
3283 * ```c
3284 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_MATCH_STRING, char *name, int32_t logic_mode);
3285 * ```
3286 *
3287 * Additionally, each of these modes has a case-insensitive variant prefixed with `SDDS_CI_` (e.g., `SDDS_CI_NAME_ARRAY`).
3288 *
3289 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3290 * @param selection_column A null-terminated string specifying the name of the column used for row selection.
3291 * This column must be of string type.
3292 * @param mode An integer representing the selection mode. Supported modes include:
3293 * - `SDDS_NAME_ARRAY`
3294 * - `SDDS_NAMES_STRING`
3295 * - `SDDS_NAME_STRINGS`
3296 * - `SDDS_MATCH_STRING`
3297 * - `SDDS_CI_NAME_ARRAY`
3298 * - `SDDS_CI_NAMES_STRING`
3299 * - `SDDS_CI_NAME_STRINGS`
3300 * - `SDDS_CI_MATCH_STRING`
3301 * @param ... Variable arguments corresponding to the selected mode:
3302 * - **SDDS_NAME_ARRAY** and **SDDS_CI_NAME_ARRAY**:
3303 * - `int32_t n_entries`: Number of names.
3304 * - `char **name`: Array of name strings.
3305 * - **SDDS_NAMES_STRING** and **SDDS_CI_NAMES_STRING**:
3306 * - `char *names`: Single string containing multiple names separated by delimiters.
3307 * - **SDDS_NAME_STRINGS** and **SDDS_CI_NAME_STRINGS**:
3308 * - `char *name1, char *name2, ..., NULL`: Multiple name strings terminated by `NULL`.
3309 * - **SDDS_MATCH_STRING** and **SDDS_CI_MATCH_STRING**:
3310 * - `char *name`: String to match.
3311 * - `int32_t logic_mode`: Logical operation mode.
3312 *
3313 * @return On success, returns the number of rows marked as "of interest". On failure, returns `-1` and sets an appropriate error message.
3314 *
3315 * @retval -1 Indicates that an error occurred (e.g., invalid dataset, unrecognized selection column, memory allocation failure, unknown mode).
3316 * @retval Non-negative Integer representing the count of rows marked as "of interest".
3317 *
3318 * @note
3319 * - The caller must ensure that the `selection_column` exists and is of string type in the dataset.
3320 * - For modes that allocate memory internally (e.g., `SDDS_NAMES_STRING`), the function handles memory management internally.
3321 *
3322 * @sa SDDS_MatchRowsOfInterest, SDDS_FilterRowsOfInterest, SDDS_DeleteUnsetRows
3323 */
3324int64_t SDDS_SetRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *selection_column, int32_t mode, ...)
3325/* This routine has 4 calling modes:
3326 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAME_ARRAY, int32_t n_entries, char **name)
3327 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAMES_STRING, char *names)
3328 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_NAME_STRINGS, char *name1, char *name2, ..., NULL )
3329 * SDDS_SetRowsOfInterest(&SDDS_dataset, selection_column, SDDS_MATCH_STRING, char *name, int32_t logic_mode)
3330 */
3331{
3332 va_list argptr;
3333 int32_t retval, type, index, n_names;
3334 int64_t i, j;
3335 char **name, *string, *match_string, *ptr;
3336 int32_t local_memory; /* (0,1,2) --> (none, pointer array, pointer array + strings) locally allocated */
3337 char buffer[SDDS_MAXLINE];
3338 int32_t logic, caseSensitive;
3339 int64_t count;
3340
3341 name = NULL;
3342 n_names = local_memory = logic = 0;
3343
3344 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetRowsOfInterest"))
3345 return (-1);
3346 va_start(argptr, mode);
3347 retval = 1;
3348 caseSensitive = 1;
3349 match_string = NULL;
3350 switch (mode) {
3351 case SDDS_CI_NAME_ARRAY:
3352 caseSensitive = 0;
3353 case SDDS_NAME_ARRAY:
3354 local_memory = 0;
3355 n_names = va_arg(argptr, int32_t);
3356 name = va_arg(argptr, char **);
3357 break;
3358 case SDDS_CI_NAMES_STRING:
3359 caseSensitive = 0;
3360 case SDDS_NAMES_STRING:
3361 local_memory = 2;
3362 n_names = 0;
3363 name = NULL;
3364 ptr = va_arg(argptr, char *);
3365 SDDS_CopyString(&string, ptr);
3366 while (SDDS_GetToken(string, buffer, SDDS_MAXLINE) > 0) {
3367 if (!(name = SDDS_Realloc(name, sizeof(*name) * (n_names + 1))) || !SDDS_CopyString(name + n_names, buffer)) {
3368 SDDS_SetError("Unable to process row selection--memory allocation failure (SDDS_SetRowsOfInterest)");
3369 retval = -1;
3370 break;
3371 }
3372 n_names++;
3373 }
3374 free(string);
3375 break;
3376 case SDDS_CI_NAME_STRINGS:
3377 caseSensitive = 0;
3378 case SDDS_NAME_STRINGS:
3379 local_memory = 1;
3380 n_names = 0;
3381 name = NULL;
3382 while ((string = va_arg(argptr, char *))) {
3383 if (!(name = SDDS_Realloc(name, sizeof(*name) * (n_names + 1)))) {
3384 SDDS_SetError("Unable to process row selection--memory allocation failure (SDDS_SetRowsOfInterest)");
3385 retval = -1;
3386 break;
3387 }
3388 name[n_names++] = string;
3389 }
3390 break;
3391 case SDDS_CI_MATCH_STRING:
3392 caseSensitive = 0;
3393 case SDDS_MATCH_STRING:
3394 local_memory = 0;
3395 n_names = 1;
3396 if ((string = va_arg(argptr, char *)))
3397 match_string = expand_ranges(string);
3398 logic = va_arg(argptr, int32_t);
3399 if (logic & SDDS_NOCASE_COMPARE)
3400 caseSensitive = 0;
3401 break;
3402 default:
3403 SDDS_SetError("Unable to process row selection--unknown mode (SDDS_SetRowsOfInterest)");
3404 retval = -1;
3405 break;
3406 }
3407
3408 va_end(argptr);
3409 if (retval != 1)
3410 return (-1);
3411
3412 if (mode != SDDS_MATCH_STRING && mode != SDDS_CI_MATCH_STRING) {
3413 int (*stringCompare)(const char *s1, const char *s2);
3414 if (caseSensitive)
3415 stringCompare = strcmp;
3416 else
3417 stringCompare = strcmp_ci;
3418 if ((index = SDDS_GetColumnIndex(SDDS_dataset, selection_column)) < 0) {
3419 SDDS_SetError("Unable to process row selection--unrecognized selection column name (SDDS_SetRowsOfInterest)");
3420 return (-1);
3421 }
3422 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) != SDDS_STRING) {
3423 SDDS_SetError("Unable to select rows--selection column is not string type (SDDS_SetRowsOfInterest)");
3424 return (-1);
3425 }
3426 if (n_names == 0) {
3427 SDDS_SetError("Unable to process row selection--no names in call (SDDS_SetRowsOfInterest)");
3428 return (-1);
3429 }
3430 for (j = 0; j < n_names; j++) {
3431 for (i = 0; i < SDDS_dataset->n_rows; i++) {
3432 if ((*stringCompare)(*((char **)SDDS_dataset->data[index] + i), name[j]) == 0)
3433 SDDS_dataset->row_flag[i] = 1;
3434 }
3435 }
3436 } else {
3437 if (selection_column) {
3438 int (*wildMatch)(char *string, char *template);
3439 if (caseSensitive)
3440 wildMatch = wild_match;
3441 else
3442 wildMatch = wild_match_ci;
3443 if (!match_string) {
3444 SDDS_SetError("Unable to select rows--no matching string given (SDDS_SetRowsOfInterest)");
3445 return (-1);
3446 }
3447 if ((index = SDDS_GetColumnIndex(SDDS_dataset, selection_column)) < 0) {
3448 free(match_string);
3449 SDDS_SetError("Unable to process row selection--unrecognized selection column name (SDDS_SetRowsOfInterest)");
3450 return (-1);
3451 }
3452 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) != SDDS_STRING) {
3453 free(match_string);
3454 SDDS_SetError("Unable to select rows--selection column is not string type (SDDS_SetRowsOfInterest)");
3455 return (-1);
3456 }
3457 for (i = 0; i < SDDS_dataset->n_rows; i++)
3458 SDDS_dataset->row_flag[i] = SDDS_Logic(SDDS_dataset->row_flag[i], (*wildMatch)(*((char **)SDDS_dataset->data[index] + i), match_string), logic);
3459 } else {
3460 for (i = 0; i < SDDS_dataset->n_rows; i++)
3461 SDDS_dataset->row_flag[i] = SDDS_Logic(SDDS_dataset->row_flag[i], 0, logic & ~(SDDS_AND | SDDS_OR));
3462 }
3463 }
3464
3465 if (local_memory == 2) {
3466 for (i = 0; i < n_names; i++)
3467 free(name[i]);
3468 }
3469 if (match_string)
3470 free(match_string);
3471 if (local_memory >= 1)
3472 free(name);
3473
3474 for (i = count = 0; i < SDDS_dataset->n_rows; i++)
3475 if (SDDS_dataset->row_flag[i])
3476 count++;
3477 return (count);
3478}
3479
3480/**
3481 * @brief Matches and marks rows of interest in an SDDS dataset based on label matching.
3482 *
3483 * This function marks rows in the provided SDDS dataset as "of interest" by matching labels in a specified column against a target label.
3484 * It supports both direct and indirect matching, as well as case-sensitive and case-insensitive comparisons, based on the provided logic flags.
3485 *
3486 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3487 * @param selection_column A null-terminated string specifying the name of the column used for label matching.
3488 * This column must be of string or character type.
3489 * @param label_to_match A null-terminated string specifying the label to match against the entries in the selection column.
3490 * If `logic` includes `SDDS_INDIRECT_MATCH`, this parameter is treated as the name of another column used for indirect matching.
3491 * @param logic An integer representing logical operation flags. Supported flags include:
3492 * - `SDDS_NOCASE_COMPARE`: Perform case-insensitive comparison.
3493 * - `SDDS_INDIRECT_MATCH`: Use indirect matching via another column.
3494 *
3495 * @return On success, returns the number of rows marked as "of interest". On failure, returns `-1` and sets an appropriate error message.
3496 *
3497 * @retval -1 Indicates that an error occurred (e.g., invalid dataset, unrecognized selection column, type mismatch, unrecognized indirect column).
3498 * @retval Non-negative Integer representing the count of rows marked as "of interest".
3499 *
3500 * @note
3501 * - The selection column must exist and be of string or character type.
3502 * - If using indirect matching (`SDDS_INDIRECT_MATCH`), the indirect column must exist and be of the same type as the selection column.
3503 *
3504 * @sa SDDS_SetRowsOfInterest, SDDS_FilterRowsOfInterest, SDDS_DeleteUnsetRows
3505 */
3506int64_t SDDS_MatchRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *selection_column, char *label_to_match, int32_t logic) {
3507 int32_t match, type, index, indirect_index;
3508 int64_t i, count;
3509 char *match_string;
3510#ifndef tolower
3511# if !defined(_MINGW)
3512 int tolower(int c);
3513# endif
3514#endif
3515
3516 index = type = indirect_index = 0;
3517
3518 match_string = NULL;
3519 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_MatchRowsOfInterest"))
3520 return (-1);
3521 if (selection_column) {
3522 if ((index = SDDS_GetColumnIndex(SDDS_dataset, selection_column)) < 0) {
3523 SDDS_SetError("Unable to select rows--column name is unrecognized (SDDS_MatchRowsOfInterest)");
3524 return (-1);
3525 }
3526 if ((type = SDDS_GetColumnType(SDDS_dataset, index)) != SDDS_STRING && type != SDDS_CHARACTER) {
3527 SDDS_SetError("Unable to select rows--selection column is not a string (SDDS_MatchRowsOfInterest)");
3528 return (-1);
3529 }
3530 if (!label_to_match) {
3531 SDDS_SetError("Unable to select rows--selection label is NULL (SDDS_MatchRowsOfInterest)");
3532 return (-1);
3533 }
3534 if (!(logic & SDDS_INDIRECT_MATCH))
3535 match_string = expand_ranges(label_to_match);
3536 else {
3537 if ((indirect_index = SDDS_GetColumnIndex(SDDS_dataset, label_to_match)) < 0) {
3538 SDDS_SetError("Unable to select rows--indirect column name is unrecognized (SDDS_MatchRowsOfInterest)");
3539 return (-1);
3540 }
3541 if (SDDS_GetColumnType(SDDS_dataset, indirect_index) != type) {
3542 SDDS_SetError("Unable to select rows--indirect column is not same type as main column (SDDS_MatchRowsOfInterest)");
3543 return (-1);
3544 }
3545 }
3546 }
3547 if (type == SDDS_STRING) {
3548 int (*stringCompare)(const char *s, const char *t);
3549 int (*wildMatch)(char *s, char *t);
3550 if (logic & SDDS_NOCASE_COMPARE) {
3551 stringCompare = strcmp_ci;
3552 wildMatch = wild_match_ci;
3553 } else {
3554 stringCompare = strcmp;
3555 wildMatch = wild_match;
3556 }
3557 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3558 if (selection_column)
3559 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);
3560 else
3561 match = SDDS_Logic(SDDS_dataset->row_flag[i], 0, logic & ~(SDDS_AND | SDDS_OR));
3562 if ((SDDS_dataset->row_flag[i] = match))
3563 count++;
3564 }
3565 } else {
3566 char c1, c2;
3567 c2 = 0;
3568 if (!(logic & SDDS_INDIRECT_MATCH))
3569 c2 = *match_string;
3570 if (logic & SDDS_NOCASE_COMPARE) {
3571 c2 = tolower(c2);
3572 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3573 c1 = tolower(*((char *)SDDS_dataset->data[index] + i));
3574 if (selection_column)
3575 match = SDDS_Logic(SDDS_dataset->row_flag[i], logic & SDDS_INDIRECT_MATCH ? c1 == tolower(*((char *)SDDS_dataset->data[indirect_index] + i)) : c1 == c2, logic);
3576 else
3577 match = SDDS_Logic(SDDS_dataset->row_flag[i], 0, logic & ~(SDDS_AND | SDDS_OR));
3578 if ((SDDS_dataset->row_flag[i] = match))
3579 count++;
3580 }
3581 } else {
3582 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3583 c1 = *((char *)SDDS_dataset->data[index] + i);
3584 if (selection_column)
3585 match = SDDS_Logic(SDDS_dataset->row_flag[i], logic & SDDS_INDIRECT_MATCH ? c1 == *((char *)SDDS_dataset->data[indirect_index] + i) : c1 == c2, logic);
3586 else
3587 match = SDDS_Logic(SDDS_dataset->row_flag[i], 0, logic & ~(SDDS_AND | SDDS_OR));
3588 if ((SDDS_dataset->row_flag[i] = match))
3589 count++;
3590 }
3591 }
3592 }
3593 if (match_string)
3594 free(match_string);
3595 return (count);
3596}
3597
3598/**
3599 * @brief Filters rows of interest in an SDDS dataset based on numeric ranges in a specified column.
3600 *
3601 * This function marks rows in the provided SDDS dataset as "of interest" if the values in the specified filter column fall
3602 * within the defined numeric range (`lower_limit` to `upper_limit`). Logical operations specified by the `logic` parameter
3603 * determine how the filtering interacts with existing row flags.
3604 *
3605 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3606 * @param filter_column A null-terminated string specifying the name of the column used for numeric filtering.
3607 * This column must be of a numeric type.
3608 * @param lower_limit The lower bound of the numeric range. Rows with values below this limit are excluded.
3609 * @param upper_limit The upper bound of the numeric range. Rows with values above this limit are excluded.
3610 * @param logic An integer representing logical operation flags. Supported flags include:
3611 * - `SDDS_NEGATE_PREVIOUS`: Invert the previous row flag.
3612 * - `SDDS_NEGATE_MATCH`: Invert the match result.
3613 * - `SDDS_AND`: Combine with existing row flags using logical AND.
3614 * - `SDDS_OR`: Combine with existing row flags using logical OR.
3615 * - `SDDS_NEGATE_EXPRESSION`: Invert the entire logical expression.
3616 *
3617 * @return On success, returns the number of rows marked as "of interest" after filtering. On failure, returns `-1` and sets an appropriate error message.
3618 *
3619 * @retval -1 Indicates that an error occurred (e.g., invalid dataset, unrecognized filter column, non-numeric filter column).
3620 * @retval Non-negative Integer representing the count of rows marked as "of interest".
3621 *
3622 * @note
3623 * - 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`).
3624 * - Logical flags determine how the filtering interacts with existing row flags. Multiple flags can be combined using bitwise OR.
3625 *
3626 * @sa SDDS_SetRowsOfInterest, SDDS_MatchRowsOfInterest, SDDS_DeleteUnsetRows
3627 */
3628int64_t SDDS_FilterRowsOfInterest(SDDS_DATASET *SDDS_dataset, char *filter_column, double lower_limit, double upper_limit, int32_t logic) {
3629 int32_t accept, type, index;
3630 int64_t i, count;
3631 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_FilterRowsOfInterest"))
3632 return (-1);
3633 if (!filter_column) {
3634 SDDS_SetError("Unable to filter rows--filter column name not given (SDDS_FilterRowsOfInterest)");
3635 return (-1);
3636 }
3637 if ((index = SDDS_GetColumnIndex(SDDS_dataset, filter_column)) < 0) {
3638 SDDS_SetError("Unable to filter rows--column name is unrecognized (SDDS_FilterRowsOfInterest)");
3639 return (-1);
3640 }
3641 switch (type = SDDS_GetColumnType(SDDS_dataset, index)) {
3642 case SDDS_SHORT:
3643 case SDDS_USHORT:
3644 case SDDS_LONG:
3645 case SDDS_ULONG:
3646 case SDDS_LONG64:
3647 case SDDS_ULONG64:
3648 case SDDS_FLOAT:
3649 case SDDS_DOUBLE:
3650 case SDDS_LONGDOUBLE:
3651 break;
3652 default:
3653 SDDS_SetError("Unable to filter rows--filter column is not a numeric type (SDDS_FilterRowsOfInterest)");
3654 return (-1);
3655 }
3656 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3657 if (logic & SDDS_NEGATE_PREVIOUS)
3658 SDDS_dataset->row_flag[i] = !SDDS_dataset->row_flag[i];
3659 accept = SDDS_ItemInsideWindow(SDDS_dataset->data[index], i, type, lower_limit, upper_limit);
3660 if (logic & SDDS_NEGATE_MATCH)
3661 accept = !accept;
3662 if (logic & SDDS_AND)
3663 accept = accept && SDDS_dataset->row_flag[i];
3664 else if (logic & SDDS_OR)
3665 accept = accept || SDDS_dataset->row_flag[i];
3666 if (logic & SDDS_NEGATE_EXPRESSION)
3667 accept = !accept;
3668 if ((SDDS_dataset->row_flag[i] = accept))
3669 count++;
3670 }
3671 return (count);
3672}
3673
3674/**
3675 * @brief Filters rows of interest in an SDDS dataset based on numeric scanning of a specified column.
3676 *
3677 * This function marks rows in the provided SDDS dataset as "of interest" based on whether the entries in the specified filter
3678 * column can be interpreted as valid numbers. It supports inversion of the filtering criterion through the `mode` parameter.
3679 *
3680 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3681 * @param filter_column A null-terminated string specifying the name of the column used for numeric scanning.
3682 * This column must not be of string type.
3683 * @param mode An unsigned integer representing mode flags. Supported flags include:
3684 * - `NUMSCANFILTER_INVERT`: Invert the filtering criterion (select rows where the entry is not a number).
3685 *
3686 * @return On success, returns the number of rows marked as "of interest" after filtering. On failure, returns `-1` and sets an appropriate error message.
3687 *
3688 * @retval -1 Indicates that an error occurred (e.g., invalid dataset, unrecognized filter column, filter column is of string type).
3689 * @retval Non-negative Integer representing the count of rows marked as "of interest".
3690 *
3691 * @note
3692 * - The filter column must exist and must not be of string type.
3693 * - The function uses `tokenIsNumber` to determine if an entry is a valid number.
3694 *
3695 * @sa SDDS_SetRowsOfInterest, SDDS_MatchRowsOfInterest, SDDS_DeleteUnsetRows
3696 */
3697int64_t SDDS_FilterRowsByNumScan(SDDS_DATASET *SDDS_dataset, char *filter_column, uint32_t mode) {
3698 int32_t accept, index;
3699 int64_t i, count;
3700 short invert;
3701 char *ptr;
3702
3703 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_FilterRowsByNumScan"))
3704 return (-1);
3705 if (!filter_column) {
3706 SDDS_SetError("Unable to filter rows--filter column name not given (SDDS_FilterRowsByNumScan)");
3707 return (-1);
3708 }
3709 if ((index = SDDS_GetColumnIndex(SDDS_dataset, filter_column)) < 0) {
3710 SDDS_SetError("Unable to filter rows--column name is unrecognized (SDDS_FilterRowsByNumScan)");
3711 return (-1);
3712 }
3713 switch (SDDS_GetColumnType(SDDS_dataset, index)) {
3714 case SDDS_SHORT:
3715 case SDDS_USHORT:
3716 case SDDS_LONG:
3717 case SDDS_ULONG:
3718 case SDDS_LONG64:
3719 case SDDS_ULONG64:
3720 case SDDS_FLOAT:
3721 case SDDS_DOUBLE:
3722 case SDDS_LONGDOUBLE:
3723 case SDDS_CHARACTER:
3724 SDDS_SetError("Unable to filter rows--filter column is not string type (SDDS_FilterRowsByNumScan)");
3725 return (-1);
3726 default:
3727 break;
3728 }
3729 invert = mode & NUMSCANFILTER_INVERT ? 1 : 0;
3730 for (i = count = 0; i < SDDS_dataset->n_rows; i++) {
3731 ptr = ((char **)(SDDS_dataset->data[index]))[i];
3732 accept = !invert;
3733 if (!tokenIsNumber(ptr))
3734 accept = invert;
3735 if ((SDDS_dataset->row_flag[i] = accept))
3736 count++;
3737 }
3738 return (count);
3739}
3740
3741/**
3742 * @brief Deletes rows from an SDDS dataset that are not marked as "of interest".
3743 *
3744 * This function removes all rows in the provided SDDS dataset that have not been flagged as "of interest" using prior selection functions.
3745 * It effectively compacts the dataset by retaining only the desired rows and updating the row count accordingly.
3746 *
3747 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3748 *
3749 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3750 *
3751 * @retval 1 Indicates that rows were successfully deleted.
3752 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, problem copying rows).
3753 *
3754 * @note
3755 * - This operation modifies the dataset in place by removing unset rows.
3756 * - It is recommended to perform row selection before calling this function to ensure that only desired rows are retained.
3757 *
3758 * @sa SDDS_SetRowsOfInterest, SDDS_MatchRowsOfInterest, SDDS_FilterRowsOfInterest
3759 */
3760int32_t SDDS_DeleteUnsetRows(SDDS_DATASET *SDDS_dataset) {
3761 int64_t i, j;
3762 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DeleteUnsetRows"))
3763 return (0);
3764
3765 for (i = j = 0; i < SDDS_dataset->n_rows; i++) {
3766 if (SDDS_dataset->row_flag[i]) {
3767 if (i != j) {
3768 SDDS_dataset->row_flag[j] = SDDS_dataset->row_flag[i];
3769 if (!SDDS_TransferRow(SDDS_dataset, j, i)) {
3770 SDDS_SetError("Unable to delete unset rows--problem copying row (SDDS_DeleteUnsetRows)");
3771 return (0);
3772 }
3773 }
3774 j++;
3775 }
3776 }
3777 SDDS_dataset->n_rows = j;
3778 return (1);
3779}
3780
3781/**
3782 * @brief Transfers data from a source row to a target row within an SDDS dataset.
3783 *
3784 * This function copies all column data from the specified source row to the target row in the provided SDDS dataset.
3785 * It handles both string and non-string data types appropriately, ensuring that memory is managed correctly for string entries.
3786 *
3787 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3788 * @param target The index of the target row where data will be copied to.
3789 * @param source The index of the source row from which data will be copied.
3790 *
3791 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3792 *
3793 * @retval 1 Indicates that the row transfer was successful.
3794 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, out-of-range indices, memory allocation failure, string copy failure).
3795 *
3796 * @note
3797 * - Both `target` and `source` must be valid row indices within the dataset.
3798 * - The function does not allocate or deallocate rows; it only copies data between existing rows.
3799 *
3800 * @sa SDDS_DeleteUnsetRows, SDDS_CopyColumn
3801 */
3802int32_t SDDS_TransferRow(SDDS_DATASET *SDDS_dataset, int64_t target, int64_t source) {
3803 int32_t size;
3804 int64_t i;
3805 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_TransferRow"))
3806 return (0);
3807 for (i = 0; i < SDDS_dataset->layout.n_columns; i++) {
3808 if (SDDS_dataset->layout.column_definition[i].type != SDDS_STRING) {
3809 size = SDDS_type_size[SDDS_dataset->layout.column_definition[i].type - 1];
3810 memcpy((char *)SDDS_dataset->data[i] + target * size, (char *)SDDS_dataset->data[i] + source * size, size);
3811 } else {
3812 if (((char ***)SDDS_dataset->data)[i][target])
3813 free(((char ***)SDDS_dataset->data)[i][target]);
3814 ((char ***)SDDS_dataset->data)[i][target] = NULL;
3815 if (!SDDS_CopyString(((char ***)SDDS_dataset->data)[i] + target, ((char ***)SDDS_dataset->data)[i][source]))
3816 return ((int32_t)0);
3817 }
3818 }
3819 return (1);
3820}
3821
3822/**
3823 * @brief Deletes a specified column from an SDDS dataset.
3824 *
3825 * **Note:** This function is currently non-functional and will abort execution if called.
3826 *
3827 * This function is intended to remove a column identified by `column_name` from the provided SDDS dataset.
3828 * It handles the reordering of remaining columns and updates the dataset's layout accordingly. However, as indicated
3829 * by the current implementation, the function is not operational and will terminate the program when invoked.
3830 *
3831 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3832 * @param column_name A null-terminated string specifying the name of the column to be deleted.
3833 *
3834 * @return This function does not return as it aborts execution. If it were functional, it would return `1` on success
3835 * and `0` on failure.
3836 *
3837 * @warning
3838 * - **Currently Non-Functional:** The function will terminate the program with an error message when called.
3839 *
3840 * @todo
3841 * - Implement the functionality to delete a column without aborting.
3842 *
3843 * @sa SDDS_DeleteUnsetColumns, SDDS_CopyColumn
3844 */
3845int32_t SDDS_DeleteColumn(SDDS_DATASET *SDDS_dataset, char *column_name) {
3846 int32_t index;
3847 int64_t i, j;
3848
3849 SDDS_Bomb("SDDS_DeleteColumn is presently not functional.");
3850
3851 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DeleteColumn"))
3852 return (0);
3853 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
3854 SDDS_SetError("Unable to delete column--unrecognized column name (SDDS_DeleteColumn)");
3855 return (0);
3856 }
3857 for (i = index + 1; i < SDDS_dataset->layout.n_columns; i++) {
3858 if (!SDDS_CopyColumn(SDDS_dataset, i - 1, i)) {
3859 SDDS_SetError("Unable to delete column--error copying column (SDDS_DeleteColumn)");
3860 return (0);
3861 }
3862 for (j = 0; j < SDDS_dataset->n_of_interest; j++)
3863 if (SDDS_dataset->column_order[j] == index) {
3864 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));
3865 SDDS_dataset->n_of_interest--;
3866 } else if (SDDS_dataset->column_order[j] > index)
3867 SDDS_dataset->column_order[j] -= 1;
3868 }
3869 if ((SDDS_dataset->layout.n_columns -= 1) == 0)
3870 SDDS_dataset->n_rows = 0;
3871 return (1);
3872}
3873
3874/**
3875 * @brief Deletes all columns from an SDDS dataset that are not marked as "of interest".
3876 *
3877 * This function iterates through all columns in the provided SDDS dataset and removes those that have not been flagged as "of interest".
3878 * It ensures that only desired columns are retained, updating the dataset's layout and column order accordingly.
3879 *
3880 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3881 *
3882 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3883 *
3884 * @retval 1 Indicates that columns were successfully deleted.
3885 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, failure to delete a column).
3886 *
3887 * @note
3888 * - This operation modifies the dataset in place by removing unset columns.
3889 * - It is recommended to perform column selection before calling this function to ensure that only desired columns are retained.
3890 *
3891 * @sa SDDS_SetColumnsOfInterest, SDDS_DeleteColumn, SDDS_CopyColumn
3892 */
3894 int64_t i;
3895 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DeleteUnsetColumns"))
3896 return (0);
3897 for (i = 0; i < SDDS_dataset->layout.n_columns; i++)
3898 if (!SDDS_dataset->column_flag[i]) {
3899 if (!SDDS_DeleteColumn(SDDS_dataset, SDDS_dataset->layout.column_definition[i].name))
3900 return (0);
3901 else
3902 i--;
3903 }
3904 return (1);
3905}
3906
3907/**
3908 * @brief Copies data from a source column to a target column within an SDDS dataset.
3909 *
3910 * This function duplicates the data from the specified source column to the target column in the provided SDDS dataset.
3911 * It handles both string and non-string data types appropriately, ensuring that memory is managed correctly for string entries.
3912 *
3913 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3914 * @param target The index of the target column where data will be copied to.
3915 * @param source The index of the source column from which data will be copied.
3916 *
3917 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3918 *
3919 * @retval 1 Indicates that the column copy was successful.
3920 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, out-of-range indices, memory allocation failure, string copy failure).
3921 *
3922 * @note
3923 * - Both `target` and `source` must be valid column indices within the dataset.
3924 * - The function does not handle the allocation of new columns; it assumes that the target column already exists.
3925 *
3926 * @sa SDDS_DeleteColumn, SDDS_DeleteUnsetColumns, SDDS_TransferRow
3927 */
3928int32_t SDDS_CopyColumn(SDDS_DATASET *SDDS_dataset, int32_t target, int32_t source) {
3929 COLUMN_DEFINITION *cd_target, *cd_source;
3930 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_CopyColumn"))
3931 return (0);
3932 if (target < 0 || source < 0 || target >= SDDS_dataset->layout.n_columns || source >= SDDS_dataset->layout.n_columns) {
3933 SDDS_SetError("Unable to copy column--target or source index out of range (SDDS_CopyColumn");
3934 return (0);
3935 }
3936 cd_target = SDDS_dataset->layout.column_definition + target;
3937 cd_source = SDDS_dataset->layout.column_definition + source;
3938 SDDS_dataset->column_flag[target] = SDDS_dataset->column_flag[source];
3939 if (SDDS_dataset->n_rows_allocated) {
3940 if (cd_target->type != cd_source->type) {
3941 if (!(SDDS_dataset->data[target] = SDDS_Realloc(SDDS_dataset->data[target], SDDS_type_size[cd_source->type - 1] * SDDS_dataset->n_rows_allocated))) {
3942 SDDS_SetError("Unable to copy column--memory allocation failure (SDDS_CopyColumn)");
3943 return (0);
3944 }
3945 }
3946 if (cd_source->type != SDDS_STRING)
3947 memcpy(SDDS_dataset->data[target], SDDS_dataset->data[source], SDDS_type_size[cd_source->type - 1] * SDDS_dataset->n_rows);
3948 else if (!SDDS_CopyStringArray(SDDS_dataset->data[target], SDDS_dataset->data[source], SDDS_dataset->n_rows)) {
3949 SDDS_SetError("Unable to copy column--string copy failure (SDDS_CopyColumn)");
3950 return (0);
3951 }
3952 }
3953 memcpy((char *)cd_target, (char *)cd_source, sizeof(*cd_target));
3954 return (1);
3955}
3956
3957/**
3958 * @brief Deletes a specified parameter from an SDDS dataset.
3959 *
3960 * This function removes a parameter identified by `parameter_name` from the provided SDDS dataset.
3961 * It shifts all subsequent parameters up to fill the gap left by the deleted parameter and updates the
3962 * dataset's parameter count accordingly.
3963 *
3964 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
3965 * @param parameter_name A null-terminated string specifying the name of the parameter to be deleted.
3966 *
3967 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
3968 *
3969 * @retval 1 Indicates that the parameter was successfully deleted.
3970 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, unrecognized parameter name, error copying parameters).
3971 *
3972 * @note
3973 * - This operation modifies the dataset by removing the specified parameter.
3974 * - It is recommended to ensure that the parameter to be deleted is not essential for further operations.
3975 *
3976 * @sa SDDS_CopyParameter, SDDS_DeleteUnsetParameters
3977 */
3978int32_t SDDS_DeleteParameter(SDDS_DATASET *SDDS_dataset, char *parameter_name) {
3979 int32_t i, index;
3980 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_DeleteParameter"))
3981 return (0);
3982 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
3983 SDDS_SetError("Unable to delete parameter--unrecognized parameter name (SDDS_DeleteParameter)");
3984 return (0);
3985 }
3986 for (i = index + 1; i < SDDS_dataset->layout.n_parameters; i++) {
3987 if (!SDDS_CopyParameter(SDDS_dataset, i - 1, i)) {
3988 SDDS_SetError("Unable to delete parameter--error copying parameter (SDDS_DeleteParameter)");
3989 return (0);
3990 }
3991 }
3992 SDDS_dataset->layout.n_parameters -= 1;
3993 return (1);
3994}
3995
3996/**
3997 * @brief Copies a parameter from a source index to a target index within an SDDS dataset.
3998 *
3999 * This function duplicates the parameter data from the source index to the target index in the provided SDDS dataset.
4000 * It handles both string and non-string data types appropriately, ensuring that memory is managed correctly for string entries.
4001 *
4002 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4003 * @param target The index of the target parameter where data will be copied to.
4004 * @param source The index of the source parameter from which data will be copied.
4005 *
4006 * @return On success, returns `1`. On failure, returns `0` and sets an appropriate error message.
4007 *
4008 * @retval 1 Indicates that the parameter copy was successful.
4009 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, out-of-range indices, memory allocation failure, string copy failure).
4010 *
4011 * @note
4012 * - Both `target` and `source` must be valid parameter indices within the dataset.
4013 * - The function assumes that the target parameter already exists and is intended to be overwritten.
4014 *
4015 * @sa SDDS_DeleteParameter, SDDS_CopyArray
4016 */
4017int32_t SDDS_CopyParameter(SDDS_DATASET *SDDS_dataset, int32_t target, int32_t source) {
4018 PARAMETER_DEFINITION *cd_target, *cd_source;
4019 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_CopyParameter"))
4020 return (0);
4021 if (target < 0 || source < 0 || target >= SDDS_dataset->layout.n_parameters || source >= SDDS_dataset->layout.n_parameters) {
4022 SDDS_SetError("Unable to copy parameter--target or source index out of range (SDDS_CopyParameter");
4023 return (0);
4024 }
4025 cd_target = SDDS_dataset->layout.parameter_definition + target;
4026 cd_source = SDDS_dataset->layout.parameter_definition + source;
4027 if (SDDS_dataset->parameter) {
4028 if (cd_target->type != cd_source->type) {
4029 if (!(SDDS_dataset->parameter[target] = SDDS_Realloc(SDDS_dataset->data[target], SDDS_type_size[cd_source->type - 1]))) {
4030 SDDS_SetError("Unable to copy parameter--memory allocation failure (SDDS_CopyParameter)");
4031 return (0);
4032 }
4033 }
4034 if (cd_source->type != SDDS_STRING)
4035 memcpy(SDDS_dataset->parameter[target], SDDS_dataset->parameter[source], SDDS_type_size[cd_source->type - 1]);
4036 else if (!SDDS_CopyStringArray(SDDS_dataset->parameter[target], SDDS_dataset->parameter[source], 1)) {
4037 SDDS_SetError("Unable to copy parameter--string copy failure (SDDS_CopyParameter)");
4038 return (0);
4039 }
4040 }
4041 memcpy((char *)cd_target, (char *)cd_source, sizeof(*cd_target));
4042 return (1);
4043}
4044
4045/**
4046 * @brief Checks whether a data item is within a specified numeric window.
4047 *
4048 * This function determines if the data item at the given index within the data array falls within the range defined by
4049 * `lower_limit` and `upper_limit`. It handles various numeric data types and ensures that the value is neither NaN nor infinity.
4050 *
4051 * @param data Pointer to the data array.
4052 * @param index The index of the item within the data array to be checked.
4053 * @param type The data type of the item. Supported types include:
4054 * - `SDDS_SHORT`
4055 * - `SDDS_USHORT`
4056 * - `SDDS_LONG`
4057 * - `SDDS_ULONG`
4058 * - `SDDS_LONG64`
4059 * - `SDDS_ULONG64`
4060 * - `SDDS_FLOAT`
4061 * - `SDDS_DOUBLE`
4062 * - `SDDS_LONGDOUBLE`
4063 * @param lower_limit The lower bound of the numeric window.
4064 * @param upper_limit The upper bound of the numeric window.
4065 *
4066 * @return Returns `1` if the item is within the window and valid, otherwise returns `0`.
4067 *
4068 * @retval 1 Indicates that the item is within the specified numeric window and is a valid number.
4069 * @retval 0 Indicates that the item is outside the specified window, is NaN, is infinite, or the data type is non-numeric.
4070 *
4071 * @note
4072 * - The function sets an error message if the data type is non-numeric.
4073 * - It is essential to ensure that the `data` array is properly initialized and contains valid data before calling this function.
4074 *
4075 * @sa SDDS_FilterRowsOfInterest, SDDS_GetParameterAsDouble
4076 */
4077int32_t SDDS_ItemInsideWindow(void *data, int64_t index, int32_t type, double lower_limit, double upper_limit) {
4078 short short_val;
4079 unsigned short ushort_val;
4080 int32_t long_val;
4081 uint32_t ulong_val;
4082 int64_t long64_val;
4083 uint64_t ulong64_val;
4084 long double ldouble_val;
4085 double double_val;
4086 float float_val;
4087
4088 switch (type) {
4089 case SDDS_SHORT:
4090 if ((short_val = *((short *)data + index)) < lower_limit || short_val > upper_limit)
4091 return (0);
4092 return (1);
4093 case SDDS_USHORT:
4094 if ((ushort_val = *((unsigned short *)data + index)) < lower_limit || ushort_val > upper_limit)
4095 return (0);
4096 return (1);
4097 case SDDS_LONG:
4098 if ((long_val = *((int32_t *)data + index)) < lower_limit || long_val > upper_limit)
4099 return (0);
4100 return (1);
4101 case SDDS_ULONG:
4102 if ((ulong_val = *((uint32_t *)data + index)) < lower_limit || ulong_val > upper_limit)
4103 return (0);
4104 return (1);
4105 case SDDS_LONG64:
4106 if ((long64_val = *((int64_t *)data + index)) < lower_limit || long64_val > upper_limit)
4107 return (0);
4108 return (1);
4109 case SDDS_ULONG64:
4110 if ((ulong64_val = *((uint64_t *)data + index)) < lower_limit || ulong64_val > upper_limit)
4111 return (0);
4112 return (1);
4113 case SDDS_FLOAT:
4114 if ((float_val = *((float *)data + index)) < lower_limit || float_val > upper_limit)
4115 return (0);
4116 if (isnan(float_val) || isinf(float_val))
4117 return 0;
4118 return (1);
4119 case SDDS_DOUBLE:
4120 if ((double_val = *((double *)data + index)) < lower_limit || double_val > upper_limit)
4121 return 0;
4122 if (isnan(double_val) || isinf(double_val))
4123 return 0;
4124 return (1);
4125 case SDDS_LONGDOUBLE:
4126 if ((ldouble_val = *((long double *)data + index)) < lower_limit || ldouble_val > upper_limit)
4127 return 0;
4128 if (isnan(ldouble_val) || isinf(ldouble_val))
4129 return 0;
4130 return (1);
4131 default:
4132 SDDS_SetError("Unable to complete window check--item type is non-numeric (SDDS_ItemInsideWindow)");
4133 return (0);
4134 }
4135}
4136
4137/**
4138 * @brief Applies logical operations to determine the new state of a row flag based on previous and current match conditions.
4139 *
4140 * This function evaluates logical conditions between a previous flag (`previous`) and a current match flag (`match`) based on the
4141 * provided `logic` flags. It supports various logical operations such as AND, OR, negation of previous flags, and negation of match results.
4142 *
4143 * @param previous The previous state of the row flag (typically `0` or `1`).
4144 * @param match The current match result to be combined with the previous flag.
4145 * @param logic An unsigned integer representing logical operation flags. Supported flags include:
4146 * - `SDDS_0_PREVIOUS`: Set the previous flag to `0`.
4147 * - `SDDS_1_PREVIOUS`: Set the previous flag to `1`.
4148 * - `SDDS_NEGATE_PREVIOUS`: Negate the previous flag.
4149 * - `SDDS_NEGATE_MATCH`: Negate the current match result.
4150 * - `SDDS_AND`: Perform a logical AND between the previous flag and the match result.
4151 * - `SDDS_OR`: Perform a logical OR between the previous flag and the match result.
4152 * - `SDDS_NEGATE_EXPRESSION`: Negate the final logical expression result.
4153 *
4154 * @return Returns the result of the logical operation as an integer (`0` or `1`).
4155 *
4156 * @retval 1 Indicates that the final logical condition evaluates to true.
4157 * @retval 0 Indicates that the final logical condition evaluates to false.
4158 *
4159 * @note
4160 * - Multiple logic flags can be combined using bitwise OR to perform complex logical operations.
4161 * - The order of operations follows the precedence defined within the function implementation.
4162 *
4163 * @sa SDDS_SetRowsOfInterest, SDDS_MatchRowsOfInterest
4164 */
4165int32_t SDDS_Logic(int32_t previous, int32_t match, uint32_t logic) {
4166 if (logic & SDDS_0_PREVIOUS)
4167 previous = 0;
4168 else if (logic & SDDS_1_PREVIOUS)
4169 previous = 1;
4170 if (logic & SDDS_NEGATE_PREVIOUS)
4171 previous = !previous;
4172 if (logic & SDDS_NEGATE_MATCH)
4173 match = !match;
4174 if (logic & SDDS_AND)
4175 match = match && previous;
4176 else if (logic & SDDS_OR)
4177 match = match || previous;
4178 else
4179 match = previous;
4180 if (logic & SDDS_NEGATE_EXPRESSION)
4181 match = !match;
4182 return (match);
4183}
4184
4185/**
4186 * @brief Retrieves an array from the current data table of an SDDS dataset.
4187 *
4188 * This function returns a pointer to a `SDDS_ARRAY` structure containing the data and other information about a specified array
4189 * within the current data table of an SDDS dataset. The function can either populate a provided `SDDS_ARRAY` structure or allocate
4190 * a new one if `memory` is `NULL`.
4191 *
4192 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4193 * @param array_name A null-terminated string specifying the name of the SDDS array to retrieve.
4194 * @param memory Optional pointer to an existing `SDDS_ARRAY` structure where the array information will be stored. If `NULL`,
4195 * a new `SDDS_ARRAY` structure is allocated and returned.
4196 *
4197 * @return On success, returns a pointer to a `SDDS_ARRAY` structure containing the array data and metadata. If `memory` is not `NULL`,
4198 * the function populates the provided structure. On failure, returns `NULL` and sets an appropriate error message.
4199 *
4200 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, memory allocation failure).
4201 * @retval Non-NULL Pointer to a `SDDS_ARRAY` structure containing the array data and metadata.
4202 *
4203 * @note
4204 * - The caller is responsible for freeing the allocated memory for the `SDDS_ARRAY` structure if `memory` is `NULL`.
4205 * - The `definition` field in the returned structure points to the internal copy of the array definition.
4206 *
4207 * @sa SDDS_GetArrayInDoubles, SDDS_GetArrayInString, SDDS_GetArrayInLong
4208 */
4209SDDS_ARRAY *SDDS_GetArray(SDDS_DATASET *SDDS_dataset, char *array_name, SDDS_ARRAY *memory) {
4210 int32_t index, type, size;
4211 SDDS_ARRAY *copy, *original;
4212
4213 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetArray"))
4214 return (NULL);
4215 if (!array_name) {
4216 SDDS_SetError("Unable to get array--array name pointer is NULL (SDDS_GetArray)");
4217 return (NULL);
4218 }
4219 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4220 SDDS_SetError("Unable to get array--array name is unrecognized (SDDS_GetArray)");
4221 return (NULL);
4222 }
4223 if (memory)
4224 copy = memory;
4225 else if (!(copy = (SDDS_ARRAY *)calloc(1, sizeof(*copy)))) {
4226 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArray)");
4227 return (NULL);
4228 }
4229 original = SDDS_dataset->array + index;
4230 if (copy->definition && !SDDS_FreeArrayDefinition(copy->definition)) {
4231 SDDS_SetError("Unable to get array--array definition corrupted (SDDS_GetArray)");
4232 return (NULL);
4233 }
4234 if (!SDDS_CopyArrayDefinition(&copy->definition, original->definition)) {
4235 SDDS_SetError("Unable to get array--array definition missing (SDDS_GetArray)");
4236 return (NULL);
4237 }
4238 type = copy->definition->type;
4239 size = SDDS_type_size[copy->definition->type - 1];
4240 if (!(copy->dimension = SDDS_Realloc(copy->dimension, sizeof(*copy->dimension) * copy->definition->dimensions))) {
4241 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArray)");
4242 return (NULL);
4243 }
4244 memcpy((void *)copy->dimension, (void *)original->dimension, sizeof(*copy->dimension) * copy->definition->dimensions);
4245 if (!(copy->elements = original->elements))
4246 return (copy);
4247 if (!(copy->data = SDDS_Realloc(copy->data, size * original->elements))) {
4248 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArray)");
4249 return (NULL);
4250 }
4251
4252 if (copy->definition->type != SDDS_STRING)
4253 memcpy(copy->data, original->data, size * copy->elements);
4254 else if (!SDDS_CopyStringArray((char **)copy->data, (char **)original->data, original->elements)) {
4255 SDDS_SetError("Unable to get array--string copy failure (SDDS_GetArray)");
4256 return (NULL);
4257 }
4258
4259 /* should free existing subpointers here, but probably not worth the trouble */
4260 if (copy->pointer && copy->definition->dimensions != 1)
4261 free(copy->pointer);
4262 if (!(copy->pointer = SDDS_MakePointerArray(copy->data, type, copy->definition->dimensions, copy->dimension))) {
4263 SDDS_SetError("Unable to get array--couldn't make pointer array (SDDS_GetArray)");
4264 return (NULL);
4265 }
4266 return (copy);
4267}
4268
4269/**
4270 * @brief Retrieves an array from the current data table of an SDDS dataset and converts its elements to strings.
4271 *
4272 * This function extracts the specified array from the provided SDDS dataset and converts each of its elements into a null-terminated
4273 * string representation. The conversion respects the data type of the array elements, ensuring accurate string formatting.
4274 *
4275 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4276 * @param array_name A null-terminated string specifying the name of the SDDS array to retrieve and convert.
4277 * @param values Pointer to an integer where the number of elements in the array will be stored upon successful completion.
4278 *
4279 * @return On success, returns a pointer to an array of null-terminated strings (`char **`). Each string represents an element of the
4280 * original SDDS array. On failure, returns `NULL` and sets an appropriate error message.
4281 *
4282 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, memory allocation failure).
4283 * @retval Non-NULL Pointer to an array of strings representing the SDDS array elements.
4284 *
4285 * @note
4286 * - The caller is responsible for freeing each string in the returned array as well as the array itself.
4287 * - The function handles different data types, including numeric types and strings, ensuring proper formatting for each type.
4288 *
4289 * @sa SDDS_GetArray, SDDS_GetArrayInDoubles, SDDS_GetArrayInLong
4290 */
4291char **SDDS_GetArrayInString(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t *values) {
4292 int32_t index, type, i, elements;
4293 SDDS_ARRAY *original;
4294 char **data;
4295 char buffer[SDDS_MAXLINE];
4296 void *rawData;
4297
4298 *values = 0;
4299 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetArrayInString"))
4300 return (NULL);
4301 if (!array_name) {
4302 SDDS_SetError("Unable to get array--array name pointer is NULL (SDDS_GetArrayInString)");
4303 return (NULL);
4304 }
4305 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4306 SDDS_SetError("Unable to get array--array name is unrecognized (SDDS_GetArrayInString)");
4307 return (NULL);
4308 }
4309 original = SDDS_dataset->array + index;
4310 type = original->definition->type;
4311 elements = original->elements;
4312 if (!(data = (char **)SDDS_Malloc(sizeof(*data) * elements))) {
4313 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArrayInString)");
4314 return (NULL);
4315 }
4316 rawData = original->data;
4317 switch (type) {
4318 case SDDS_LONGDOUBLE:
4319 for (i = 0; i < elements; i++) {
4320 if (LDBL_DIG == 18) {
4321 sprintf(buffer, "%22.18Le", ((long double *)rawData)[i]);
4322 } else {
4323 sprintf(buffer, "%22.15Le", ((long double *)rawData)[i]);
4324 }
4325 SDDS_CopyString(&data[i], buffer);
4326 }
4327 break;
4328 case SDDS_DOUBLE:
4329 for (i = 0; i < elements; i++) {
4330 sprintf(buffer, "%22.15le", ((double *)rawData)[i]);
4331 SDDS_CopyString(&data[i], buffer);
4332 }
4333 break;
4334 case SDDS_FLOAT:
4335 for (i = 0; i < elements; i++) {
4336 sprintf(buffer, "%15.8e", ((float *)rawData)[i]);
4337 SDDS_CopyString(&data[i], buffer);
4338 }
4339 break;
4340 case SDDS_LONG64:
4341 for (i = 0; i < elements; i++) {
4342 sprintf(buffer, "%" PRId64, ((int64_t *)rawData)[i]);
4343 SDDS_CopyString(&data[i], buffer);
4344 }
4345 break;
4346 case SDDS_ULONG64:
4347 for (i = 0; i < elements; i++) {
4348 sprintf(buffer, "%" PRIu64, ((uint64_t *)rawData)[i]);
4349 SDDS_CopyString(&data[i], buffer);
4350 }
4351 break;
4352 case SDDS_LONG:
4353 for (i = 0; i < elements; i++) {
4354 sprintf(buffer, "%" PRId32, ((int32_t *)rawData)[i]);
4355 SDDS_CopyString(&data[i], buffer);
4356 }
4357 break;
4358 case SDDS_ULONG:
4359 for (i = 0; i < elements; i++) {
4360 sprintf(buffer, "%" PRIu32, ((uint32_t *)rawData)[i]);
4361 SDDS_CopyString(&data[i], buffer);
4362 }
4363 break;
4364 case SDDS_SHORT:
4365 for (i = 0; i < elements; i++) {
4366 sprintf(buffer, "%hd", ((short *)rawData)[i]);
4367 SDDS_CopyString(&data[i], buffer);
4368 }
4369 break;
4370 case SDDS_USHORT:
4371 for (i = 0; i < elements; i++) {
4372 sprintf(buffer, "%hu", ((unsigned short *)rawData)[i]);
4373 SDDS_CopyString(&data[i], buffer);
4374 }
4375 break;
4376 case SDDS_CHARACTER:
4377 for (i = 0; i < elements; i++) {
4378 sprintf(buffer, "%c", ((char *)rawData)[i]);
4379 SDDS_CopyString(&data[i], buffer);
4380 }
4381 break;
4382 case SDDS_STRING:
4383 for (i = 0; i < elements; i++) {
4384 SDDS_CopyString(&data[i], ((char **)rawData)[i]);
4385 }
4386 break;
4387 }
4388 *values = elements;
4389 return data;
4390}
4391
4392/**
4393 * @brief Retrieves an array from the current data table of an SDDS dataset and converts its elements to doubles.
4394 *
4395 * This function extracts the specified array from the provided SDDS dataset and converts each of its elements into a `double` value.
4396 * It ensures that the array is of a compatible numeric type before performing the conversion.
4397 *
4398 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4399 * @param array_name A null-terminated string specifying the name of the SDDS array to retrieve and convert.
4400 * @param values Pointer to an integer where the number of elements in the array will be stored upon successful completion.
4401 *
4402 * @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.
4403 *
4404 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, incompatible array type, memory allocation failure).
4405 * @retval Non-NULL Pointer to an array of `double` values representing the SDDS array elements.
4406 *
4407 * @note
4408 * - The caller is responsible for freeing the allocated memory for the returned `double` array.
4409 * - The function does not handle string-type arrays; attempting to retrieve a string array will result in an error.
4410 *
4411 * @sa SDDS_GetArray, SDDS_GetArrayInString, SDDS_GetArrayInLong
4412 */
4413double *SDDS_GetArrayInDoubles(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t *values) {
4414 int32_t index, type, i, elements;
4415 SDDS_ARRAY *original;
4416 double *data;
4417 void *rawData;
4418
4419 *values = 0;
4420 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetArrayInDoubles"))
4421 return (NULL);
4422 if (!array_name) {
4423 SDDS_SetError("Unable to get array--array name pointer is NULL (SDDS_GetArrayInDoubles)");
4424 return (NULL);
4425 }
4426 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4427 SDDS_SetError("Unable to get array--array name is unrecognized (SDDS_GetArrayInDoubles)");
4428 return (NULL);
4429 }
4430 original = SDDS_dataset->array + index;
4431 if ((type = original->definition->type) == SDDS_STRING) {
4432 SDDS_SetError("Unable to get array--string type (SDDS_GetArrayInDoubles)");
4433 return (NULL);
4434 }
4435 elements = original->elements;
4436 if (!(data = SDDS_Malloc(sizeof(*data) * elements))) {
4437 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArrayInDoubles)");
4438 return (NULL);
4439 }
4440 rawData = original->data;
4441 switch (type) {
4442 case SDDS_LONGDOUBLE:
4443 for (i = 0; i < elements; i++) {
4444 data[i] = ((long double *)rawData)[i];
4445 }
4446 break;
4447 case SDDS_DOUBLE:
4448 for (i = 0; i < elements; i++) {
4449 data[i] = ((double *)rawData)[i];
4450 }
4451 break;
4452 case SDDS_FLOAT:
4453 for (i = 0; i < elements; i++) {
4454 data[i] = ((float *)rawData)[i];
4455 }
4456 break;
4457 case SDDS_LONG64:
4458 for (i = 0; i < elements; i++) {
4459 data[i] = ((int64_t *)rawData)[i];
4460 }
4461 break;
4462 case SDDS_ULONG64:
4463 for (i = 0; i < elements; i++) {
4464 data[i] = ((uint64_t *)rawData)[i];
4465 }
4466 break;
4467 case SDDS_LONG:
4468 for (i = 0; i < elements; i++) {
4469 data[i] = ((int32_t *)rawData)[i];
4470 }
4471 break;
4472 case SDDS_ULONG:
4473 for (i = 0; i < elements; i++) {
4474 data[i] = ((uint32_t *)rawData)[i];
4475 }
4476 break;
4477 case SDDS_SHORT:
4478 for (i = 0; i < elements; i++) {
4479 data[i] = ((short *)rawData)[i];
4480 }
4481 break;
4482 case SDDS_USHORT:
4483 for (i = 0; i < elements; i++) {
4484 data[i] = ((unsigned short *)rawData)[i];
4485 }
4486 break;
4487 case SDDS_CHARACTER:
4488 for (i = 0; i < elements; i++) {
4489 data[i] = ((char *)rawData)[i];
4490 }
4491 break;
4492 }
4493 *values = elements;
4494 return data;
4495}
4496
4497/**
4498 * @brief Retrieves an array from the current data table of an SDDS dataset and converts its elements to 32-bit integers.
4499 *
4500 * This function extracts the specified array from the provided SDDS dataset and converts each of its elements into a 32-bit integer (`int32_t`).
4501 * It ensures that the array is of a compatible numeric type before performing the conversion.
4502 *
4503 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4504 * @param array_name A null-terminated string specifying the name of the SDDS array to retrieve and convert.
4505 * @param values Pointer to an integer where the number of elements in the array will be stored upon successful completion.
4506 *
4507 * @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.
4508 *
4509 * @retval NULL Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, incompatible array type, memory allocation failure).
4510 * @retval Non-NULL Pointer to an array of `int32_t` values representing the SDDS array elements.
4511 *
4512 * @note
4513 * - The caller is responsible for freeing the allocated memory for the returned `int32_t` array.
4514 * - The function does not handle string-type arrays; attempting to retrieve a string array will result in an error.
4515 *
4516 * @sa SDDS_GetArray, SDDS_GetArrayInDoubles, SDDS_GetArrayInString
4517 */
4518int32_t *SDDS_GetArrayInLong(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t *values) {
4519 int32_t index, type, i, elements;
4520 SDDS_ARRAY *original;
4521 int32_t *data;
4522 void *rawData;
4523
4524 *values = 0;
4525 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetArrayInLong"))
4526 return (NULL);
4527 if (!array_name) {
4528 SDDS_SetError("Unable to get array--array name pointer is NULL (SDDS_GetArrayInLong)");
4529 return (NULL);
4530 }
4531 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4532 SDDS_SetError("Unable to get array--array name is unrecognized (SDDS_GetArrayInLong)");
4533 return (NULL);
4534 }
4535 original = SDDS_dataset->array + index;
4536 if ((type = original->definition->type) == SDDS_STRING) {
4537 SDDS_SetError("Unable to get array--string type (SDDS_GetArrayInLong)");
4538 return (NULL);
4539 }
4540 elements = original->elements;
4541 if (!(data = SDDS_Malloc(sizeof(*data) * elements))) {
4542 SDDS_SetError("Unable to get array--allocation failure (SDDS_GetArrayInLong)");
4543 return (NULL);
4544 }
4545 rawData = original->data;
4546 switch (type) {
4547 case SDDS_LONGDOUBLE:
4548 for (i = 0; i < elements; i++) {
4549 data[i] = ((long double *)rawData)[i];
4550 }
4551 break;
4552 case SDDS_DOUBLE:
4553 for (i = 0; i < elements; i++) {
4554 data[i] = ((double *)rawData)[i];
4555 }
4556 break;
4557 case SDDS_FLOAT:
4558 for (i = 0; i < elements; i++) {
4559 data[i] = ((float *)rawData)[i];
4560 }
4561 break;
4562 case SDDS_LONG64:
4563 for (i = 0; i < elements; i++) {
4564 data[i] = ((int64_t *)rawData)[i];
4565 }
4566 break;
4567 case SDDS_ULONG64:
4568 for (i = 0; i < elements; i++) {
4569 data[i] = ((uint64_t *)rawData)[i];
4570 }
4571 break;
4572 case SDDS_LONG:
4573 for (i = 0; i < elements; i++) {
4574 data[i] = ((int32_t *)rawData)[i];
4575 }
4576 break;
4577 case SDDS_ULONG:
4578 for (i = 0; i < elements; i++) {
4579 data[i] = ((uint32_t *)rawData)[i];
4580 }
4581 break;
4582 case SDDS_SHORT:
4583 for (i = 0; i < elements; i++) {
4584 data[i] = ((short *)rawData)[i];
4585 }
4586 break;
4587 case SDDS_USHORT:
4588 for (i = 0; i < elements; i++) {
4589 data[i] = ((unsigned short *)rawData)[i];
4590 }
4591 break;
4592 case SDDS_CHARACTER:
4593 for (i = 0; i < elements; i++) {
4594 data[i] = ((char *)rawData)[i];
4595 }
4596 break;
4597 }
4598 *values = elements;
4599 return data;
4600}
4601
4602/**
4603 * @brief Retrieves the text and contents descriptions from an SDDS dataset.
4604 *
4605 * This function extracts the text description and contents description from the specified SDDS dataset.
4606 * The descriptions are copied into the provided pointers if they are not `NULL`. This allows users to
4607 * obtain metadata information about the dataset's content and purpose.
4608 *
4609 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4610 * @param text Pointer to a `char*` variable where the text description will be copied.
4611 * If `NULL`, the text description is not retrieved.
4612 * @param contents Pointer to a `char*` variable where the contents description will be copied.
4613 * If `NULL`, the contents description is not retrieved.
4614 *
4615 * @return Returns `1` on successful retrieval of the descriptions. On failure, returns `0` and sets an appropriate error message.
4616 *
4617 * @retval 1 Indicates that the descriptions were successfully retrieved and copied.
4618 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, memory allocation failure).
4619 *
4620 * @note
4621 * - The caller is responsible for freeing the memory allocated for `text` and `contents` if they are not `NULL`.
4622 * - Ensure that the dataset is properly initialized before calling this function.
4623 *
4624 * @sa SDDS_SetDescription, SDDS_GetArray, SDDS_GetParameter
4625 */
4626int32_t SDDS_GetDescription(SDDS_DATASET *SDDS_dataset, char **text, char **contents) {
4627 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_GetDescription"))
4628 return (0);
4629 if (text) {
4630 *text = NULL;
4631 if (!SDDS_CopyString(text, SDDS_dataset->layout.description)) {
4632 SDDS_SetError("Unable to retrieve description data (SDDS_GetDescription)");
4633 return (0);
4634 }
4635 }
4636 if (contents) {
4637 *contents = NULL;
4638 if (!SDDS_CopyString(contents, SDDS_dataset->layout.contents)) {
4639 SDDS_SetError("Unable to retrieve description data (SDDS_GetDescription)");
4640 return (0);
4641 }
4642 }
4643
4644 return (1);
4645}
4646
4647/**
4648 * @brief Sets unit conversions for a specified array in an SDDS dataset.
4649 *
4650 * This function updates the units of the specified array within the SDDS dataset and applies a conversion factor
4651 * to all its elements if the dataset has already been read (i.e., `pages_read > 0`). The function ensures that
4652 * the new units are consistent with the old units if provided.
4653 *
4654 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4655 * @param array_name A null-terminated string specifying the name of the array to update.
4656 * @param new_units A null-terminated string specifying the new units to assign to the array.
4657 * This parameter must not be `NULL`.
4658 * @param old_units A null-terminated string specifying the expected current units of the array.
4659 * If `NULL`, the function does not verify the existing units.
4660 * @param factor A `double` representing the conversion factor to apply to each element of the array.
4661 * Each element will be multiplied by this factor.
4662 *
4663 * @return Returns `1` on successful unit conversion and update. On failure, returns `0` and sets an appropriate error message.
4664 *
4665 * @retval 1 Indicates that the unit conversion was successfully applied.
4666 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, unrecognized array name, type undefined, memory allocation failure).
4667 *
4668 * @note
4669 * - The `new_units` parameter must not be `NULL`. Passing `NULL` will result in an error.
4670 * - If the dataset has not been read yet (`pages_read == 0`), the conversion factor is stored but not applied immediately.
4671 * - The function handles various data types, ensuring that the conversion factor is appropriately applied based on the array's type.
4672 *
4673 * @sa SDDS_SetColumnUnitsConversion, SDDS_SetParameterUnitsConversion, SDDS_GetArray
4674 */
4675int32_t SDDS_SetArrayUnitsConversion(SDDS_DATASET *SDDS_dataset, char *array_name, char *new_units, char *old_units, double factor) {
4676 int32_t index, type;
4677 int64_t i;
4678 void *rawData;
4679 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetArrayUnitsConversion"))
4680 return(0);
4681 if (new_units == NULL) {
4682 SDDS_SetError("new_units is NULL (SDDS_SetArrayUnitsConversion)");
4683 return(0);
4684 }
4685 if ((index = SDDS_GetArrayIndex(SDDS_dataset, array_name)) < 0) {
4686 SDDS_SetError("Unable to get array--name is not recognized (SDDS_SetArrayUnitsConversion)");
4687 return(0);
4688 }
4689 if (!(type = SDDS_GetArrayType(SDDS_dataset, index))) {
4690 SDDS_SetError("Unable to get array--data type undefined (SDDS_SetArrayUnitsConversion)");
4691 return(0);
4692 }
4693 if (SDDS_dataset->layout.array_definition[index].units != NULL) {
4694 if (strcmp(new_units, SDDS_dataset->layout.array_definition[index].units) != 0) {
4695 if ((old_units != NULL) && (strcmp(old_units, SDDS_dataset->layout.array_definition[index].units) != 0)) {
4696 SDDS_SetError("Unexpected units value found (SDDS_SetArrayUnitsConversion)");
4697 return(0);
4698 }
4699 /* free(SDDS_dataset->layout.array_definition[index].units); */
4700 cp_str(&(SDDS_dataset->layout.array_definition[index].units), new_units);
4701 }
4702 } else {
4703 cp_str(&(SDDS_dataset->layout.array_definition[index].units), new_units);
4704 }
4705
4706 if (SDDS_dataset->pages_read == 0) {
4707 return(1);
4708 }
4709 rawData = SDDS_dataset->array[index].data;
4710 switch (type) {
4711 case SDDS_LONGDOUBLE:
4712 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4713 ((long double *)rawData)[i] *= factor;
4714 }
4715 break;
4716 case SDDS_DOUBLE:
4717 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4718 ((double *)rawData)[i] *= factor;
4719 }
4720 break;
4721 case SDDS_FLOAT:
4722 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4723 ((float *)rawData)[i] *= factor;
4724 }
4725 break;
4726 case SDDS_LONG:
4727 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4728 ((int32_t *)rawData)[i] *= factor;
4729 }
4730 break;
4731 case SDDS_ULONG:
4732 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4733 ((uint32_t *)rawData)[i] *= factor;
4734 }
4735 break;
4736 case SDDS_LONG64:
4737 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4738 ((int64_t *)rawData)[i] *= factor;
4739 }
4740 break;
4741 case SDDS_ULONG64:
4742 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4743 ((uint64_t *)rawData)[i] *= factor;
4744 }
4745 break;
4746 case SDDS_SHORT:
4747 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4748 ((short *)rawData)[i] *= factor;
4749 }
4750 break;
4751 case SDDS_USHORT:
4752 for (i = 0; i < SDDS_dataset->array[index].elements; i++) {
4753 ((unsigned short *)rawData)[i] *= factor;
4754 }
4755 break;
4756 }
4757 return(1);
4758}
4759
4760/**
4761 * @brief Sets unit conversions for a specified column in an SDDS dataset.
4762 *
4763 * This function updates the units of the specified column within the SDDS dataset and applies a conversion factor
4764 * to all its elements if the dataset has already been read (i.e., `pages_read > 0`). The function ensures that
4765 * the new units are consistent with the old units if provided.
4766 *
4767 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4768 * @param column_name A null-terminated string specifying the name of the column to update.
4769 * @param new_units A null-terminated string specifying the new units to assign to the column.
4770 * This parameter must not be `NULL`.
4771 * @param old_units A null-terminated string specifying the expected current units of the column.
4772 * If `NULL`, the function does not verify the existing units.
4773 * @param factor A `double` representing the conversion factor to apply to each element of the column.
4774 * Each element will be multiplied by this factor.
4775 *
4776 * @return Returns `1` on successful unit conversion and update. On failure, returns `0` and sets an appropriate error message.
4777 *
4778 * @retval 1 Indicates that the unit conversion was successfully applied.
4779 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, unrecognized column name, type undefined, memory allocation failure).
4780 *
4781 * @note
4782 * - The `new_units` parameter must not be `NULL`. Passing `NULL` will result in an error.
4783 * - If the dataset has not been read yet (`pages_read == 0`), the conversion factor is stored but not applied immediately.
4784 * - The function handles various data types, ensuring that the conversion factor is appropriately applied based on the column's type.
4785 *
4786 * @sa SDDS_SetArrayUnitsConversion, SDDS_SetParameterUnitsConversion, SDDS_GetColumn
4787 */
4788int32_t SDDS_SetColumnUnitsConversion(SDDS_DATASET *SDDS_dataset, char *column_name, char *new_units, char *old_units, double factor) {
4789 int32_t index, type;
4790 int64_t i;
4791 void *rawData;
4792 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetColumnUnitsConversion"))
4793 return(0);
4794 if (new_units == NULL) {
4795 SDDS_SetError("new_units is NULL (SDDS_SetColumnUnitsConversion)");
4796 return(0);
4797 }
4798 if ((index = SDDS_GetColumnIndex(SDDS_dataset, column_name)) < 0) {
4799 SDDS_SetError("Unable to get column--name is not recognized (SDDS_SetColumnUnitsConversion)");
4800 return(0);
4801 }
4802 if (!(type = SDDS_GetColumnType(SDDS_dataset, index))) {
4803 SDDS_SetError("Unable to get column--data type undefined (SDDS_SetColumnUnitsConversion)");
4804 return(0);
4805 }
4806 if (SDDS_dataset->layout.column_definition[index].units != NULL) {
4807 if (strcmp(new_units, SDDS_dataset->layout.column_definition[index].units) != 0) {
4808 if ((old_units != NULL) && (strcmp(old_units, SDDS_dataset->layout.column_definition[index].units) != 0)) {
4809 SDDS_SetError("Unexpected units value found (SDDS_SetColumnUnitsConversion)");
4810 return(0);
4811 }
4812 free(SDDS_dataset->layout.column_definition[index].units);
4813 cp_str(&(SDDS_dataset->original_layout.column_definition[index].units), new_units);
4814 cp_str(&(SDDS_dataset->layout.column_definition[index].units), new_units);
4815 }
4816 } else {
4817 cp_str(&(SDDS_dataset->original_layout.column_definition[index].units), new_units);
4818 cp_str(&(SDDS_dataset->layout.column_definition[index].units), new_units);
4819 }
4820
4821 if (SDDS_dataset->pages_read == 0) {
4822 return(1);
4823 }
4824 rawData = SDDS_dataset->data[index];
4825 switch (type) {
4826 case SDDS_LONGDOUBLE:
4827 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4828 ((long double *)rawData)[i] *= factor;
4829 }
4830 break;
4831 case SDDS_DOUBLE:
4832 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4833 ((double *)rawData)[i] *= factor;
4834 }
4835 break;
4836 case SDDS_FLOAT:
4837 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4838 ((float *)rawData)[i] *= factor;
4839 }
4840 break;
4841 case SDDS_LONG:
4842 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4843 ((int32_t *)rawData)[i] *= factor;
4844 }
4845 break;
4846 case SDDS_ULONG:
4847 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4848 ((uint32_t *)rawData)[i] *= factor;
4849 }
4850 break;
4851 case SDDS_LONG64:
4852 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4853 ((int64_t *)rawData)[i] *= factor;
4854 }
4855 break;
4856 case SDDS_ULONG64:
4857 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4858 ((uint64_t *)rawData)[i] *= factor;
4859 }
4860 break;
4861 case SDDS_SHORT:
4862 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4863 ((short *)rawData)[i] *= factor;
4864 }
4865 break;
4866 case SDDS_USHORT:
4867 for (i = 0; i < SDDS_dataset->n_rows; i++) {
4868 ((unsigned short *)rawData)[i] *= factor;
4869 }
4870 break;
4871 }
4872 return(1);
4873}
4874
4875/**
4876 * @brief Sets unit conversions for a specified parameter in an SDDS dataset.
4877 *
4878 * This function updates the units of the specified parameter within the SDDS dataset and applies a conversion factor
4879 * to its value if the dataset has already been read (i.e., `pages_read > 0`). The function ensures that the new units
4880 * are consistent with the old units if provided.
4881 *
4882 * @param SDDS_dataset Pointer to the `SDDS_DATASET` structure representing the dataset.
4883 * @param parameter_name A null-terminated string specifying the name of the parameter to update.
4884 * @param new_units A null-terminated string specifying the new units to assign to the parameter.
4885 * This parameter must not be `NULL`.
4886 * @param old_units A null-terminated string specifying the expected current units of the parameter.
4887 * If `NULL`, the function does not verify the existing units.
4888 * @param factor A `double` representing the conversion factor to apply to the parameter's value.
4889 * The parameter's value will be multiplied by this factor.
4890 *
4891 * @return Returns `1` on successful unit conversion and update. On failure, returns `0` and sets an appropriate error message.
4892 *
4893 * @retval 1 Indicates that the unit conversion was successfully applied.
4894 * @retval 0 Indicates that an error occurred (e.g., invalid dataset, unrecognized parameter name, type undefined, memory allocation failure).
4895 *
4896 * @note
4897 * - The `new_units` parameter must not be `NULL`. Passing `NULL` will result in an error.
4898 * - If the dataset has not been read yet (`pages_read == 0`), the conversion factor is stored but not applied immediately.
4899 * - The function handles various data types, ensuring that the conversion factor is appropriately applied based on the parameter's type.
4900 *
4901 * @sa SDDS_SetArrayUnitsConversion, SDDS_SetColumnUnitsConversion, SDDS_GetParameter
4902 */
4903int32_t SDDS_SetParameterUnitsConversion(SDDS_DATASET *SDDS_dataset, char *parameter_name, char *new_units, char *old_units, double factor) {
4904 int32_t index, type;
4905 void *rawData;
4906 if (!SDDS_CheckDataset(SDDS_dataset, "SDDS_SetParameterUnitsConversion"))
4907 return(0);
4908 if (new_units == NULL) {
4909 SDDS_SetError("new_units is NULL (SDDS_SetParameterUnitsConversion)");
4910 return(0);
4911 }
4912 if ((index = SDDS_GetParameterIndex(SDDS_dataset, parameter_name)) < 0) {
4913 SDDS_SetError("Unable to get parameter--name is not recognized (SDDS_SetParameterUnitsConversion)");
4914 return(0);
4915 }
4916 if (!(type = SDDS_GetParameterType(SDDS_dataset, index))) {
4917 SDDS_SetError("Unable to get parameter--data type undefined (SDDS_SetParameterUnitsConversion)");
4918 return(0);
4919 }
4920 if (SDDS_dataset->layout.parameter_definition[index].units != NULL) {
4921 if (strcmp(new_units, SDDS_dataset->layout.parameter_definition[index].units) != 0) {
4922 if ((old_units != NULL) && (strcmp(old_units, SDDS_dataset->layout.parameter_definition[index].units) != 0)) {
4923 SDDS_SetError("Unexpected units value found (SDDS_SetParameterUnitsConversion)");
4924 return(0);
4925 }
4926 /* free(SDDS_dataset->layout.parameter_definition[index].units); */
4927 cp_str(&(SDDS_dataset->layout.parameter_definition[index].units), new_units);
4928 }
4929 } else {
4930 cp_str(&(SDDS_dataset->layout.parameter_definition[index].units), new_units);
4931 }
4932
4933 if (SDDS_dataset->pages_read == 0) {
4934 return(1);
4935 }
4936 rawData = SDDS_dataset->parameter[index];
4937 switch (type) {
4938 case SDDS_LONGDOUBLE:
4939 *((long double *)rawData) *= factor;
4940 break;
4941 case SDDS_DOUBLE:
4942 *((double *)rawData) *= factor;
4943 break;
4944 case SDDS_FLOAT:
4945 *((float *)rawData) *= factor;
4946 break;
4947 case SDDS_LONG:
4948 *((int32_t *)rawData) *= factor;
4949 break;
4950 case SDDS_ULONG:
4951 *((uint32_t *)rawData) *= factor;
4952 break;
4953 case SDDS_LONG64:
4954 *((int64_t *)rawData) *= factor;
4955 break;
4956 case SDDS_ULONG64:
4957 *((uint64_t *)rawData) *= factor;
4958 break;
4959 case SDDS_SHORT:
4960 *((short *)rawData) *= factor;
4961 break;
4962 case SDDS_USHORT:
4963 *((unsigned short *)rawData) *= factor;
4964 break;
4965 }
4966 return(1);
4967}
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:379
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:750
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:552
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:639
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:342
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
int32_t SDDS_CheckTabularData(SDDS_DATASET *SDDS_dataset, const char *caller)
Validates the consistency of tabular data within an SDDS dataset.
Definition SDDS_utils.c:577
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
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