SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsderef.c
Go to the documentation of this file.
1/**
2 * @file sddsderef.c
3 * @brief Array Dereferencing Tool for SDDS Data Sets
4 *
5 * @details
6 * This program performs array dereferencing on SDDS (Self Describing Data Sets) data files.
7 * Users can create new columns or parameters by indexing into existing array or column data.
8 * It supports customizable behavior for handling out-of-bounds indices and allows specifying
9 * the order of data processing (row-major or column-major).
10 *
11 * @section Usage
12 * ```
13 * sddsderef [<inputfile>] [<outputfile>]
14 * [-pipe=[input][,output]]
15 * [-column=<newName>,{arraySource|columnSource}=<name>,<indexColumnName>[,...]]
16 * [-parameter=<newName>,{arraySource|columnSource}=<name>,<indexParameterName>[,...]]
17 * [-constant=<newName>,{arraySource|columnSource}=<name>,<indexValue>[,<indexValue>]]
18 * [-outOfBounds=exit|delete]
19 * [-majorOrder=row|column]
20 * ```
21 *
22 * @section Options
23 * | Option | Description |
24 * |-----------------|-----------------------------------------------------------------------------|
25 * | `-pipe` | Use standard input and/or output instead of files. |
26 * | `-column` | Define a new column by dereferencing an existing array or column. |
27 * | `-parameter` | Define a new parameter by dereferencing an existing array or column. |
28 * | `-constant` | Define a new constant by dereferencing an existing array or column. |
29 * | `-outOfBounds` | Specify behavior for out-of-bounds indices: `exit` the program or `delete` the row. |
30 * | `-majorOrder` | Specify the major order for processing: `row` or `column`. |
31 *
32 * @copyright
33 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
34 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
35 *
36 * @license
37 * This file is distributed under the terms of the Software License Agreement
38 * found in the file LICENSE included with this distribution.
39 *
40 * @authors
41 * M. Borland, R. Soliday, H. Shang
42 */
43
44#include "mdb.h"
45#include "SDDS.h"
46#include "scan.h"
47
48/* Enumeration for option types */
49enum option_type {
50 SET_COLUMN,
51 SET_PARAMETER,
52 SET_PIPE,
53 SET_OUTOFBOUNDS,
54 SET_CONSTANT,
55 SET_MAJOR_ORDER,
56 N_OPTIONS
57};
58
59static char *optionName[N_OPTIONS] = {
60 "column",
61 "parameter",
62 "pipe",
63 "outofbounds",
64 "constant",
65 "majorOrder",
66};
67
68#define COLUMN_CLASS 0
69#define PARAMETER_CLASS 1
70#define ARRAY_CLASS 2
71#define CONSTANT_CLASS 3
72#define CLASS_NAMES 4
73
74static char *USAGE =
75 "sddsderef [<inputfile>] [<outputfile>]\n"
76 " [-pipe=[input][,output]]\n"
77 " [-column=<newName>,{arraySource|columnSource}=<name>,<indexColumnName>[,...]]\n"
78 " [-parameter=<newName>,{arraySource|columnSource}=<name>,<indexParameterName>[,...]]\n"
79 " [-constant=<newName>,{arraySource|columnSource}=<name>,<indexValue>[,<indexValue>]]\n"
80 " [-outOfBounds=exit|delete]\n"
81 " [-majorOrder=row|column]\n\n"
82 "Options:\n"
83 " -pipe Use standard input and/or output instead of files.\n"
84 " -column Define a new column by dereferencing an existing array or column.\n"
85 " -parameter Define a new parameter by dereferencing an existing array or column.\n"
86 " -constant Define a new constant by dereferencing an existing array or column.\n"
87 " -outOfBounds Specify behavior for out-of-bounds indices: 'exit' or 'delete'.\n"
88 " -majorOrder Specify the major order for processing: 'row' or 'column'.\n\n"
89 "Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
90
91typedef struct
92{
93 char *target, *source, **indexElement;
94 long targetIndex, indexElements, targetClass, sourceClass, sourceIndex;
95 long *indexValue;
97
98long DereferenceColumnWithParameter(SDDS_DATASET *outSet, DEREF_REQUEST *deref, unsigned long outOfBounds);
99long DereferenceColumnWithColumn(SDDS_DATASET *outSet, DEREF_REQUEST *deref, unsigned long outOfBounds);
100long DereferenceArrayWithParameter(SDDS_DATASET *outSet, DEREF_REQUEST *deref, unsigned long outOfBounds);
101long DereferenceArrayWithColumn(SDDS_DATASET *outSet, DEREF_REQUEST *deref, unsigned long outOfBounds);
102long DoDereferencing(SDDS_DATASET *outSet, DEREF_REQUEST *deref, long derefs, unsigned long outOfBounds);
103void setupOutputFile(SDDS_DATASET *outSet, char *output, SDDS_DATASET *inSet, char *input, DEREF_REQUEST *deref, long derefs, short columnMajorOrder);
104void addDerefRequest(DEREF_REQUEST **deref, long *derefs, char **argv, long argc, long class);
105
106#define EXIT_OUTBOUNDS 0x1U
107#define DELETE_OUTBOUNDS 0x2U
108
109int main(int argc, char **argv) {
110 SDDS_DATASET inSet, outSet;
111 SCANNED_ARG *s_arg;
112 long i_arg;
113 char *input, *output;
114 long derefRequests, code;
115 unsigned long outOfBounds;
116 DEREF_REQUEST *derefRequest;
117 unsigned long pipeFlags, majorOrderFlag;
118 short columnMajorOrder = -1;
119
121 argc = scanargs(&s_arg, argc, argv);
122 if (argc < 2)
123 bomb(NULL, USAGE);
124
125 input = output = NULL;
126 derefRequests = 0;
127 derefRequest = NULL;
128 pipeFlags = 0;
129 outOfBounds = EXIT_OUTBOUNDS;
130
131 for (i_arg = 1; i_arg < argc; i_arg++) {
132 if (s_arg[i_arg].arg_type == OPTION) {
133 switch (match_string(s_arg[i_arg].list[0], optionName, N_OPTIONS, 0)) {
134 case SET_MAJOR_ORDER:
135 majorOrderFlag = 0;
136 s_arg[i_arg].n_items--;
137 if (s_arg[i_arg].n_items > 0 && (!scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0, "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER, "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
138 SDDS_Bomb("invalid -majorOrder syntax/values");
139 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
140 columnMajorOrder = 1;
141 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
142 columnMajorOrder = 0;
143 break;
144 case SET_COLUMN:
145 if (s_arg[i_arg].n_items < 4)
146 SDDS_Bomb("invalid -column syntax");
147 addDerefRequest(&derefRequest, &derefRequests, s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, COLUMN_CLASS);
148 break;
149 case SET_PARAMETER:
150 if (s_arg[i_arg].n_items < 4)
151 SDDS_Bomb("invalid -parameter syntax");
152 addDerefRequest(&derefRequest, &derefRequests, s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, PARAMETER_CLASS);
153 break;
154 case SET_CONSTANT:
155 if (s_arg[i_arg].n_items < 4)
156 SDDS_Bomb("invalid -constant syntax");
157 addDerefRequest(&derefRequest, &derefRequests, s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, CONSTANT_CLASS);
158 break;
159 case SET_PIPE:
160 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
161 SDDS_Bomb("invalid -pipe syntax");
162 break;
163 case SET_OUTOFBOUNDS:
164 s_arg[i_arg].n_items -= 1;
165 outOfBounds = 0;
166 if (s_arg[i_arg].n_items != 1 || !scanItemList(&outOfBounds, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0, "exit", -1, NULL, 0, EXIT_OUTBOUNDS, "delete", -1, NULL, 0, DELETE_OUTBOUNDS, NULL) || !outOfBounds) {
167 SDDS_Bomb("invalid -outOfBounds syntax/values");
168 }
169 break;
170 default:
171 fprintf(stderr, "error: unknown/ambiguous option: %s\n", s_arg[i_arg].list[0]);
172 exit(EXIT_FAILURE);
173 break;
174 }
175 } else {
176 if (input == NULL)
177 input = s_arg[i_arg].list[0];
178 else if (output == NULL)
179 output = s_arg[i_arg].list[0];
180 else
181 SDDS_Bomb("too many filenames");
182 }
183 }
184
185 processFilenames("sddsderef", &input, &output, pipeFlags, 0, NULL);
186
187 setupOutputFile(&outSet, output, &inSet, input, derefRequest, derefRequests, columnMajorOrder);
188
189 while ((code = SDDS_ReadPage(&inSet)) > 0) {
190 if (!SDDS_CopyPage(&outSet, &inSet))
191 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
192 if (!DoDereferencing(&outSet, derefRequest, derefRequests, outOfBounds))
193 SDDS_Bomb("problem doing dereferencing");
194 if (!SDDS_WritePage(&outSet))
195 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
196 }
197 if (code == 0)
198 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
199 if (!SDDS_Terminate(&inSet) || !SDDS_Terminate(&outSet)) {
200 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
201 exit(EXIT_FAILURE);
202 }
203 return EXIT_SUCCESS;
204}
205
206void setupOutputFile(SDDS_DATASET *outSet, char *output, SDDS_DATASET *inSet, char *input, DEREF_REQUEST *deref, long derefs, short columnMajorOrder) {
207 long i, j;
208 if (!SDDS_InitializeInput(inSet, input) ||
209 !SDDS_InitializeCopy(outSet, inSet, output, "w"))
210 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
211 if (columnMajorOrder != -1)
212 outSet->layout.data_mode.column_major = columnMajorOrder;
213 else
214 outSet->layout.data_mode.column_major = inSet->layout.data_mode.column_major;
215 for (i = 0; i < derefs; i++) {
216 switch (deref[i].sourceClass) {
217 case ARRAY_CLASS:
218 if (SDDS_GetArrayIndex(outSet, deref[i].source) < 0) {
219 fprintf(stderr, "error (sddsderef): no array %s in input\n", deref[i].source);
220 exit(EXIT_FAILURE);
221 }
222 break;
223 case COLUMN_CLASS:
224 if (SDDS_GetColumnIndex(outSet, deref[i].source) < 0) {
225 fprintf(stderr, "error (sddsderef): no column %s in input\n", deref[i].source);
226 exit(EXIT_FAILURE);
227 }
228 break;
229 default:
230 SDDS_Bomb("invalid source class in setupOutputFile (coding error)");
231 break;
232 }
233 switch (deref[i].targetClass) {
234 case PARAMETER_CLASS:
235 case CONSTANT_CLASS:
236 switch (deref[i].sourceClass) {
237 case ARRAY_CLASS:
238 if (!SDDS_DefineParameterLikeArray(outSet, outSet, deref[i].source, deref[i].target))
239 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
240 deref[i].sourceIndex = SDDS_GetArrayIndex(outSet, deref[i].source);
241 break;
242 case COLUMN_CLASS:
243 if (!SDDS_DefineParameterLikeColumn(outSet, outSet, deref[i].source, deref[i].target))
244 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
245 deref[i].sourceIndex = SDDS_GetColumnIndex(outSet, deref[i].source);
246 break;
247 }
248 deref[i].targetIndex = SDDS_GetParameterIndex(outSet, deref[i].target);
249 if (deref[i].targetClass == PARAMETER_CLASS) {
250 for (j = 0; j < deref[i].indexElements; j++) {
251 if (SDDS_GetParameterIndex(outSet, deref[i].indexElement[j]) < 0) {
252 fprintf(stderr, "error (sddsderef): no parameter %s in input\n", deref[i].indexElement[j]);
253 exit(EXIT_FAILURE);
254 }
255 }
256 }
257 break;
258 case COLUMN_CLASS:
259 switch (deref[i].sourceClass) {
260 case ARRAY_CLASS:
261 if (!SDDS_DefineColumnLikeArray(outSet, outSet, deref[i].source, deref[i].target))
262 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
263 deref[i].sourceIndex = SDDS_GetArrayIndex(outSet, deref[i].source);
264 break;
265 case COLUMN_CLASS:
266 if (!SDDS_TransferColumnDefinition(outSet, outSet, deref[i].source, deref[i].target))
267 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
268 deref[i].sourceIndex = SDDS_GetColumnIndex(outSet, deref[i].source);
269 break;
270 }
271 deref[i].targetIndex = SDDS_GetColumnIndex(outSet, deref[i].target);
272 for (j = 0; j < deref[i].indexElements; j++) {
273 if (SDDS_GetColumnIndex(outSet, deref[i].indexElement[j]) < 0) {
274 fprintf(stderr, "error (sddsderef): no column %s in input\n", deref[i].indexElement[j]);
275 exit(EXIT_FAILURE);
276 }
277 }
278 break;
279 default:
280 fprintf(stderr, "error (sddsderef): invalid target data class (internal error)\n");
281 exit(EXIT_FAILURE);
282 break;
283 }
284 }
285 if (!SDDS_WriteLayout(outSet))
286 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
287}
288
289void addDerefRequest(DEREF_REQUEST **deref, long *derefs, char **argv, long argc, long class) {
290 long i, items;
291 unsigned long flags;
292#define ARRAY_SOURCE 0x1U
293#define COLUMN_SOURCE 0x2U
294 if (argc < 3) {
295 fprintf(stderr, "error (sddsderef): too few values for -%s\n", optionName[class]);
296 exit(EXIT_FAILURE);
297 }
298 if (!(*deref = SDDS_Realloc(*deref, sizeof(**deref) * (*derefs + 1))))
299 SDDS_Bomb("memory allocation failure (addDerefRequest)");
300
301 /* Store the first non-optional argument */
302 (*deref)[*derefs].targetClass = class;
303 (*deref)[*derefs].target = argv[0];
304 argv++;
305 argc--;
306
307 /* parse the second argument (key=value form) */
308 items = 1;
309 if (!scanItemList(&flags, argv, &items, 0, "arraySource", SDDS_STRING, &(*deref)[*derefs].source, 1, ARRAY_SOURCE, "columnSource", SDDS_STRING, &(*deref)[*derefs].source, 1, COLUMN_SOURCE, NULL) ||
310 !flags ||
311 flags == (ARRAY_SOURCE | COLUMN_SOURCE)) {
312 fprintf(stderr, "error (sddsderef): one of arraySource or columnSource must be given with -column or -parameter\n");
313 exit(EXIT_FAILURE);
314 }
315 if (flags & ARRAY_SOURCE)
316 (*deref)[*derefs].sourceClass = ARRAY_CLASS;
317 else {
318 (*deref)[*derefs].sourceClass = COLUMN_CLASS;
319 if (argc > 2) {
320 fprintf(stderr, "error (sddsderef): too many indices for column dereference\n");
321 exit(EXIT_FAILURE);
322 }
323 }
324
325 /* parse the remaining list of arguments (names of data elements) */
326 argv++;
327 argc--;
328 (*deref)[*derefs].indexElements = argc;
329 (*deref)[*derefs].indexElement = NULL;
330 (*deref)[*derefs].indexValue = NULL;
331 if (class == CONSTANT_CLASS) {
332 if (!((*deref)[*derefs].indexValue = (long *)malloc(sizeof(long) * argc))) {
333 SDDS_Bomb("memory allocation failure (addDerefRequest)");
334 }
335 for (i = 0; i < argc; i++) {
336 if (sscanf(argv[i], "%ld", (*deref)[*derefs].indexValue + i) != 1)
337 SDDS_Bomb("constant doesn't contain scannable integer");
338 }
339 } else {
340 if (!((*deref)[*derefs].indexElement = (char **)malloc(sizeof(*(*deref)[*derefs].indexElement) * argc)))
341 SDDS_Bomb("memory allocation failure (addDerefRequest)");
342 for (i = 0; i < argc; i++)
343 (*deref)[*derefs].indexElement[i] = argv[i];
344 }
345 *derefs += 1;
346}
347
348long DoDereferencing(SDDS_DATASET *outSet, DEREF_REQUEST *deref, long derefs, unsigned long outOfBounds) {
349 long i;
350 for (i = 0; i < derefs; i++) {
351 switch (deref[i].targetClass) {
352 case PARAMETER_CLASS:
353 case CONSTANT_CLASS:
354 switch (deref[i].sourceClass) {
355 case ARRAY_CLASS:
356 if (!DereferenceArrayWithParameter(outSet, deref + i, outOfBounds))
357 return 0;
358 break;
359 case COLUMN_CLASS:
360 if (!DereferenceColumnWithParameter(outSet, deref + i, outOfBounds))
361 return 0;
362 break;
363 default:
364 SDDS_Bomb("invalid source class--code error (DoDereferencing)");
365 break;
366 }
367 break;
368 case COLUMN_CLASS:
369 switch (deref[i].sourceClass) {
370 case ARRAY_CLASS:
371 if (!DereferenceArrayWithColumn(outSet, deref + i, outOfBounds))
372 return 0;
373 break;
374 case COLUMN_CLASS:
375 if (!DereferenceColumnWithColumn(outSet, deref + i, outOfBounds))
376 return 0;
377 break;
378 default:
379 SDDS_Bomb("invalid source class--code error (DoDereferencing)");
380 break;
381 }
382 break;
383 default:
384 SDDS_Bomb("invalid target class--code error (DoDereferencing)");
385 break;
386 }
387 }
388 return 1;
389}
390
391long DereferenceColumnWithParameter(SDDS_DATASET *outSet, DEREF_REQUEST *deref, unsigned long outOfBounds) {
392 double data[4];
393 long offset, type;
394 int64_t rows;
395 double value;
396 int32_t zeroValue = 0;
397 static char *blankString = "";
398
399 if (!(rows = outSet->n_rows))
400 return 1;
401 type = SDDS_GetColumnType(outSet, deref->sourceIndex);
402 if (deref->targetClass == CONSTANT_CLASS) {
403 value = deref->indexValue[0];
404 } else if (!SDDS_GetParameterAsDouble(outSet, deref->indexElement[0], &value)) {
405 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
406 return 0;
407 }
408 offset = ((long)value);
409 if (offset < 0 || offset >= rows) {
410 if (outOfBounds & EXIT_OUTBOUNDS) {
411 char s[1024];
412 sprintf(s, "column index out of bounds: column %s, length %" PRId64 ", offset %ld\n %s=%ld", deref->source, rows, offset, deref->indexElement[0], offset);
413 SDDS_Bomb(s);
414 }
415 if (type == SDDS_STRING)
416 memcpy((char *)data, (char *)&blankString, sizeof(blankString));
417 else
418 SDDS_CastValue((void *)&zeroValue, 0, SDDS_LONG, type, (void *)data);
419 } else {
420 if (!SDDS_GetValueByAbsIndex(outSet, deref->sourceIndex, offset, (void *)data)) {
421 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
422 return 0;
423 }
424 }
425
426 if (!SDDS_SetParameters(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, deref->targetIndex, (void *)data, -1)) {
427 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
428 return 0;
429 }
430 return 1;
431}
432
433long DereferenceArrayWithParameter(SDDS_DATASET *outSet, DEREF_REQUEST *deref, unsigned long outOfBounds) {
434 SDDS_ARRAY *array;
435 long i, j, offset, size;
436 double value;
437 int32_t zeroValue = 0;
438 static char *blankString = "";
439 double data[4];
440
441 if (!(array = SDDS_GetArray(outSet, deref->source, NULL))) {
442 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
443 return 0;
444 }
445 if (deref->indexElements != array->definition->dimensions) {
446 fprintf(stderr, "error: number of index elements (%ld) doesn't match number of array dimensions (%" PRId32 ") for array %s\n", deref->indexElements, array->definition->dimensions, deref->source);
447 return 0;
448 }
449 size = SDDS_GetTypeSize(array->definition->type);
450 offset = 0;
451 for (i = 0, j = deref->indexElements - 1; i < deref->indexElements; i++, j--) {
452 if (deref->targetClass == CONSTANT_CLASS) {
453 value = deref->indexValue[i];
454 } else {
455 /* get index values from parameters */
456 if (!SDDS_GetParameterAsDouble(outSet, deref->indexElement[i], &value)) {
457 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
458 return 0;
459 }
460 }
461 offset = ((long)value) + offset * array->dimension[j];
462 }
463 if (offset < 0 || offset >= array->elements) {
464 if (outOfBounds & EXIT_OUTBOUNDS) {
465 char s[1024];
466 sprintf(s, "array index out of bounds: array %s, length %" PRId32 ", offset %ld\n %s=%ld", deref->source, array->elements, offset, deref->indexElement[0], offset);
467 SDDS_Bomb(s);
468 }
469 if (array->definition->type == SDDS_STRING)
470 memcpy((char *)data, (char *)&blankString, sizeof(blankString));
471 else
472 SDDS_CastValue((void *)&zeroValue, 0, SDDS_LONG, array->definition->type, (void *)data);
473 if (!SDDS_SetParameters(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, deref->targetIndex, (void *)data, -1)) {
474 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
475 return 0;
476 }
477 } else if (!SDDS_SetParameters(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, deref->targetIndex, (char *)array->data + offset * size, -1)) {
478 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
479 return 0;
480 }
481 SDDS_FreeArray(array);
482 return 1;
483}
484
485long DereferenceArrayWithColumn(SDDS_DATASET *outSet, DEREF_REQUEST *deref, unsigned long outOfBounds) {
486 SDDS_ARRAY *array;
487 long i, offset, size, index;
488 int64_t row, rows;
489 int32_t **indexData;
490
491 if (!(rows = outSet->n_rows))
492 return 1;
493 if (!(array = SDDS_GetArray(outSet, deref->source, NULL))) {
494 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
495 return 0;
496 }
497 if (deref->indexElements != array->definition->dimensions) {
498 fprintf(stderr, "error: number of index elements (%ld) doesn't match number of array dimensions (%" PRId32 ") for array %s\n", deref->indexElements, array->definition->dimensions, deref->source);
499 return 0;
500 }
501 size = SDDS_GetTypeSize(array->definition->type);
502 offset = 0;
503
504 if (!(indexData = (int32_t **)malloc(sizeof(*indexData) * deref->indexElements)))
505 SDDS_Bomb("memory allocation failure while derefencing column data");
506 for (i = 0; i < deref->indexElements; i++)
507 if (!(indexData[i] = (int32_t *)SDDS_GetNumericColumn(outSet, deref->indexElement[i], SDDS_LONG))) {
508 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
509 return 0;
510 }
511 for (row = 0; row < rows; row++) {
512 for (i = offset = 0; i < deref->indexElements; i++) {
513 /* get index values from columns */
514 index = indexData[i][row];
515 if (index < 0 || index > array->dimension[i]) {
516 offset = -1;
517 break;
518 }
519 offset = index + offset * array->dimension[i];
520 }
521
522 if (offset < 0 || offset >= array->elements) {
523 if (outOfBounds & EXIT_OUTBOUNDS) {
524 char s[1024], t[1024];
525 sprintf(s, "array index out of bounds: array %s, length %" PRId32 ", offset %ld\n", deref->source, array->elements, offset);
526 for (i = 0; i < deref->indexElements; i++) {
527 sprintf(t, " %s=%" PRId32 " (dim=%" PRId32 ")", deref->indexElement[i], indexData[i][row], array->dimension[i]);
528 strcat(s, t);
529 }
530 SDDS_Bomb(s);
531 }
532 if (!SDDS_AssertRowFlags(outSet, SDDS_INDEX_LIMITS, row, row, 0)) {
533 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
534 return 0;
535 }
536 } else if (!SDDS_SetRowValues(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, row, deref->targetIndex, (char *)array->data + offset * size, -1)) {
537 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
538 return 0;
539 }
540 }
541 for (i = 0; i < deref->indexElements; i++)
542 free(indexData[i]);
543 free(indexData);
544 SDDS_FreeArray(array);
545 return 1;
546}
547
548long DereferenceColumnWithColumn(SDDS_DATASET *outSet, DEREF_REQUEST *deref, unsigned long outOfBounds) {
549 double data[4];
550 long offset;
551 int64_t rows, row;
552 long *indexData;
553
554 if (!(rows = outSet->n_rows)) {
555 return 1;
556 }
557 offset = 0;
558 if (!(indexData = (long *)SDDS_GetNumericColumn(outSet, deref->indexElement[0], SDDS_LONG))) {
559 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
560 return 0;
561 }
562
563 for (row = 0; row < rows; row++) {
564 offset = indexData[row];
565 if (offset < 0 || offset >= rows) {
566 if (outOfBounds & EXIT_OUTBOUNDS) {
567 char s[1024];
568 sprintf(s, "column index out of bounds: column %s, length %" PRId64 ", offset %ld\n %s=%ld\n", deref->source, rows, offset, deref->indexElement[0], offset);
569 SDDS_Bomb(s);
570 }
571 if (!SDDS_AssertRowFlags(outSet, SDDS_INDEX_LIMITS, row, row, 0)) {
572 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
573 return 0;
574 }
575 } else if (!SDDS_GetValueByAbsIndex(outSet, deref->sourceIndex, offset, (void *)data) ||
576 !SDDS_SetRowValues(outSet, SDDS_SET_BY_INDEX | SDDS_PASS_BY_REFERENCE, row, deref->targetIndex, (void *)data, -1)) {
577 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
578 return 0;
579 }
580 }
581 free(indexData);
582 return 1;
583}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
Definition SDDS_copy.c:40
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:578
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_AssertRowFlags(SDDS_DATASET *SDDS_dataset, uint32_t mode,...)
Sets acceptance flags for rows based on specified criteria.
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,...
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...
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.
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_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
int32_t SDDS_DefineParameterLikeColumn(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Defines a parameter in the target dataset based on a column definition from the source dataset.
int32_t SDDS_DefineColumnLikeArray(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Defines a column in the target dataset based on an array definition from the source dataset.
int32_t SDDS_DefineParameterLikeArray(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Defines a parameter in the target dataset based on an array definition from the source dataset.
void SDDS_FreeArray(SDDS_ARRAY *array)
Frees memory allocated for an SDDS array structure.
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.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_GetTypeSize(int32_t type)
Retrieves the size in bytes of a specified SDDS data type.
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
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
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 scanargs(SCANNED_ARG **scanned, int argc, char **argv)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.