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