1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 #include "H5Zmodule.h" /* This source code file is part of the H5Z module */
15
16
17 #include "H5private.h" /* Generic Functions */
18 #include "H5Eprivate.h" /* Error handling */
19 #include "H5Iprivate.h" /* IDs */
20 #include "H5MMprivate.h" /* Memory management */
21 #include "H5VMprivate.h" /* H5VM_array_fill */
22 #include "H5Zpkg.h" /* Data filters */
23
24
25 /* Token types */
26 typedef enum {
27 H5Z_XFORM_ERROR,
28 H5Z_XFORM_INTEGER, /* this represents an integer type in the data transform expression */
29 H5Z_XFORM_FLOAT, /* this represents a floating point type in the data transform expression */
30 H5Z_XFORM_SYMBOL,
31 H5Z_XFORM_PLUS,
32 H5Z_XFORM_MINUS,
33 H5Z_XFORM_MULT,
34 H5Z_XFORM_DIVIDE,
35 H5Z_XFORM_LPAREN,
36 H5Z_XFORM_RPAREN,
37 H5Z_XFORM_END
38 } H5Z_token_type;
39
40
41 typedef struct {
42 unsigned int num_ptrs;
43 void** ptr_dat_val;
44 } H5Z_datval_ptrs;
45
46
47 /* Used to represent values in transform expression */
48 typedef union {
49 void *dat_val;
50 long int_val;
51 double float_val;
52 } H5Z_num_val;
53
54 typedef struct H5Z_node {
55 struct H5Z_node *lchild;
56 struct H5Z_node *rchild;
57 H5Z_token_type type;
58 H5Z_num_val value;
59 } H5Z_node;
60
61 struct H5Z_data_xform_t {
62 char* xform_exp;
63 H5Z_node* parse_root;
64 H5Z_datval_ptrs* dat_val_pointers;
65 };
66
67 typedef struct result {
68 H5Z_token_type type;
69 H5Z_num_val value;
70 } H5Z_result;
71
72
73 /* The token */
74 typedef struct {
75 const char *tok_expr; /* Holds the original expression */
76
77 /* Current token values */
78 H5Z_token_type tok_type; /* The type of the current token */
79 const char *tok_begin; /* The beginning of the current token */
80 const char *tok_end; /* The end of the current token */
81
82 /* Previous token values */
83 H5Z_token_type tok_last_type; /* The type of the last token */
84 const char *tok_last_begin; /* The beginning of the last token */
85 const char *tok_last_end; /* The end of the last token */
86 } H5Z_token;
87
88 /* Local function prototypes */
89 static H5Z_token *H5Z_get_token(H5Z_token *current);
90 static H5Z_node *H5Z_parse_expression(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers);
91 static H5Z_node *H5Z_parse_term(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers);
92 static H5Z_node *H5Z_parse_factor(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers);
93 static H5Z_node *H5Z_new_node(H5Z_token_type type);
94 static void H5Z_do_op(H5Z_node* tree);
95 static hbool_t H5Z_op_is_numbs(H5Z_node* _tree);
96 static hbool_t H5Z_op_is_numbs2(H5Z_node* _tree);
97 static hid_t H5Z_xform_find_type(const H5T_t* type);
98 static herr_t H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_type, H5Z_result* res);
99 static void H5Z_xform_destroy_parse_tree(H5Z_node *tree);
100 static void* H5Z_xform_parse(const char *expression, H5Z_datval_ptrs* dat_val_pointers);
101 static void* H5Z_xform_copy_tree(H5Z_node* tree, H5Z_datval_ptrs* dat_val_pointers, H5Z_datval_ptrs* new_dat_val_pointers);
102 static void H5Z_xform_reduce_tree(H5Z_node* tree);
103 #ifdef H5Z_XFORM_DEBUG
104 static void H5Z_XFORM_DEBUG(H5Z_node *tree);
105 static void H5Z_print(H5Z_node *tree, FILE *stream);
106 #endif /* H5Z_XFORM_DEBUG */
107
108 /* PGCC (11.8-0) has trouble with the command *p++ = *p OP tree_val. It increments P first before
109 * doing the operation. So I break down the command into two lines:
110 * *p = *p OP tree_val; p++;
111 * Actually, the behavior of *p++ = *p OP tree_val is undefined. (SLU - 2012/3/19)
112 */
113 #define H5Z_XFORM_DO_OP1(RESL,RESR,TYPE,OP,SIZE) \
114 { \
115 size_t u; \
116 \
117 if(((RESL).type == H5Z_XFORM_SYMBOL) && ((RESR).type != H5Z_XFORM_SYMBOL)) \
118 { \
119 TYPE* p; \
120 double tree_val; \
121 \
122 tree_val = ((RESR).type==H5Z_XFORM_INTEGER ? (double)(RESR).value.int_val : (RESR).value.float_val); \
123 p = (TYPE*)(RESL).value.dat_val; \
124 \
125 for(u = 0; u < (SIZE); u++) { \
126 *p = (TYPE)((double)*p OP tree_val); \
127 p++; \
128 } \
129 } \
130 else if(((RESR).type == H5Z_XFORM_SYMBOL) && ((RESL).type != H5Z_XFORM_SYMBOL)) \
131 { \
132 TYPE* p; \
133 double tree_val; \
134 \
135 /* The case that the left operand is nothing, like -x or +x */ \
136 if((RESL).type == H5Z_XFORM_ERROR) \
137 tree_val = 0; \
138 else \
139 tree_val = ((RESL).type==H5Z_XFORM_INTEGER ? (double)(RESL).value.int_val : (RESL).value.float_val); \
140 \
141 p = (TYPE*)(RESR).value.dat_val; \
142 for(u = 0; u < (SIZE); u++) { \
143 *p = (TYPE)(tree_val OP (double)*p); \
144 p++; \
145 } \
146 } \
147 else if( ((RESL).type == H5Z_XFORM_SYMBOL) && ((RESR).type == H5Z_XFORM_SYMBOL)) \
148 { \
149 TYPE* pl = (TYPE*)(RESL).value.dat_val; \
150 TYPE* pr = (TYPE*)(RESR).value.dat_val; \
151 \
152 for(u = 0; u < (SIZE); u++) { \
153 *pl = (TYPE)(*pl OP *pr); \
154 pl++; pr++; \
155 } \
156 } \
157 else \
158 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Unexpected type conversion operation") \
159 }
160
161 #if H5_SIZEOF_LONG_DOUBLE != 0
162 #if CHAR_MIN >= 0
163 #define H5Z_XFORM_TYPE_OP(RESL,RESR,TYPE,OP,SIZE) \
164 { \
165 if((TYPE) == H5T_NATIVE_CHAR) \
166 H5Z_XFORM_DO_OP1((RESL), (RESR), char, OP, (SIZE)) \
167 else if((TYPE) == H5T_NATIVE_SCHAR) \
168 H5Z_XFORM_DO_OP1((RESL), (RESR), signed char, OP, (SIZE)) \
169 else if((TYPE) == H5T_NATIVE_SHORT) \
170 H5Z_XFORM_DO_OP1((RESL), (RESR), short, OP, (SIZE)) \
171 else if((TYPE) == H5T_NATIVE_USHORT) \
172 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned short, OP, (SIZE)) \
173 else if((TYPE) == H5T_NATIVE_INT) \
174 H5Z_XFORM_DO_OP1((RESL), (RESR), int, OP, (SIZE)) \
175 else if((TYPE) == H5T_NATIVE_UINT) \
176 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned int, OP, (SIZE)) \
177 else if((TYPE) == H5T_NATIVE_LONG) \
178 H5Z_XFORM_DO_OP1((RESL), (RESR), long, OP, (SIZE)) \
179 else if((TYPE) == H5T_NATIVE_ULONG) \
180 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long, OP, (SIZE)) \
181 else if((TYPE) == H5T_NATIVE_LLONG) \
182 H5Z_XFORM_DO_OP1((RESL), (RESR), long long, OP, (SIZE)) \
183 else if((TYPE) == H5T_NATIVE_ULLONG) \
184 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long long, OP, (SIZE)) \
185 else if((TYPE) == H5T_NATIVE_FLOAT) \
186 H5Z_XFORM_DO_OP1((RESL), (RESR), float, OP, (SIZE)) \
187 else if((TYPE) == H5T_NATIVE_DOUBLE) \
188 H5Z_XFORM_DO_OP1((RESL), (RESR), double, OP, (SIZE)) \
189 else if((TYPE) == H5T_NATIVE_LDOUBLE) \
190 H5Z_XFORM_DO_OP1((RESL), (RESR), long double, OP, (SIZE)) \
191 }
192 #else /* CHAR_MIN >= 0 */
193 #define H5Z_XFORM_TYPE_OP(RESL,RESR,TYPE,OP,SIZE) \
194 { \
195 if((TYPE) == H5T_NATIVE_CHAR) \
196 H5Z_XFORM_DO_OP1((RESL), (RESR), char, OP, (SIZE)) \
197 else if((TYPE) == H5T_NATIVE_UCHAR) \
198 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned char, OP, (SIZE)) \
199 else if((TYPE) == H5T_NATIVE_SHORT) \
200 H5Z_XFORM_DO_OP1((RESL), (RESR), short, OP, (SIZE)) \
201 else if((TYPE) == H5T_NATIVE_USHORT) \
202 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned short, OP, (SIZE)) \
203 else if((TYPE) == H5T_NATIVE_INT) \
204 H5Z_XFORM_DO_OP1((RESL), (RESR), int, OP, (SIZE)) \
205 else if((TYPE) == H5T_NATIVE_UINT) \
206 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned int, OP, (SIZE)) \
207 else if((TYPE) == H5T_NATIVE_LONG) \
208 H5Z_XFORM_DO_OP1((RESL), (RESR), long, OP, (SIZE)) \
209 else if((TYPE) == H5T_NATIVE_ULONG) \
210 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long, OP, (SIZE)) \
211 else if((TYPE) == H5T_NATIVE_LLONG) \
212 H5Z_XFORM_DO_OP1((RESL), (RESR), long long, OP, (SIZE)) \
213 else if((TYPE) == H5T_NATIVE_ULLONG) \
214 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long long, OP, (SIZE)) \
215 else if((TYPE) == H5T_NATIVE_FLOAT) \
216 H5Z_XFORM_DO_OP1((RESL), (RESR), float, OP, (SIZE)) \
217 else if((TYPE) == H5T_NATIVE_DOUBLE) \
218 H5Z_XFORM_DO_OP1((RESL), (RESR), double, OP, (SIZE)) \
219 else if((TYPE) == H5T_NATIVE_LDOUBLE) \
220 H5Z_XFORM_DO_OP1((RESL), (RESR), long double, OP, (SIZE)) \
221 }
222 #endif /* CHAR_MIN >= 0 */
223 #else
224 #if CHAR_MIN >= 0
225 #define H5Z_XFORM_TYPE_OP(RESL,RESR,TYPE,OP,SIZE) \
226 { \
227 if((TYPE) == H5T_NATIVE_CHAR) \
228 H5Z_XFORM_DO_OP1((RESL), (RESR), char, OP, (SIZE)) \
229 else if((TYPE) == H5T_NATIVE_SCHAR) \
230 H5Z_XFORM_DO_OP1((RESL), (RESR), signed char, OP, (SIZE)) \
231 else if((TYPE) == H5T_NATIVE_SHORT) \
232 H5Z_XFORM_DO_OP1((RESL), (RESR), short, OP, (SIZE)) \
233 else if((TYPE) == H5T_NATIVE_USHORT) \
234 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned short, OP, (SIZE)) \
235 else if((TYPE) == H5T_NATIVE_INT) \
236 H5Z_XFORM_DO_OP1((RESL), (RESR), int, OP, (SIZE)) \
237 else if((TYPE) == H5T_NATIVE_UINT) \
238 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned int, OP, (SIZE)) \
239 else if((TYPE) == H5T_NATIVE_LONG) \
240 H5Z_XFORM_DO_OP1((RESL), (RESR), long, OP, (SIZE)) \
241 else if((TYPE) == H5T_NATIVE_ULONG) \
242 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long, OP, (SIZE)) \
243 else if((TYPE) == H5T_NATIVE_LLONG) \
244 H5Z_XFORM_DO_OP1((RESL), (RESR), long long, OP, (SIZE)) \
245 else if((TYPE) == H5T_NATIVE_ULLONG) \
246 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long long, OP, (SIZE)) \
247 else if((TYPE) == H5T_NATIVE_FLOAT) \
248 H5Z_XFORM_DO_OP1((RESL), (RESR), float, OP, (SIZE)) \
249 else if((TYPE) == H5T_NATIVE_DOUBLE) \
250 H5Z_XFORM_DO_OP1((RESL), (RESR), double, OP, (SIZE)) \
251 }
252 #else /* CHAR_MIN >= 0 */
253 #define H5Z_XFORM_TYPE_OP(RESL,RESR,TYPE,OP,SIZE) \
254 { \
255 if((TYPE) == H5T_NATIVE_CHAR) \
256 H5Z_XFORM_DO_OP1((RESL), (RESR), char, OP, (SIZE)) \
257 else if((TYPE) == H5T_NATIVE_UCHAR) \
258 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned char, OP, (SIZE)) \
259 else if((TYPE) == H5T_NATIVE_SHORT) \
260 H5Z_XFORM_DO_OP1((RESL), (RESR), short, OP, (SIZE)) \
261 else if((TYPE) == H5T_NATIVE_USHORT) \
262 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned short, OP, (SIZE)) \
263 else if((TYPE) == H5T_NATIVE_INT) \
264 H5Z_XFORM_DO_OP1((RESL), (RESR), int, OP, (SIZE)) \
265 else if((TYPE) == H5T_NATIVE_UINT) \
266 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned int, OP, (SIZE)) \
267 else if((TYPE) == H5T_NATIVE_LONG) \
268 H5Z_XFORM_DO_OP1((RESL), (RESR), long, OP, (SIZE)) \
269 else if((TYPE) == H5T_NATIVE_ULONG) \
270 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long, OP, (SIZE)) \
271 else if((TYPE) == H5T_NATIVE_LLONG) \
272 H5Z_XFORM_DO_OP1((RESL), (RESR), long long, OP, (SIZE)) \
273 else if((TYPE) == H5T_NATIVE_ULLONG) \
274 H5Z_XFORM_DO_OP1((RESL), (RESR), unsigned long long, OP, (SIZE)) \
275 else if((TYPE) == H5T_NATIVE_FLOAT) \
276 H5Z_XFORM_DO_OP1((RESL), (RESR), float, OP, (SIZE)) \
277 else if((TYPE) == H5T_NATIVE_DOUBLE) \
278 H5Z_XFORM_DO_OP1((RESL), (RESR), double, OP, (SIZE)) \
279 }
280 #endif /* CHAR_MIN >= 0 */
281 #endif /*H5_SIZEOF_LONG_DOUBLE */
282
283 #define H5Z_XFORM_DO_OP3(OP) \
284 { \
285 if((tree->lchild->type == H5Z_XFORM_INTEGER) && (tree->rchild->type==H5Z_XFORM_INTEGER)) \
286 { \
287 tree->type = H5Z_XFORM_INTEGER; \
288 tree->value.int_val = tree->lchild->value.int_val OP tree->rchild->value.int_val; \
289 H5MM_xfree(tree->lchild); \
290 H5MM_xfree(tree->rchild); \
291 tree->lchild = NULL; \
292 tree->rchild = NULL; \
293 } \
294 else if( ( (tree->lchild->type == H5Z_XFORM_FLOAT) || (tree->lchild->type == H5Z_XFORM_INTEGER)) && \
295 ( (tree->rchild->type == H5Z_XFORM_FLOAT) || (tree->rchild->type == H5Z_XFORM_INTEGER))) \
296 { \
297 tree->type = H5Z_XFORM_FLOAT; \
298 tree->value.float_val = ((tree->lchild->type == H5Z_XFORM_FLOAT) ? tree->lchild->value.float_val : (double)tree->lchild->value.int_val) OP \
299 ((tree->rchild->type == H5Z_XFORM_FLOAT) ? tree->rchild->value.float_val : (double)tree->rchild->value.int_val); \
300 H5MM_xfree(tree->lchild); \
301 H5MM_xfree(tree->rchild); \
302 tree->lchild = NULL; \
303 tree->rchild = NULL; \
304 } \
305 }
306
307 #define H5Z_XFORM_DO_OP4(TYPE) \
308 { \
309 if ((ret_value = (H5Z_node*) H5MM_malloc(sizeof(H5Z_node))) == NULL) \
310 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree") \
311 else \
312 { \
313 ret_value->type = (TYPE); \
314 if(tree->lchild) \
315 ret_value->lchild = (H5Z_node*) H5Z_xform_copy_tree(tree->lchild, dat_val_pointers, new_dat_val_pointers); \
316 else \
317 ret_value->lchild = NULL; \
318 if(tree->rchild) \
319 ret_value->rchild = (H5Z_node*) H5Z_xform_copy_tree(tree->rchild, dat_val_pointers, new_dat_val_pointers); \
320 else \
321 ret_value->rchild = NULL; \
322 } \
323 }
324
325 #define H5Z_XFORM_DO_OP5(TYPE, SIZE) \
326 { \
327 TYPE val = ((tree->type == H5Z_XFORM_INTEGER) ? (TYPE)tree->value.int_val : (TYPE)tree->value.float_val); \
328 H5VM_array_fill(array, &val, sizeof(TYPE), (SIZE)); \
329 }
330
331 /* The difference of this macro from H5Z_XFORM_DO_OP3 is that it handles the operations when the left operand is empty, like -x or +x.
332 * The reason that it's separated from H5Z_XFORM_DO_OP3 is because compilers don't accept operations like *x or /x. So in H5Z_do_op,
333 * these two macros are called in different ways. (SLU 2012/3/20)
334 */
335 #define H5Z_XFORM_DO_OP6(OP) \
336 { \
337 if(!tree->lchild && (tree->rchild->type==H5Z_XFORM_INTEGER)) \
338 { \
339 tree->type = H5Z_XFORM_INTEGER; \
340 tree->value.int_val = OP tree->rchild->value.int_val; \
341 H5MM_xfree(tree->rchild); \
342 tree->rchild = NULL; \
343 } \
344 else if(!tree->lchild && (tree->rchild->type==H5Z_XFORM_FLOAT)) \
345 { \
346 tree->type = H5Z_XFORM_FLOAT; \
347 tree->value.float_val = OP tree->rchild->value.float_val; \
348 H5MM_xfree(tree->rchild); \
349 tree->rchild = NULL; \
350 } \
351 else if((tree->lchild->type == H5Z_XFORM_INTEGER) && (tree->rchild->type==H5Z_XFORM_INTEGER)) \
352 { \
353 tree->type = H5Z_XFORM_INTEGER; \
354 tree->value.int_val = tree->lchild->value.int_val OP tree->rchild->value.int_val; \
355 H5MM_xfree(tree->lchild); \
356 H5MM_xfree(tree->rchild); \
357 tree->lchild = NULL; \
358 tree->rchild = NULL; \
359 } \
360 else if( ( (tree->lchild->type == H5Z_XFORM_FLOAT) || (tree->lchild->type == H5Z_XFORM_INTEGER)) && \
361 ( (tree->rchild->type == H5Z_XFORM_FLOAT) || (tree->rchild->type == H5Z_XFORM_INTEGER))) \
362 { \
363 tree->type = H5Z_XFORM_FLOAT; \
364 tree->value.float_val = ((tree->lchild->type == H5Z_XFORM_FLOAT) ? tree->lchild->value.float_val : (double)tree->lchild->value.int_val) OP \
365 ((tree->rchild->type == H5Z_XFORM_FLOAT) ? tree->rchild->value.float_val : (double)tree->rchild->value.int_val); \
366 H5MM_xfree(tree->lchild); \
367 H5MM_xfree(tree->rchild); \
368 tree->lchild = NULL; \
369 tree->rchild = NULL; \
370 } \
371 }
372
373 /*
374 * Programmer: Bill Wendling <wendling@ncsa.uiuc.edu>
375 * 25. August 2003
376 */
377
378 /*
379 * This is the context-free grammar for our expressions:
380 *
381 * expr := term | term '+ term | term '-' term
382 * term := factor | factor '*' factor | factor '/' factor
383 * factor := number |
384 * symbol |
385 * '-' factor | // unary minus
386 * '+' factor | // unary plus
387 * '(' expr ')'
388 * symbol := [a-zA-Z][a-zA-Z0-9]*
389 * number := H5Z_XFORM_INTEGER | FLOAT
390 * // H5Z_XFORM_INTEGER is a C long int
391 * // FLOAT is a C double
392 */
393
394
395 /*-------------------------------------------------------------------------
396 * Function: H5Z_unget_token
397 * Purpose: Rollback the H5Z_token to the previous H5Z_token retrieved. There
398 * should only need to be one level of rollback necessary
399 * for our grammar.
400 * Return: Always succeeds.
401 * Programmer: Bill Wendling
402 * 26. August 2003
403 * Modifications:
404 * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
405 *
406 *-------------------------------------------------------------------------
407 */
408 static void
H5Z_unget_token(H5Z_token * current)409 H5Z_unget_token(H5Z_token *current)
410 {
411 FUNC_ENTER_NOAPI_NOINIT_NOERR
412
413 /* check args */
414 HDassert(current);
415
416 current->tok_type = current->tok_last_type;
417 current->tok_begin = current->tok_last_begin;
418 current->tok_end = current->tok_last_end;
419
420 FUNC_LEAVE_NOAPI_VOID
421 }
422
423
424 /*-------------------------------------------------------------------------
425 * Function: H5Z_get_token
426 *
427 * Purpose: Determine what the next valid H5Z_token is in the expression
428 * string. The current position within the H5Z_token string is
429 * kept internal to the H5Z_token and handled by this and the
430 * unget_H5Z_token function.
431 *
432 * Return: Succeess: The passed in H5Z_token with a valid tok_type
433 * field.
434 * Failure: The passed in H5Z_token but with the tok_type
435 * field set to ERROR.
436 *
437 * Programmer: Bill Wendling
438 * 26. August 2003
439 *
440 *-------------------------------------------------------------------------
441 */
442 static H5Z_token *
H5Z_get_token(H5Z_token * current)443 H5Z_get_token(H5Z_token *current)
444 {
445 H5Z_token *ret_value = current;
446
447 FUNC_ENTER_NOAPI_NOINIT
448
449 /* check args */
450 HDassert(current);
451
452 /* Save the last position for possible ungets */
453 current->tok_last_type = current->tok_type;
454 current->tok_last_begin = current->tok_begin;
455 current->tok_last_end = current->tok_end;
456
457 current->tok_begin = current->tok_end;
458
459 while (current->tok_begin[0] != '\0') {
460 if (HDisspace(current->tok_begin[0])) {
461 /* ignore whitespace */
462 } else if (HDisdigit(current->tok_begin[0]) ||
463 current->tok_begin[0] == '.') {
464 current->tok_end = current->tok_begin;
465
466 /*
467 * H5Z_XFORM_INTEGER := digit-sequence
468 * digit-sequence := digit | digit digit-sequence
469 * digit := 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
470 */
471 if (current->tok_end[0] != '.') {
472 /* is number */
473 current->tok_type = H5Z_XFORM_INTEGER;
474
475 while (HDisdigit(current->tok_end[0]))
476 ++current->tok_end;
477 }
478
479 /*
480 * float := digit-sequence exponent |
481 * dotted-digits exponent?
482 * dotted-digits := digit-sequence '.' digit-sequence? |
483 * '.' digit-sequence
484 * exponent := [Ee] [-+]? digit-sequence
485 */
486 if (current->tok_end[0] == '.' ||
487 current->tok_end[0] == 'e' ||
488 current->tok_end[0] == 'E') {
489 current->tok_type = H5Z_XFORM_FLOAT;
490
491 if (current->tok_end[0] == '.')
492 do {
493 ++current->tok_end;
494 } while (HDisdigit(current->tok_end[0]));
495
496 if (current->tok_end[0] == 'e' ||
497 current->tok_end[0] == 'E') {
498 ++current->tok_end;
499
500 if (current->tok_end[0] == '-' ||
501 current->tok_end[0] == '+')
502 ++current->tok_end;
503
504 if (!HDisdigit(current->tok_end[0])) {
505 current->tok_type = H5Z_XFORM_ERROR;
506 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, current, "Invalidly formatted floating point number")
507 }
508
509 while (HDisdigit(current->tok_end[0]))
510 ++current->tok_end;
511 }
512
513 /* Check that this is a properly formatted numerical value */
514 if (HDisalpha(current->tok_end[0]) || current->tok_end[0] == '.') {
515 current->tok_type = H5Z_XFORM_ERROR;
516 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, current, "Invalidly formatted floating point number")
517 }
518 }
519
520 break;
521 } else if (HDisalpha(current->tok_begin[0])) {
522 /* is symbol */
523 current->tok_type = H5Z_XFORM_SYMBOL;
524 current->tok_end = current->tok_begin;
525
526 while (HDisalnum(current->tok_end[0]))
527 ++current->tok_end;
528
529 break;
530 } else {
531 /* should be +, -, *, /, (, or ) */
532 switch (current->tok_begin[0]) {
533 case '+': current->tok_type = H5Z_XFORM_PLUS; break;
534 case '-': current->tok_type = H5Z_XFORM_MINUS; break;
535 case '*': current->tok_type = H5Z_XFORM_MULT; break;
536 case '/': current->tok_type = H5Z_XFORM_DIVIDE; break;
537 case '(': current->tok_type = H5Z_XFORM_LPAREN; break;
538 case ')': current->tok_type = H5Z_XFORM_RPAREN; break;
539 default:
540 current->tok_type = H5Z_XFORM_ERROR;
541 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, current, "Unknown H5Z_token in data transform expression ")
542 }
543
544 current->tok_end = current->tok_begin + 1;
545 break;
546 }
547
548 ++current->tok_begin;
549 }
550
551 if (current->tok_begin[0] == '\0')
552 current->tok_type = H5Z_XFORM_END;
553
554 /* Set return value */
555 ret_value = current;
556
557 done:
558 FUNC_LEAVE_NOAPI(ret_value)
559 }
560
561
562 /*-------------------------------------------------------------------------
563 * Function: H5Z_xform_destroy_parse_tree
564 * Purpose: Recursively destroys the expression tree.
565 * Return: Nothing
566 * Programmer: Bill Wendling
567 * 25. August 2003
568 * Modifications:
569 * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
570 *
571 *-------------------------------------------------------------------------
572 */
573 static void
H5Z_xform_destroy_parse_tree(H5Z_node * tree)574 H5Z_xform_destroy_parse_tree(H5Z_node *tree)
575 {
576 FUNC_ENTER_NOAPI_NOINIT_NOERR
577
578 if (tree)
579 {
580 H5Z_xform_destroy_parse_tree(tree->lchild);
581 H5Z_xform_destroy_parse_tree(tree->rchild);
582 H5MM_xfree(tree);
583 tree = NULL;
584 }
585
586 FUNC_LEAVE_NOAPI_VOID
587 }
588
589
590 /*-------------------------------------------------------------------------
591 * Function: H5Z_parse
592 *
593 * Purpose: Entry function for parsing the expression string.
594 *
595 * Return: Success: Valid H5Z_node ptr to an expression tree.
596 * NULLure: NULL
597 *
598 * Programmer: Bill Wendling
599 * 26. August 2003
600 *
601 *-------------------------------------------------------------------------
602 */
603 static void *
H5Z_xform_parse(const char * expression,H5Z_datval_ptrs * dat_val_pointers)604 H5Z_xform_parse(const char *expression, H5Z_datval_ptrs* dat_val_pointers)
605 {
606 H5Z_token tok;
607 void *ret_value = NULL; /* Return value */
608
609 FUNC_ENTER_NOAPI(NULL)
610
611 if(!expression)
612 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "No expression provided?")
613
614 /* Set up the initial H5Z_token for parsing */
615 tok.tok_expr = tok.tok_begin = tok.tok_end = expression;
616
617 ret_value = (void*)H5Z_parse_expression(&tok, dat_val_pointers);
618
619 H5Z_xform_reduce_tree((H5Z_node*)ret_value);
620
621 done:
622 FUNC_LEAVE_NOAPI(ret_value)
623 }
624
625
626 /*-------------------------------------------------------------------------
627 * Function: H5Z_parse_expression
628 * Purpose: Beginning of the recursive descent parser to parse the
629 * expression. An expression is:
630 *
631 * expr := term | term '+' term | term '-' term
632 *
633 * Return: Success: Valid H5Z_node ptr to expression tree
634 * NULLure: NULL
635 * Programmer: Bill Wendling
636 * 26. August 2003
637 * Modifications:
638 * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
639 *
640 *-------------------------------------------------------------------------
641 */
642 static H5Z_node *
H5Z_parse_expression(H5Z_token * current,H5Z_datval_ptrs * dat_val_pointers)643 H5Z_parse_expression(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers)
644 {
645 H5Z_node *expr;
646 H5Z_node *ret_value = NULL; /* Return value */
647
648 FUNC_ENTER_NOAPI_NOINIT
649
650 expr = H5Z_parse_term(current, dat_val_pointers);
651
652 for (;;) {
653 H5Z_node *new_node;
654
655 current = H5Z_get_token(current);
656
657 switch(current->tok_type) {
658 case H5Z_XFORM_PLUS:
659 new_node = H5Z_new_node(H5Z_XFORM_PLUS);
660
661 if (!new_node) {
662 H5Z_xform_destroy_parse_tree(expr);
663 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
664 }
665
666 new_node->lchild = expr;
667 new_node->rchild = H5Z_parse_term(current, dat_val_pointers);
668
669 if (!new_node->rchild) {
670 H5Z_xform_destroy_parse_tree(new_node);
671 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
672 }
673
674 expr = new_node;
675 break;
676
677 case H5Z_XFORM_MINUS:
678 new_node = H5Z_new_node(H5Z_XFORM_MINUS);
679
680 if (!new_node) {
681 H5Z_xform_destroy_parse_tree(expr);
682 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
683 }
684
685 new_node->lchild = expr;
686 new_node->rchild = H5Z_parse_term(current, dat_val_pointers);
687
688 if (!new_node->rchild) {
689 H5Z_xform_destroy_parse_tree(new_node);
690 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
691 }
692
693 expr = new_node;
694 break;
695
696 case H5Z_XFORM_RPAREN:
697 H5Z_unget_token(current);
698 HGOTO_DONE(expr)
699
700 case H5Z_XFORM_END:
701 HGOTO_DONE(expr)
702
703 case H5Z_XFORM_ERROR:
704 case H5Z_XFORM_INTEGER:
705 case H5Z_XFORM_FLOAT:
706 case H5Z_XFORM_SYMBOL:
707 case H5Z_XFORM_MULT:
708 case H5Z_XFORM_DIVIDE:
709 case H5Z_XFORM_LPAREN:
710 default:
711 H5Z_xform_destroy_parse_tree(expr);
712 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
713 }
714 }
715
716 done:
717 FUNC_LEAVE_NOAPI(ret_value)
718 }
719
720
721 /*-------------------------------------------------------------------------
722 * Function: H5Z_parse_term
723 * Purpose: Parses a term in our expression language. A term is:
724 *
725 * term := factor | factor '*' factor | factor '/' factor
726 *
727 * Return: Success: Valid H5Z_node ptr to expression tree
728 * NULLure: NULL
729 * Programmer: Bill Wendling
730 * 26. August 2003
731 * Modifications:
732 * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
733 *
734 *-------------------------------------------------------------------------
735 */
736 static H5Z_node *
H5Z_parse_term(H5Z_token * current,H5Z_datval_ptrs * dat_val_pointers)737 H5Z_parse_term(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers)
738 {
739 H5Z_node *term = NULL;
740 H5Z_node *ret_value = NULL; /* Return value */
741
742 FUNC_ENTER_NOAPI_NOINIT
743
744 term = H5Z_parse_factor(current, dat_val_pointers);
745
746 for (;;) {
747 H5Z_node *new_node;
748
749 current = H5Z_get_token(current);
750
751 switch (current->tok_type) {
752 case H5Z_XFORM_MULT:
753 new_node = H5Z_new_node(H5Z_XFORM_MULT);
754
755 if (!new_node) {
756 H5Z_xform_destroy_parse_tree(term);
757 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
758 }
759
760 new_node->lchild = term;
761 new_node->rchild = H5Z_parse_factor(current, dat_val_pointers);
762
763 if (!new_node->rchild) {
764 H5Z_xform_destroy_parse_tree(new_node);
765 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
766 }
767
768 term = new_node;
769 break;
770
771 case H5Z_XFORM_DIVIDE:
772 new_node = H5Z_new_node(H5Z_XFORM_DIVIDE);
773
774 if (!new_node) {
775 H5Z_xform_destroy_parse_tree(term);
776 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
777 }
778
779 new_node->lchild = term;
780 new_node->rchild = H5Z_parse_factor(current, dat_val_pointers);
781 term = new_node;
782
783 if (!new_node->rchild) {
784 H5Z_xform_destroy_parse_tree(new_node);
785 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
786 }
787 break;
788
789 case H5Z_XFORM_RPAREN:
790 H5Z_unget_token(current);
791 HGOTO_DONE(term)
792
793 case H5Z_XFORM_END:
794 HGOTO_DONE(term)
795
796 case H5Z_XFORM_INTEGER:
797 case H5Z_XFORM_FLOAT:
798 case H5Z_XFORM_SYMBOL:
799 case H5Z_XFORM_PLUS:
800 case H5Z_XFORM_MINUS:
801 case H5Z_XFORM_LPAREN:
802 H5Z_unget_token(current);
803 HGOTO_DONE(term)
804
805 case H5Z_XFORM_ERROR:
806 default:
807 H5Z_xform_destroy_parse_tree(term);
808 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "bad transform type passed to data transform expression")
809 } /* end switch */
810 } /* end for */
811
812 done:
813 FUNC_LEAVE_NOAPI(ret_value)
814 }
815
816
817 /*-------------------------------------------------------------------------
818 * Function: H5Z_parse_factor
819 * Purpose: Parses a factor in our expression language. A factor is:
820 *
821 * factor := number | // C long or double
822 * symbol | // C identifier
823 * '-' factor | // unary minus
824 * '+' factor | // unary plus
825 * '(' expr ')'
826 *
827 * Return: Success: Valid H5Z_node ptr to expression tree
828 * NULLure: NULL
829 * Programmer: Bill Wendling
830 * 26. August 2003
831 * Modifications:
832 * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
833 *
834 *-------------------------------------------------------------------------
835 */
836 static H5Z_node *
H5Z_parse_factor(H5Z_token * current,H5Z_datval_ptrs * dat_val_pointers)837 H5Z_parse_factor(H5Z_token *current, H5Z_datval_ptrs* dat_val_pointers)
838 {
839 H5Z_node *factor=NULL;
840 H5Z_node *new_node;
841 H5Z_node *ret_value = NULL; /* Return value */
842
843 FUNC_ENTER_NOAPI_NOINIT
844
845 current = H5Z_get_token(current);
846
847 switch (current->tok_type) {
848 case H5Z_XFORM_INTEGER:
849 factor = H5Z_new_node(H5Z_XFORM_INTEGER);
850
851 if (!factor)
852 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
853 sscanf(current->tok_begin, "%ld", &factor->value.int_val);
854 break;
855
856 case H5Z_XFORM_FLOAT:
857 factor = H5Z_new_node(H5Z_XFORM_FLOAT);
858
859 if (!factor)
860 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
861 sscanf(current->tok_begin, "%lf", &factor->value.float_val);
862 break;
863
864 case H5Z_XFORM_SYMBOL:
865 factor = H5Z_new_node(H5Z_XFORM_SYMBOL);
866
867 if (!factor)
868 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
869
870 factor->value.dat_val = &(dat_val_pointers->ptr_dat_val[dat_val_pointers->num_ptrs]);
871 dat_val_pointers->num_ptrs++;
872 break;
873
874 case H5Z_XFORM_LPAREN:
875 factor = H5Z_parse_expression(current, dat_val_pointers);
876
877 if (!factor)
878 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Unable to allocate new node")
879
880 current = H5Z_get_token(current);
881
882 if (current->tok_type != H5Z_XFORM_RPAREN) {
883 H5Z_xform_destroy_parse_tree(factor);
884 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Syntax error in data transform expression")
885 }
886 break;
887
888 case H5Z_XFORM_RPAREN:
889 /* We shouldn't see a ) right now */
890 H5Z_xform_destroy_parse_tree(factor);
891 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Syntax error: unexpected ')' ")
892
893 case H5Z_XFORM_PLUS:
894 /* unary + */
895 new_node = H5Z_parse_factor(current, dat_val_pointers);
896
897 if (new_node) {
898 if (new_node->type != H5Z_XFORM_INTEGER && new_node->type != H5Z_XFORM_FLOAT &&
899 new_node->type != H5Z_XFORM_SYMBOL) {
900 H5Z_xform_destroy_parse_tree(new_node);
901 H5Z_xform_destroy_parse_tree(factor);
902 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
903 }
904
905 factor = new_node;
906 new_node = H5Z_new_node(H5Z_XFORM_PLUS);
907
908 if (!new_node) {
909 H5Z_xform_destroy_parse_tree(factor);
910 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
911 }
912
913 new_node->rchild = factor;
914 factor = new_node;
915 } else {
916 H5Z_xform_destroy_parse_tree(factor);
917 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
918 }
919 break;
920
921 case H5Z_XFORM_MINUS:
922 /* unary - */
923 new_node = H5Z_parse_factor(current, dat_val_pointers);
924
925 if (new_node) {
926 if (new_node->type != H5Z_XFORM_INTEGER && new_node->type != H5Z_XFORM_FLOAT &&
927 new_node->type != H5Z_XFORM_SYMBOL) {
928 H5Z_xform_destroy_parse_tree(new_node);
929 H5Z_xform_destroy_parse_tree(factor);
930 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
931 }
932
933 factor = new_node;
934 new_node = H5Z_new_node(H5Z_XFORM_MINUS);
935
936 if (!new_node) {
937 H5Z_xform_destroy_parse_tree(factor);
938 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
939 }
940
941 new_node->rchild = factor;
942 factor = new_node;
943 } else {
944 H5Z_xform_destroy_parse_tree(factor);
945 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error parsing data transform expression")
946 }
947 break;
948
949 case H5Z_XFORM_END:
950 break;
951
952 case H5Z_XFORM_MULT:
953 case H5Z_XFORM_DIVIDE:
954 case H5Z_XFORM_ERROR:
955 default:
956 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Invalid token while parsing data transform expression")
957
958 }
959
960 /* Set return value */
961 ret_value=factor;
962
963 done:
964 FUNC_LEAVE_NOAPI(ret_value);
965 }
966
967
968 /*-------------------------------------------------------------------------
969 * Function: H5Z_new_node
970 * Purpose: Create and initialize a new H5Z_node structure.
971 * Return: Success: Valid H5Z_node ptr
972 * NULLure: NULL
973 * Programmer: Bill Wendling
974 * 26. August 2003
975 * Modifications:
976 * Leon Arber: Added FUNC_ENTER / FUNC_LEAVE pairs
977 *
978 *-------------------------------------------------------------------------
979 */
980 static H5Z_node *
H5Z_new_node(H5Z_token_type type)981 H5Z_new_node(H5Z_token_type type)
982 {
983 H5Z_node *ret_value = NULL; /* Return value */
984
985 FUNC_ENTER_NOAPI_NOINIT
986
987 if(NULL == (ret_value = (H5Z_node *)H5MM_calloc(sizeof(H5Z_node))))
988 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to allocate space for nodes in the parse tree")
989
990 ret_value->type = type;
991
992 done:
993 FUNC_LEAVE_NOAPI(ret_value)
994 }
995
996
997 /*-------------------------------------------------------------------------
998 * Function: H5Z_xform_eval
999 * Purpose: If the transform is trivial, this function applies it.
1000 * Otherwise, it calls H5Z_xform_eval_full to do the full
1001 * transform.
1002 * Return: SUCCEED if transform applied successfully, FAIL otherwise
1003 * Programmer: Leon Arber
1004 * 5/1/04
1005 * Modifications:
1006 *
1007 *-------------------------------------------------------------------------
1008 */
1009 herr_t
H5Z_xform_eval(H5Z_data_xform_t * data_xform_prop,void * array,size_t array_size,const H5T_t * buf_type)1010 H5Z_xform_eval(H5Z_data_xform_t *data_xform_prop, void* array, size_t array_size, const H5T_t *buf_type)
1011 {
1012 H5Z_node *tree;
1013 hid_t array_type;
1014 H5Z_result res;
1015 size_t i;
1016 herr_t ret_value = SUCCEED; /* Return value */
1017
1018 FUNC_ENTER_NOAPI(FAIL)
1019
1020 HDassert(data_xform_prop);
1021
1022 tree = data_xform_prop->parse_root;
1023
1024 /* Get the datatype ID for the buffer's type */
1025 if((array_type = H5Z_xform_find_type(buf_type)) < 0)
1026 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Cannot perform data transform on this type.")
1027
1028 /* After this point, we're assured that the type of the array is handled by the eval code,
1029 * so we no longer have to check for valid types
1030 */
1031
1032 /* If it's a trivial data transform, perform it */
1033 if(tree->type == H5Z_XFORM_INTEGER || tree->type == H5Z_XFORM_FLOAT) {
1034 if(array_type == H5T_NATIVE_CHAR)
1035 H5Z_XFORM_DO_OP5(char, array_size)
1036 #if CHAR_MIN >= 0
1037 else if(array_type == H5T_NATIVE_SCHAR)
1038 H5Z_XFORM_DO_OP5(signed char, array_size)
1039 #else /* CHAR_MIN >= 0 */
1040 else if(array_type == H5T_NATIVE_UCHAR)
1041 H5Z_XFORM_DO_OP5(unsigned char, array_size)
1042 #endif /* CHAR_MIN >= 0 */
1043 else if(array_type == H5T_NATIVE_SHORT)
1044 H5Z_XFORM_DO_OP5(short, array_size)
1045 else if(array_type == H5T_NATIVE_USHORT)
1046 H5Z_XFORM_DO_OP5(unsigned short, array_size)
1047 else if(array_type == H5T_NATIVE_INT)
1048 H5Z_XFORM_DO_OP5(int, array_size)
1049 else if(array_type == H5T_NATIVE_UINT)
1050 H5Z_XFORM_DO_OP5(unsigned int, array_size)
1051 else if(array_type == H5T_NATIVE_LONG)
1052 H5Z_XFORM_DO_OP5(long, array_size)
1053 else if(array_type == H5T_NATIVE_ULONG)
1054 H5Z_XFORM_DO_OP5(unsigned long, array_size)
1055 else if(array_type == H5T_NATIVE_LLONG)
1056 H5Z_XFORM_DO_OP5(long long, array_size)
1057 else if(array_type == H5T_NATIVE_ULLONG)
1058 H5Z_XFORM_DO_OP5(unsigned long long, array_size)
1059 else if(array_type == H5T_NATIVE_FLOAT)
1060 H5Z_XFORM_DO_OP5(float, array_size)
1061 else if(array_type == H5T_NATIVE_DOUBLE)
1062 H5Z_XFORM_DO_OP5(double, array_size)
1063 #if H5_SIZEOF_LONG_DOUBLE !=0
1064 else if(array_type == H5T_NATIVE_LDOUBLE)
1065 H5Z_XFORM_DO_OP5(long double, array_size)
1066 #endif
1067
1068 } /* end if */
1069 /* Otherwise, do the full data transform */
1070 else {
1071 /* Optimization for linear transform: */
1072 if(data_xform_prop->dat_val_pointers->num_ptrs == 1)
1073 data_xform_prop->dat_val_pointers->ptr_dat_val[0] = array;
1074
1075 /* If it's a quadratic transform, we have no choice but to store multiple copies of the data */
1076 else {
1077 for(i = 0; i < data_xform_prop->dat_val_pointers->num_ptrs; i++) {
1078 if(NULL == (data_xform_prop->dat_val_pointers->ptr_dat_val[i] = (void*)H5MM_malloc(array_size * H5T_get_size((H5T_t *)H5I_object(array_type)))))
1079 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "Ran out of memory trying to allocate space for data in data transform")
1080
1081 HDmemcpy(data_xform_prop->dat_val_pointers->ptr_dat_val[i], array, array_size * H5T_get_size((H5T_t *)H5I_object(array_type)));
1082 } /* end for */
1083 } /* end else */
1084
1085 if(H5Z_xform_eval_full(tree, array_size, array_type, &res) < 0)
1086 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform")
1087
1088 if(data_xform_prop->dat_val_pointers->num_ptrs > 1)
1089 HDmemcpy(array, res.value.dat_val, array_size * H5T_get_size((H5T_t *)H5I_object(array_type)));
1090
1091 /* Free the temporary arrays we used */
1092 if(data_xform_prop->dat_val_pointers->num_ptrs > 1)
1093 for(i=0; i<data_xform_prop->dat_val_pointers->num_ptrs; i++)
1094 H5MM_xfree(data_xform_prop->dat_val_pointers->ptr_dat_val[i]);
1095 } /* end else */
1096
1097 done:
1098 if(ret_value < 0) {
1099 /* If we ran out of memory above copying the array for temp storage (which we easily can for
1100 * polynomial transforms of high order) we free those arrays which we already allocated */
1101 if(data_xform_prop->dat_val_pointers->num_ptrs > 1)
1102 for(i = 0; i < data_xform_prop->dat_val_pointers->num_ptrs; i++)
1103 if(data_xform_prop->dat_val_pointers->ptr_dat_val[i])
1104 H5MM_xfree(data_xform_prop->dat_val_pointers->ptr_dat_val[i]);
1105 } /* end if */
1106
1107 FUNC_LEAVE_NOAPI(ret_value)
1108 } /* end H5Z_xform_eval() */
1109
1110
1111 /*-------------------------------------------------------------------------
1112 * Function: H5Z_xform_eval_full
1113 * Purpose: Does a full evaluation of the parse tree contained in tree
1114 * and applies this transform to array.
1115 * Return: Nothing
1116 * Programmer: Leon Arber
1117 * 5/1/04
1118 * Modifications:
1119 *
1120 *
1121 * Notes: In the case of a polynomial data transform (ie, the left and right subtree
1122 * are both of type H5Z_XFORM_SYMBOL), the convention is that the left hand side
1123 * will accumulate changes and, at the end, the new data will be copied from the lhs.
1124 *-------------------------------------------------------------------------
1125 */
1126 static herr_t
H5Z_xform_eval_full(H5Z_node * tree,const size_t array_size,const hid_t array_type,H5Z_result * res)1127 H5Z_xform_eval_full(H5Z_node *tree, const size_t array_size, const hid_t array_type, H5Z_result *res)
1128 {
1129 H5Z_result resl, resr;
1130 herr_t ret_value = SUCCEED; /* Return value */
1131
1132 FUNC_ENTER_NOAPI_NOINIT
1133
1134 /* check args */
1135 HDassert(tree);
1136
1137 HDmemset(&resl, 0, sizeof(H5Z_result));
1138 HDmemset(&resr, 0, sizeof(H5Z_result));
1139
1140 if (tree->type == H5Z_XFORM_INTEGER) {
1141 res->type = H5Z_XFORM_INTEGER;
1142 res->value.int_val = tree->value.int_val;
1143 } /* end if */
1144 else if (tree->type == H5Z_XFORM_FLOAT) {
1145 res->type = H5Z_XFORM_FLOAT;
1146 res->value.float_val = tree->value.float_val;
1147 } /* end if */
1148 else if (tree->type == H5Z_XFORM_SYMBOL) {
1149 res->type = H5Z_XFORM_SYMBOL;
1150
1151 /*since dat_val stores the address of the array which is really stored in the dat_val_pointers,
1152 * here we make dat_val store a pointer to the array itself instead of the address of it so that the
1153 * rest of the code below works normally. */
1154 res->value.dat_val = *((void**)(tree->value.dat_val));
1155 } /* end if */
1156 else {
1157 if(tree->lchild && H5Z_xform_eval_full(tree->lchild, array_size, array_type, &resl) < 0)
1158 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform")
1159 if(H5Z_xform_eval_full(tree->rchild, array_size, array_type, &resr) < 0)
1160 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error while performing data transform")
1161
1162 res->type = H5Z_XFORM_SYMBOL;
1163
1164 /* For each type of operation:
1165 * 1. See if "x" is on left hand side, right hand side, or if both sides are "x"
1166 * 2. Figure out what type of data we're going to be manipulating
1167 * 3. Do the operation on the data. */
1168 switch (tree->type) {
1169 case H5Z_XFORM_PLUS:
1170 H5Z_XFORM_TYPE_OP(resl, resr, array_type, +, array_size)
1171 break;
1172
1173 case H5Z_XFORM_MINUS:
1174 H5Z_XFORM_TYPE_OP(resl, resr, array_type, -, array_size)
1175 break;
1176
1177 case H5Z_XFORM_MULT:
1178 H5Z_XFORM_TYPE_OP(resl, resr, array_type, *, array_size)
1179 break;
1180
1181 case H5Z_XFORM_DIVIDE:
1182 H5Z_XFORM_TYPE_OP(resl, resr, array_type, /, array_size)
1183 break;
1184
1185 case H5Z_XFORM_ERROR:
1186 case H5Z_XFORM_INTEGER:
1187 case H5Z_XFORM_FLOAT:
1188 case H5Z_XFORM_SYMBOL:
1189 case H5Z_XFORM_LPAREN:
1190 case H5Z_XFORM_RPAREN:
1191 case H5Z_XFORM_END:
1192 default:
1193 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "Invalid expression tree")
1194 } /* end switch */
1195
1196 /* The result stores a pointer to the new data */
1197 /* So, if the left hand side got its data modified, the result stores a pointers
1198 * to the left hand side's data, ditto for rhs */
1199 if(resl.type == H5Z_XFORM_SYMBOL)
1200 res->value.dat_val = resl.value.dat_val;
1201 else if(resr.type == H5Z_XFORM_SYMBOL)
1202 res->value.dat_val = resr.value.dat_val;
1203 else
1204 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "error during transform evaluation")
1205 } /* end else */
1206
1207 done:
1208 FUNC_LEAVE_NOAPI(ret_value)
1209 } /* end H5Z_xform_eval_full() */
1210
1211
1212 /*-------------------------------------------------------------------------
1213 * Function: H5Z_find_type
1214 * Return: Native type of datatype that is passed in
1215 * Programmer: Leon Arber, 4/20/04
1216 * Modifications:
1217 *
1218 *
1219 *-------------------------------------------------------------------------
1220 */
1221 static hid_t
H5Z_xform_find_type(const H5T_t * type)1222 H5Z_xform_find_type(const H5T_t* type)
1223 {
1224 H5T_t *tmp; /* Temporary datatype */
1225 hid_t ret_value = SUCCEED; /* Return value */
1226
1227 FUNC_ENTER_NOAPI_NOINIT
1228
1229 HDassert(type);
1230
1231 /* Check for SHORT type */
1232 if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_SHORT))
1233 && 0 == H5T_cmp(type, tmp, FALSE))
1234 HGOTO_DONE(H5T_NATIVE_SHORT)
1235 /* Check for INT type */
1236 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_INT))
1237 && 0 == H5T_cmp(type, tmp, FALSE))
1238 HGOTO_DONE(H5T_NATIVE_INT)
1239 /* Check for LONG type */
1240 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_LONG))
1241 && 0 == H5T_cmp(type, tmp, FALSE))
1242 HGOTO_DONE(H5T_NATIVE_LONG)
1243 /* Check for LONGLONG type */
1244 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_LLONG))
1245 && 0 == H5T_cmp(type, tmp, FALSE))
1246 HGOTO_DONE(H5T_NATIVE_LLONG)
1247 /* Check for UCHAR type */
1248 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_UCHAR))
1249 && 0 == H5T_cmp(type, tmp, FALSE))
1250 HGOTO_DONE(H5T_NATIVE_UCHAR)
1251 /* Check for CHAR type */
1252 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_CHAR))
1253 && 0 == H5T_cmp(type, tmp, FALSE))
1254 HGOTO_DONE(H5T_NATIVE_CHAR)
1255 /* Check for SCHAR type */
1256 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_SCHAR))
1257 && 0 == H5T_cmp(type, tmp, FALSE))
1258 HGOTO_DONE(H5T_NATIVE_SCHAR)
1259 /* Check for USHORT type */
1260 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_USHORT))
1261 && 0 == H5T_cmp(type, tmp, FALSE))
1262 HGOTO_DONE(H5T_NATIVE_USHORT)
1263 /* Check for UINT type */
1264 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_UINT))
1265 && 0 == H5T_cmp(type, tmp, FALSE))
1266 HGOTO_DONE(H5T_NATIVE_UINT)
1267 /* Check for ULONG type */
1268 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_ULONG))
1269 && 0 == H5T_cmp(type, tmp, FALSE))
1270 HGOTO_DONE(H5T_NATIVE_ULONG)
1271 /* Check for ULONGLONG type */
1272 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_ULLONG))
1273 && 0 == H5T_cmp(type, tmp, FALSE))
1274 HGOTO_DONE(H5T_NATIVE_ULLONG)
1275 /* Check for FLOAT type */
1276 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_FLOAT))
1277 && 0 == H5T_cmp(type, tmp, FALSE))
1278 HGOTO_DONE(H5T_NATIVE_FLOAT)
1279 /* Check for DOUBLE type */
1280 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_DOUBLE))
1281 && 0 == H5T_cmp(type, tmp, FALSE))
1282 HGOTO_DONE(H5T_NATIVE_DOUBLE)
1283 #if H5_SIZEOF_LONG_DOUBLE !=0
1284 /* Check for LONGDOUBLE type */
1285 else if((tmp = (H5T_t *)H5I_object(H5T_NATIVE_LDOUBLE))
1286 && 0 == H5T_cmp(type, tmp, FALSE))
1287 HGOTO_DONE(H5T_NATIVE_LDOUBLE)
1288 #endif
1289 else
1290 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "could not find matching type")
1291
1292 done:
1293 FUNC_LEAVE_NOAPI(ret_value)
1294 } /* end H5Z_xform_find_type() */
1295
1296
1297 /*-------------------------------------------------------------------------
1298 * Function: H5Z_xform_copy_tree
1299 * Purpose: Makes a copy of the parse tree passed in.
1300 * Return: A pointer to a root for a new parse tree which is a copy
1301 * of the one passed in.
1302 * Programmer: Leon Arber
1303 * April 1, 2004.
1304 * Modifications:
1305 *
1306 *-------------------------------------------------------------------------
1307 */
1308 static void *
H5Z_xform_copy_tree(H5Z_node * tree,H5Z_datval_ptrs * dat_val_pointers,H5Z_datval_ptrs * new_dat_val_pointers)1309 H5Z_xform_copy_tree(H5Z_node* tree, H5Z_datval_ptrs* dat_val_pointers, H5Z_datval_ptrs* new_dat_val_pointers)
1310 {
1311 H5Z_node* ret_value=NULL;
1312
1313 FUNC_ENTER_NOAPI(NULL)
1314
1315 HDassert(tree);
1316
1317 if(tree->type == H5Z_XFORM_INTEGER)
1318 {
1319 if ((ret_value = (H5Z_node*) H5MM_malloc(sizeof(H5Z_node))) == NULL)
1320 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
1321 else
1322 {
1323 ret_value -> type = H5Z_XFORM_INTEGER;
1324 ret_value ->value.int_val = tree->value.int_val;
1325 ret_value -> lchild = NULL;
1326 ret_value -> rchild = NULL;
1327 }
1328 }
1329 else if (tree->type == H5Z_XFORM_FLOAT)
1330 {
1331 if ((ret_value = (H5Z_node*) H5MM_malloc(sizeof(H5Z_node))) == NULL)
1332 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
1333 else
1334 {
1335 ret_value -> type = H5Z_XFORM_FLOAT;
1336 ret_value ->value.float_val = tree->value.float_val;
1337 ret_value -> lchild = NULL;
1338 ret_value -> rchild = NULL;
1339 }
1340 }
1341 else if(tree->type == H5Z_XFORM_SYMBOL)
1342 {
1343 if ((ret_value = (H5Z_node*) H5MM_malloc(sizeof(H5Z_node))) == NULL)
1344 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "Ran out of memory trying to copy parse tree")
1345 else
1346 {
1347 ret_value -> type = H5Z_XFORM_SYMBOL;
1348
1349 ret_value -> value.dat_val = &(new_dat_val_pointers->ptr_dat_val[new_dat_val_pointers->num_ptrs]);
1350 new_dat_val_pointers->num_ptrs++;
1351 ret_value -> lchild = NULL;
1352 ret_value -> rchild = NULL;
1353 }
1354 }
1355 else if(tree->type == H5Z_XFORM_MULT)
1356 H5Z_XFORM_DO_OP4(H5Z_XFORM_MULT)
1357 else if(tree->type == H5Z_XFORM_PLUS)
1358 H5Z_XFORM_DO_OP4(H5Z_XFORM_PLUS)
1359 else if(tree->type == H5Z_XFORM_MINUS)
1360 H5Z_XFORM_DO_OP4(H5Z_XFORM_MINUS)
1361 else if(tree->type == H5Z_XFORM_DIVIDE)
1362 H5Z_XFORM_DO_OP4(H5Z_XFORM_DIVIDE)
1363 else
1364 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, NULL, "Error in parse tree while trying to copy")
1365
1366 done:
1367 FUNC_LEAVE_NOAPI(ret_value)
1368 }
1369
1370
1371 /*-------------------------------------------------------------------------
1372 * Function: H5Z_op_is_numbs
1373 * Purpose: Internal function to facilitate the condition check in
1374 * H5Z_xform_reduce_tree to reduce the bulkiness of the code.
1375 * Return: TRUE or FALSE
1376 * Programmer: Raymond Lu
1377 * 15 March 2012
1378 * Modifications:
1379 *
1380 *-------------------------------------------------------------------------
1381 */
1382 static hbool_t
H5Z_op_is_numbs(H5Z_node * _tree)1383 H5Z_op_is_numbs(H5Z_node* _tree)
1384 {
1385 hbool_t ret_value = FALSE;
1386
1387 FUNC_ENTER_NOAPI_NOINIT_NOERR
1388
1389 HDassert(_tree);
1390
1391 if(((_tree->lchild->type == H5Z_XFORM_INTEGER) || (_tree->lchild->type == H5Z_XFORM_FLOAT)) && ((_tree->rchild->type == H5Z_XFORM_INTEGER) || (_tree->rchild->type == H5Z_XFORM_FLOAT)))
1392 ret_value = TRUE;
1393
1394 FUNC_LEAVE_NOAPI(ret_value)
1395 }
1396
1397
1398 /*-------------------------------------------------------------------------
1399 * Function: H5Z_op_is_numbs2
1400 * Purpose: Internal function to facilitate the condition check in
1401 * H5Z_xform_reduce_tree to reduce the bulkiness of the code.
1402 * The difference from H5Z_op_is_numbs is that the left child
1403 * can be empty, like -x or +x.
1404 * Return: TRUE or FALSE
1405 * Programmer: Raymond Lu
1406 * 15 March 2012
1407 * Modifications:
1408 *
1409 *-------------------------------------------------------------------------
1410 */
1411 static hbool_t
H5Z_op_is_numbs2(H5Z_node * _tree)1412 H5Z_op_is_numbs2(H5Z_node* _tree)
1413 {
1414 hbool_t ret_value = FALSE;
1415
1416 FUNC_ENTER_NOAPI_NOINIT_NOERR
1417
1418 HDassert(_tree);
1419
1420 if((!_tree->lchild && ((_tree->rchild->type == H5Z_XFORM_INTEGER) || (_tree->rchild->type == H5Z_XFORM_FLOAT))) ||
1421 ((_tree->lchild && ((_tree->lchild->type == H5Z_XFORM_INTEGER) || (_tree->lchild->type == H5Z_XFORM_FLOAT))) && (_tree->rchild && ((_tree->rchild->type == H5Z_XFORM_INTEGER) || (_tree->rchild->type == H5Z_XFORM_FLOAT)))))
1422 ret_value = TRUE;
1423
1424 FUNC_LEAVE_NOAPI(ret_value)
1425 }
1426
1427
1428 /*-------------------------------------------------------------------------
1429 * Function: H5Z_xform_reduce_tree
1430 * Purpose: Simplifies parse tree passed in by performing any obvious
1431 * and trivial arithemtic calculations.
1432 *
1433 * Return: None.
1434 * Programmer: Leon Arber
1435 * April 1, 2004.
1436 * Modifications:
1437 *
1438 *-------------------------------------------------------------------------
1439 */
1440 static void
H5Z_xform_reduce_tree(H5Z_node * tree)1441 H5Z_xform_reduce_tree(H5Z_node* tree)
1442 {
1443 FUNC_ENTER_NOAPI_NOINIT_NOERR
1444
1445 if(tree) {
1446 if((tree->type == H5Z_XFORM_DIVIDE) || (tree->type == H5Z_XFORM_MULT))
1447 {
1448 if(H5Z_op_is_numbs(tree))
1449 H5Z_do_op(tree);
1450 else
1451 {
1452 H5Z_xform_reduce_tree(tree->lchild);
1453 if(H5Z_op_is_numbs(tree))
1454 H5Z_do_op(tree);
1455 else {
1456 H5Z_xform_reduce_tree(tree->rchild);
1457 if(H5Z_op_is_numbs(tree))
1458 H5Z_do_op(tree);
1459 }
1460 }
1461 } else if((tree->type == H5Z_XFORM_PLUS) || (tree->type == H5Z_XFORM_MINUS)) {
1462 if(H5Z_op_is_numbs2(tree))
1463 H5Z_do_op(tree);
1464 else
1465 {
1466 H5Z_xform_reduce_tree(tree->lchild);
1467 if(H5Z_op_is_numbs2(tree))
1468 H5Z_do_op(tree);
1469 else {
1470 H5Z_xform_reduce_tree(tree->rchild);
1471 if(H5Z_op_is_numbs2(tree))
1472 H5Z_do_op(tree);
1473 }
1474 }
1475 }
1476
1477 }
1478
1479 FUNC_LEAVE_NOAPI_VOID;
1480 }
1481
1482
1483 /*-------------------------------------------------------------------------
1484 * Function: H5Z_do_op
1485 * Purpose: If the root of the tree passed in points to a simple
1486 * arithmetic operation and the left and right subtrees are both
1487 * integer or floating point values, this function does that
1488 * operation, free the left and right subtrees, and replaces
1489 * the root with the result of the operation.
1490 * Return: None.
1491 * Programmer: Leon Arber
1492 * April 1, 2004.
1493 * Modifications:
1494 * Raymond Lu
1495 * 15 March 2012
1496 * I added a new macro H5Z_XFORM_DO_OP6 to handle the special
1497 * operations like -x or +x when the left operand is empty.
1498 *
1499 *-------------------------------------------------------------------------
1500 */
1501 static void
H5Z_do_op(H5Z_node * tree)1502 H5Z_do_op(H5Z_node* tree)
1503 {
1504 FUNC_ENTER_NOAPI_NOINIT_NOERR
1505
1506 if(tree->type == H5Z_XFORM_DIVIDE)
1507 H5Z_XFORM_DO_OP3(/)
1508 else if(tree->type == H5Z_XFORM_MULT)
1509 H5Z_XFORM_DO_OP3(*)
1510 else if(tree->type == H5Z_XFORM_PLUS)
1511 H5Z_XFORM_DO_OP6(+)
1512 else if(tree->type == H5Z_XFORM_MINUS)
1513 H5Z_XFORM_DO_OP6(-)
1514
1515 FUNC_LEAVE_NOAPI_VOID;
1516 }
1517
1518
1519 /*-------------------------------------------------------------------------
1520 * Function: H5D_xform_create
1521 *
1522 * Purpose: Create a new data transform object from a string.
1523 *
1524 * Return:
1525 * Success: SUCCEED
1526 * Failure: FAIL
1527 *
1528 * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu
1529 *
1530 * Date: May 4, 2004
1531 *
1532 * Comments:
1533 *
1534 * Modifications:
1535 *
1536 *-------------------------------------------------------------------------
1537 */
1538 H5Z_data_xform_t *
H5Z_xform_create(const char * expr)1539 H5Z_xform_create(const char *expr)
1540 {
1541 H5Z_data_xform_t *data_xform_prop = NULL;
1542 unsigned int i;
1543 unsigned int count = 0;
1544 H5Z_data_xform_t *ret_value = NULL; /* Return value */
1545
1546 FUNC_ENTER_NOAPI(NULL)
1547
1548 HDassert(expr);
1549
1550 /* Allocate space for the data transform information */
1551 if(NULL == (data_xform_prop = (H5Z_data_xform_t *)H5MM_calloc(sizeof(H5Z_data_xform_t))))
1552 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory for data transform info")
1553
1554 if(NULL == (data_xform_prop->dat_val_pointers = (H5Z_datval_ptrs *)H5MM_malloc(sizeof(H5Z_datval_ptrs))))
1555 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory for data transform array storage")
1556
1557 /* copy the user's string into the property */
1558 if(NULL == (data_xform_prop->xform_exp = (char *)H5MM_xstrdup(expr)))
1559 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory for data transform expression")
1560
1561 /* Find the number of times "x" is used in this equation, and allocate room for storing that many points */
1562 for(i = 0; i < HDstrlen(expr); i++)
1563 if(HDisalpha(expr[i]))
1564 count++;
1565
1566 /* When there are no "x"'s in the equation (ie, simple transform case),
1567 * we don't need to allocate any space since no array will have to be
1568 * stored */
1569 if(count > 0)
1570 if(NULL == (data_xform_prop->dat_val_pointers->ptr_dat_val = (void **)H5MM_calloc(count * sizeof(void *))))
1571 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to allocate memory for pointers in transform array")
1572
1573 /* Initialize the num_ptrs field, which will be used to keep track of the number of copies
1574 * of the data we have for polynomial transforms */
1575 data_xform_prop->dat_val_pointers->num_ptrs = 0;
1576
1577 /* we generate the parse tree right here and store a pointer to its root in the property. */
1578 if((data_xform_prop->parse_root = (H5Z_node *)H5Z_xform_parse(expr, data_xform_prop->dat_val_pointers))==NULL)
1579 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "unable to generate parse tree from expression")
1580
1581 /* Sanity check
1582 * count should be the same num_ptrs */
1583 if(count != data_xform_prop->dat_val_pointers->num_ptrs)
1584 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, NULL, "error copying the parse tree, did not find correct number of \"variables\"")
1585
1586 /* Assign return value */
1587 ret_value=data_xform_prop;
1588
1589
1590 done:
1591 /* Clean up on error */
1592 if(ret_value==NULL) {
1593 if(data_xform_prop) {
1594 if(data_xform_prop->parse_root)
1595 H5Z_xform_destroy_parse_tree(data_xform_prop->parse_root);
1596 if(data_xform_prop->xform_exp)
1597 H5MM_xfree(data_xform_prop->xform_exp);
1598 if(count > 0 && data_xform_prop->dat_val_pointers->ptr_dat_val)
1599 H5MM_xfree(data_xform_prop->dat_val_pointers->ptr_dat_val);
1600 if(data_xform_prop->dat_val_pointers)
1601 H5MM_xfree(data_xform_prop->dat_val_pointers);
1602 H5MM_xfree(data_xform_prop);
1603 } /* end if */
1604 } /* end if */
1605
1606 FUNC_LEAVE_NOAPI(ret_value)
1607 } /* H5Z_xform_create() */
1608
1609
1610 /*-------------------------------------------------------------------------
1611 * Function: H5Z_xform_destroy
1612 *
1613 * Purpose: Destroy a data transform object.
1614 *
1615 * Return:
1616 * Success: SUCCEED
1617 * Failure: FAIL
1618 *
1619 * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu
1620 *
1621 * Date: May 4, 2004
1622 *
1623 * Comments:
1624 *
1625 * Modifications:
1626 *
1627 *-------------------------------------------------------------------------
1628 */
1629 herr_t
H5Z_xform_destroy(H5Z_data_xform_t * data_xform_prop)1630 H5Z_xform_destroy(H5Z_data_xform_t *data_xform_prop)
1631 {
1632 FUNC_ENTER_NOAPI_NOINIT_NOERR
1633
1634 if(data_xform_prop) {
1635 /* Destroy the parse tree */
1636 H5Z_xform_destroy_parse_tree(data_xform_prop->parse_root);
1637
1638 /* Free the expression */
1639 H5MM_xfree(data_xform_prop->xform_exp);
1640
1641 /* Free the pointers to the temp. arrays, if there are any */
1642 if(data_xform_prop->dat_val_pointers->num_ptrs > 0)
1643 H5MM_xfree(data_xform_prop->dat_val_pointers->ptr_dat_val);
1644
1645 /* Free the data storage struct */
1646 H5MM_xfree(data_xform_prop->dat_val_pointers);
1647
1648 /* Free the node */
1649 H5MM_xfree(data_xform_prop);
1650 } /* end if */
1651
1652 FUNC_LEAVE_NOAPI(SUCCEED)
1653 } /* H5Z_xform_destroy() */
1654
1655
1656 /*-------------------------------------------------------------------------
1657 * Function: H5Z_xform_copy
1658 *
1659 * Purpose: Clone a data transform object.
1660 *
1661 * Return:
1662 * Success: SUCCEED
1663 * Failure: FAIL
1664 *
1665 * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu
1666 *
1667 * Date: May 4, 2004
1668 *
1669 * Comments: This is an "in-place" copy, since this routine gets called
1670 * after the top-level copy has been performed and this routine finishes
1671 * the "deep" part of the copy.
1672 *
1673 *-------------------------------------------------------------------------
1674 */
1675 herr_t
H5Z_xform_copy(H5Z_data_xform_t ** data_xform_prop)1676 H5Z_xform_copy(H5Z_data_xform_t **data_xform_prop)
1677 {
1678 unsigned int i;
1679 unsigned int count = 0;
1680 H5Z_data_xform_t *new_data_xform_prop=NULL;
1681 herr_t ret_value=SUCCEED;
1682
1683 FUNC_ENTER_NOAPI(FAIL)
1684
1685 if(*data_xform_prop) {
1686 /* Allocate new node */
1687 if(NULL == (new_data_xform_prop = (H5Z_data_xform_t *)H5MM_calloc(sizeof(H5Z_data_xform_t))))
1688 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory for data transform info")
1689
1690 /* Copy string */
1691 if(NULL == (new_data_xform_prop->xform_exp = (char *)H5MM_xstrdup((*data_xform_prop)->xform_exp)))
1692 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory for data transform expression")
1693
1694 if(NULL == (new_data_xform_prop->dat_val_pointers = (H5Z_datval_ptrs *)H5MM_malloc(sizeof(H5Z_datval_ptrs))))
1695 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory for data transform array storage")
1696
1697 /* Find the number of times "x" is used in this equation, and allocate room for storing that many points */
1698 for(i = 0; i < HDstrlen(new_data_xform_prop->xform_exp); i++)
1699 if(HDisalpha(new_data_xform_prop->xform_exp[i]))
1700 count++;
1701
1702 if(count > 0)
1703 if(NULL == (new_data_xform_prop->dat_val_pointers->ptr_dat_val = (void **)H5MM_calloc(count * sizeof(void *))))
1704 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "unable to allocate memory for pointers in transform array")
1705
1706 /* Zero out num_pointers prior to H5Z_xform_cop_tree call; that call will increment it to the right amount */
1707 new_data_xform_prop->dat_val_pointers->num_ptrs = 0;
1708
1709 /* Copy parse tree */
1710 if((new_data_xform_prop->parse_root = (H5Z_node*)H5Z_xform_copy_tree((*data_xform_prop)->parse_root, (*data_xform_prop)->dat_val_pointers, new_data_xform_prop->dat_val_pointers)) == NULL)
1711 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "error copying the parse tree")
1712
1713 /* Sanity check
1714 * count should be the same num_ptrs */
1715 if(count != new_data_xform_prop->dat_val_pointers->num_ptrs)
1716 HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "error copying the parse tree, did not find correct number of \"variables\"")
1717
1718 /* Copy new information on top of old information */
1719 *data_xform_prop=new_data_xform_prop;
1720 } /* end if */
1721
1722 done:
1723 /* Clean up on error */
1724 if(ret_value<0) {
1725 if(new_data_xform_prop) {
1726 if(new_data_xform_prop->parse_root)
1727 H5Z_xform_destroy_parse_tree(new_data_xform_prop->parse_root);
1728 if(new_data_xform_prop->xform_exp)
1729 H5MM_xfree(new_data_xform_prop->xform_exp);
1730 H5MM_xfree(new_data_xform_prop);
1731 } /* end if */
1732 } /* end if */
1733
1734 FUNC_LEAVE_NOAPI(ret_value)
1735 } /* H5Z_xform_copy() */
1736
1737
1738 /*-------------------------------------------------------------------------
1739 * Function: H5Z_xform_noop
1740 *
1741 * Purpose: Checks if a data transform will be performed
1742 *
1743 * Return: TRUE for no data transform, FALSE for a data transform
1744 *
1745 * Programmer: Quincey Koziol, koziol@ncsa.uiuc.edu
1746 *
1747 * Date: May 4, 2004
1748 *
1749 * Comments: Can't fail
1750 *
1751 * Modifications:
1752 *
1753 *-------------------------------------------------------------------------
1754 */
1755 hbool_t
H5Z_xform_noop(const H5Z_data_xform_t * data_xform_prop)1756 H5Z_xform_noop(const H5Z_data_xform_t *data_xform_prop)
1757 {
1758 hbool_t ret_value = FALSE; /* Return value */
1759
1760 FUNC_ENTER_NOAPI_NOINIT_NOERR
1761
1762 ret_value=(data_xform_prop ? FALSE : TRUE);
1763
1764 FUNC_LEAVE_NOAPI(ret_value)
1765 } /* H5Z_xform_noop() */
1766
1767
1768 /*-------------------------------------------------------------------------
1769 * Function: H5Z_xform_extract_xform_str
1770 *
1771 * Purpose: Extracts the pointer to the data transform strings from the
1772 * data transform property.`
1773 * Return:
1774 * Pointer to a copy of the string in the data_xform property.
1775 *
1776 * Programmer: Leon Arber, larber@ncsa.uiuc.edu
1777 *
1778 * Date: Sept. 4, 2004
1779 *
1780 * Modifications:
1781 *
1782 *-------------------------------------------------------------------------
1783 */
1784 const char *
H5Z_xform_extract_xform_str(const H5Z_data_xform_t * data_xform_prop)1785 H5Z_xform_extract_xform_str(const H5Z_data_xform_t *data_xform_prop)
1786 {
1787 FUNC_ENTER_NOAPI_NOINIT_NOERR
1788
1789 /* There should be no way that this can be NULL since the function
1790 * that calls this one checks to make sure it isn't before
1791 * pasing them */
1792 HDassert(data_xform_prop);
1793
1794 FUNC_LEAVE_NOAPI(data_xform_prop->xform_exp)
1795 } /* H5Z_xform_extract_xform_str() */
1796
1797