/src/hdf5/src/H5Pencdec.c
Line | Count | Source |
1 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | | * Copyright by The HDF Group. * |
3 | | * All rights reserved. * |
4 | | * * |
5 | | * This file is part of HDF5. The full HDF5 copyright notice, including * |
6 | | * terms governing use, modification, and redistribution, is contained in * |
7 | | * the LICENSE file, which can be found at the root of the source code * |
8 | | * distribution tree, or in https://www.hdfgroup.org/licenses. * |
9 | | * If you do not have access to either file, you may request a copy from * |
10 | | * help@hdfgroup.org. * |
11 | | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
12 | | |
13 | | /* |
14 | | * Purpose: Generic Property Functions |
15 | | */ |
16 | | |
17 | | /****************/ |
18 | | /* Module Setup */ |
19 | | /****************/ |
20 | | |
21 | | #include "H5Pmodule.h" /* This source code file is part of the H5P module */ |
22 | | |
23 | | /***********/ |
24 | | /* Headers */ |
25 | | /***********/ |
26 | | #include "H5private.h" /* Generic Functions */ |
27 | | #include "H5Eprivate.h" /* Error handling */ |
28 | | #include "H5Iprivate.h" /* IDs */ |
29 | | #include "H5MMprivate.h" /* Memory management */ |
30 | | #include "H5Ppkg.h" /* Property lists */ |
31 | | #include "H5VMprivate.h" /* Vector functions */ |
32 | | |
33 | | /****************/ |
34 | | /* Local Macros */ |
35 | | /****************/ |
36 | | |
37 | | /* Version # of encoded property lists */ |
38 | 0 | #define H5P_ENCODE_VERS 0 |
39 | | |
40 | | /******************/ |
41 | | /* Local Typedefs */ |
42 | | /******************/ |
43 | | |
44 | | /* Typedef for iterator when encoding a property list */ |
45 | | typedef struct { |
46 | | bool encode; /* Whether the property list should be encoded */ |
47 | | size_t *enc_size_ptr; /* Pointer to size of encoded buffer */ |
48 | | void **pp; /* Pointer to encoding buffer pointer */ |
49 | | } H5P_enc_iter_ud_t; |
50 | | |
51 | | /********************/ |
52 | | /* Local Prototypes */ |
53 | | /********************/ |
54 | | |
55 | | /*********************/ |
56 | | /* Package Variables */ |
57 | | /*********************/ |
58 | | |
59 | | /*****************************/ |
60 | | /* Library Private Variables */ |
61 | | /*****************************/ |
62 | | |
63 | | /*******************/ |
64 | | /* Local Variables */ |
65 | | /*******************/ |
66 | | |
67 | | /*------------------------------------------------------------------------- |
68 | | * Function: H5P__encode_size_t |
69 | | * |
70 | | * Purpose: Generic encoding callback routine for 'size_t' properties. |
71 | | * |
72 | | * Return: Success: Non-negative |
73 | | * Failure: Negative |
74 | | * |
75 | | *------------------------------------------------------------------------- |
76 | | */ |
77 | | herr_t |
78 | | H5P__encode_size_t(const void *value, void **_pp, size_t *size) |
79 | 0 | { |
80 | 0 | uint64_t enc_value = (uint64_t) * (const size_t *)value; /* Property value to encode */ |
81 | 0 | uint8_t **pp = (uint8_t **)_pp; |
82 | 0 | unsigned enc_size = H5VM_limit_enc_size(enc_value); /* Size of encoded property */ |
83 | |
|
84 | 0 | FUNC_ENTER_PACKAGE_NOERR |
85 | | |
86 | | /* Sanity checks */ |
87 | 0 | HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t)); |
88 | 0 | assert(enc_size < 256); |
89 | 0 | assert(size); |
90 | |
|
91 | 0 | if (NULL != *pp) { |
92 | | /* Encode the size */ |
93 | 0 | *(*pp)++ = (uint8_t)enc_size; |
94 | | |
95 | | /* Encode the value */ |
96 | 0 | UINT64ENCODE_VAR(*pp, enc_value, enc_size); |
97 | 0 | } /* end if */ |
98 | | |
99 | | /* Set size needed for encoding */ |
100 | 0 | *size += (1 + enc_size); |
101 | |
|
102 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
103 | 0 | } /* end H5P__encode_size_t() */ |
104 | | |
105 | | /*------------------------------------------------------------------------- |
106 | | * Function: H5P__encode_hsize_t |
107 | | * |
108 | | * Purpose: Generic encoding callback routine for 'hsize_t' properties. |
109 | | * |
110 | | * Return: Success: Non-negative |
111 | | * Failure: Negative |
112 | | * |
113 | | *------------------------------------------------------------------------- |
114 | | */ |
115 | | herr_t |
116 | | H5P__encode_hsize_t(const void *value, void **_pp, size_t *size) |
117 | 0 | { |
118 | 0 | uint64_t enc_value = (uint64_t) * (const hsize_t *)value; /* Property value to encode */ |
119 | 0 | unsigned enc_size = H5VM_limit_enc_size(enc_value); /* Size of encoded property */ |
120 | 0 | uint8_t **pp = (uint8_t **)_pp; |
121 | |
|
122 | 0 | FUNC_ENTER_PACKAGE_NOERR |
123 | | |
124 | | /* Sanity checks */ |
125 | 0 | HDcompile_assert(sizeof(hsize_t) <= sizeof(uint64_t)); |
126 | 0 | assert(enc_size < 256); |
127 | 0 | assert(size); |
128 | |
|
129 | 0 | if (NULL != *pp) { |
130 | 0 | *(*pp)++ = (uint8_t)enc_size; |
131 | | |
132 | | /* Encode the value */ |
133 | 0 | UINT64ENCODE_VAR(*pp, enc_value, enc_size); |
134 | 0 | } /* end if */ |
135 | | |
136 | | /* Set size needed for encoding */ |
137 | 0 | *size += (1 + enc_size); |
138 | |
|
139 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
140 | 0 | } /* end H5P__encode_hsize_t() */ |
141 | | |
142 | | /*------------------------------------------------------------------------- |
143 | | * Function: H5P__encode_unsigned |
144 | | * |
145 | | * Purpose: Generic encoding callback routine for 'unsigned' properties. |
146 | | * |
147 | | * Return: Success: Non-negative |
148 | | * Failure: Negative |
149 | | * |
150 | | *------------------------------------------------------------------------- |
151 | | */ |
152 | | herr_t |
153 | | H5P__encode_unsigned(const void *value, void **_pp, size_t *size) |
154 | 0 | { |
155 | 0 | uint8_t **pp = (uint8_t **)_pp; |
156 | |
|
157 | 0 | FUNC_ENTER_PACKAGE_NOERR |
158 | | |
159 | | /* Sanity checks */ |
160 | 0 | assert(value); |
161 | 0 | assert(size); |
162 | |
|
163 | 0 | if (NULL != *pp) { |
164 | | /* Encode the size */ |
165 | 0 | *(*pp)++ = (uint8_t)sizeof(unsigned); |
166 | | |
167 | | /* Encode the value */ |
168 | 0 | H5_ENCODE_UNSIGNED(*pp, *(const unsigned *)value); |
169 | 0 | } /* end if */ |
170 | | |
171 | | /* Set size needed for encoding */ |
172 | 0 | *size += (1 + sizeof(unsigned)); |
173 | |
|
174 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
175 | 0 | } /* end H5P__encode_unsigned() */ |
176 | | |
177 | | /*------------------------------------------------------------------------- |
178 | | * Function: H5P__encode_uint8_t |
179 | | * |
180 | | * Purpose: Generic encoding callback routine for 'uint8_t' properties. |
181 | | * |
182 | | * Return: Success: Non-negative |
183 | | * Failure: Negative |
184 | | * |
185 | | *------------------------------------------------------------------------- |
186 | | */ |
187 | | herr_t |
188 | | H5P__encode_uint8_t(const void *value, void **_pp, size_t *size) |
189 | 0 | { |
190 | 0 | uint8_t **pp = (uint8_t **)_pp; |
191 | |
|
192 | 0 | FUNC_ENTER_PACKAGE_NOERR |
193 | | |
194 | | /* Sanity checks */ |
195 | 0 | assert(value); |
196 | 0 | assert(size); |
197 | |
|
198 | 0 | if (NULL != *pp) { |
199 | | /* Encode the value */ |
200 | 0 | *(*pp)++ = *(const uint8_t *)value; |
201 | 0 | } /* end if */ |
202 | | |
203 | | /* Set size needed for encoding */ |
204 | 0 | *size += 1; |
205 | |
|
206 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
207 | 0 | } /* end H5P__encode_uint8_t() */ |
208 | | |
209 | | /*------------------------------------------------------------------------- |
210 | | * Function: H5P__encode_bool |
211 | | * |
212 | | * Purpose: Generic encoding callback routine for 'bool' properties. |
213 | | * |
214 | | * Return: Success: Non-negative |
215 | | * Failure: Negative |
216 | | * |
217 | | *------------------------------------------------------------------------- |
218 | | */ |
219 | | herr_t |
220 | | H5P__encode_bool(const void *value, void **_pp, size_t *size) |
221 | 0 | { |
222 | 0 | uint8_t **pp = (uint8_t **)_pp; |
223 | |
|
224 | 0 | FUNC_ENTER_PACKAGE_NOERR |
225 | | |
226 | | /* Sanity checks */ |
227 | 0 | assert(value); |
228 | 0 | assert(size); |
229 | |
|
230 | 0 | if (NULL != *pp) |
231 | | /* Encode the value */ |
232 | 0 | *(*pp)++ = (uint8_t) * (const bool *)value; |
233 | | |
234 | | /* Set size needed for encoding */ |
235 | 0 | *size += 1; |
236 | |
|
237 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
238 | 0 | } /* end H5P__encode_bool() */ |
239 | | |
240 | | /*------------------------------------------------------------------------- |
241 | | * Function: H5P__encode_double |
242 | | * |
243 | | * Purpose: Generic encoding callback routine for 'double' properties. |
244 | | * |
245 | | * Return: Success: Non-negative |
246 | | * Failure: Negative |
247 | | * |
248 | | *------------------------------------------------------------------------- |
249 | | */ |
250 | | herr_t |
251 | | H5P__encode_double(const void *value, void **_pp, size_t *size) |
252 | 0 | { |
253 | 0 | uint8_t **pp = (uint8_t **)_pp; |
254 | |
|
255 | 0 | FUNC_ENTER_PACKAGE_NOERR |
256 | | |
257 | | /* Sanity checks */ |
258 | 0 | assert(value); |
259 | 0 | assert(size); |
260 | |
|
261 | 0 | if (NULL != *pp) { |
262 | | /* Encode the size */ |
263 | 0 | *(*pp)++ = (uint8_t)sizeof(double); |
264 | | |
265 | | /* Encode the value */ |
266 | 0 | H5_ENCODE_DOUBLE(*pp, *(const double *)value); |
267 | 0 | } /* end if */ |
268 | | |
269 | | /* Set size needed for encoding */ |
270 | 0 | *size += (1 + sizeof(double)); |
271 | |
|
272 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
273 | 0 | } /* end H5P__encode_double() */ |
274 | | |
275 | | /*------------------------------------------------------------------------- |
276 | | * Function: H5P__encode_uint64_t |
277 | | * |
278 | | * Purpose: Generic encoding callback routine for 'uint64_t' properties. |
279 | | * |
280 | | * Return: Success: Non-negative |
281 | | * Failure: Negative |
282 | | * |
283 | | *------------------------------------------------------------------------- |
284 | | */ |
285 | | herr_t |
286 | | H5P__encode_uint64_t(const void *value, void **_pp, size_t *size) |
287 | 0 | { |
288 | 0 | uint8_t **pp = (uint8_t **)_pp; |
289 | |
|
290 | 0 | FUNC_ENTER_PACKAGE_NOERR |
291 | | |
292 | | /* Sanity checks */ |
293 | 0 | assert(value); |
294 | 0 | assert(size); |
295 | |
|
296 | 0 | if (NULL != *pp) { |
297 | | /* Encode the size */ |
298 | 0 | *(*pp)++ = (uint8_t)sizeof(uint64_t); |
299 | | |
300 | | /* Encode the value */ |
301 | 0 | UINT64ENCODE(*pp, *(const unsigned *)value); |
302 | 0 | } /* end if */ |
303 | | |
304 | | /* Set size needed for encoding */ |
305 | 0 | *size += (1 + sizeof(uint64_t)); |
306 | |
|
307 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
308 | 0 | } /* end H5P__encode_uint64_t() */ |
309 | | |
310 | | /*-------------------------------------------------------------------------- |
311 | | NAME |
312 | | H5P__encode_cb |
313 | | PURPOSE |
314 | | Internal callback routine when iterating over properties while encoding |
315 | | a property list. |
316 | | USAGE |
317 | | int H5P__encode_cb(item, key, udata) |
318 | | H5P_genprop_t *prop; IN: Pointer to the property |
319 | | void *udata; IN/OUT: Pointer to iteration data from user |
320 | | RETURNS |
321 | | Success: H5_ITER_CONT |
322 | | Fail: H5_ITER_ERROR |
323 | | DESCRIPTION |
324 | | This routine encodes a property in a property list |
325 | | GLOBAL VARIABLES |
326 | | COMMENTS, BUGS, ASSUMPTIONS |
327 | | EXAMPLES |
328 | | REVISION LOG |
329 | | --------------------------------------------------------------------------*/ |
330 | | static int |
331 | | H5P__encode_cb(H5P_genprop_t *prop, void *_udata) |
332 | 0 | { |
333 | 0 | H5P_enc_iter_ud_t *udata = (H5P_enc_iter_ud_t *)_udata; /* Pointer to user data */ |
334 | 0 | int ret_value = H5_ITER_CONT; /* Return value */ |
335 | |
|
336 | 0 | FUNC_ENTER_PACKAGE |
337 | | |
338 | | /* Sanity check */ |
339 | 0 | assert(prop); |
340 | 0 | assert(udata); |
341 | | |
342 | | /* Check if this property can be encoded */ |
343 | 0 | if (prop->encode) { |
344 | 0 | size_t prop_name_len; /* Length of property's name */ |
345 | 0 | size_t prop_value_len; /* Encoded size of property's value */ |
346 | | |
347 | | /* Encode (or not, if the 'encode' flag is off) the property's name */ |
348 | 0 | prop_name_len = strlen(prop->name) + 1; |
349 | 0 | if (udata->encode) { |
350 | 0 | strcpy((char *)*(udata->pp), prop->name); |
351 | 0 | *(uint8_t **)(udata->pp) += prop_name_len; |
352 | 0 | } /* end if */ |
353 | 0 | *(udata->enc_size_ptr) += prop_name_len; |
354 | | |
355 | | /* Prepare & restore library for user callback */ |
356 | 0 | H5_BEFORE_USER_CB(H5_ITER_ERROR) |
357 | 0 | { |
358 | | /* Encode (or not, if *(udata->pp) is NULL) the property value */ |
359 | 0 | prop_value_len = 0; |
360 | 0 | ret_value = (prop->encode)(prop->value, udata->pp, &prop_value_len); |
361 | 0 | } |
362 | 0 | H5_AFTER_USER_CB(H5_ITER_ERROR) |
363 | 0 | if (ret_value < 0) |
364 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_CANTENCODE, H5_ITER_ERROR, "property encoding routine failed"); |
365 | 0 | *(udata->enc_size_ptr) += prop_value_len; |
366 | 0 | } /* end if */ |
367 | | |
368 | 0 | done: |
369 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
370 | 0 | } /* end H5P__encode_cb() */ |
371 | | |
372 | | /*------------------------------------------------------------------------- |
373 | | NAME |
374 | | H5P__encode |
375 | | PURPOSE |
376 | | Internal routine to encode a property list into a binary buffer. |
377 | | USAGE |
378 | | herr_t H5P__encode(plist, enc_all_prop, buf, nalloc) |
379 | | const H5P_genplist_t *plist; IN: Property list to encode |
380 | | bool enc_all_prop; IN: Whether to encode all properties (true), |
381 | | or just non-default (i.e. changed) properties (false). |
382 | | uint8_t *buf; OUT: buffer to hold the encoded plist |
383 | | size_t *nalloc; IN/OUT: size of buffer needed to encode plist |
384 | | RETURNS |
385 | | Returns non-negative on success, negative on failure. |
386 | | DESCRIPTION |
387 | | Encodes a property list into a binary buffer. If the buffer is NULL, then |
388 | | the call will set the size needed to encode the plist in nalloc. Otherwise |
389 | | the routine will encode the plist in buf. |
390 | | GLOBAL VARIABLES |
391 | | COMMENTS, BUGS, ASSUMPTIONS |
392 | | EXAMPLES |
393 | | REVISION LOG |
394 | | --------------------------------------------------------------------------*/ |
395 | | herr_t |
396 | | H5P__encode(const H5P_genplist_t *plist, bool enc_all_prop, void *buf, size_t *nalloc) |
397 | 0 | { |
398 | 0 | H5P_enc_iter_ud_t udata; /* User data for property iteration callback */ |
399 | 0 | uint8_t *p = (uint8_t *)buf; /* Temporary pointer to encoding buffer */ |
400 | 0 | int idx; /* Index of property to start at */ |
401 | 0 | size_t encode_size = 0; /* Size of buffer needed to encode properties */ |
402 | 0 | bool encode = true; /* Whether the property list should be encoded */ |
403 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
404 | |
|
405 | 0 | FUNC_ENTER_PACKAGE |
406 | | |
407 | | /* Sanity check */ |
408 | 0 | if (NULL == nalloc) |
409 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "bad allocation size pointer"); |
410 | | |
411 | | /* If the buffer is NULL, then this call to H5P__encode will return how much |
412 | | * space is needed to encode a property. |
413 | | */ |
414 | 0 | if (NULL == p) |
415 | 0 | encode = false; |
416 | | |
417 | | /* Encode property list description info */ |
418 | 0 | if (encode) { |
419 | | /* Version # of property list encoding */ |
420 | 0 | *p++ = (uint8_t)H5P_ENCODE_VERS; |
421 | | |
422 | | /* Type of property list */ |
423 | 0 | *p++ = (uint8_t)plist->pclass->type; |
424 | 0 | } /* end if */ |
425 | 0 | encode_size += 2; |
426 | | |
427 | | /* Initialize user data for iteration callback */ |
428 | 0 | udata.encode = encode; |
429 | 0 | udata.enc_size_ptr = &encode_size; |
430 | 0 | udata.pp = (void **)&p; |
431 | | |
432 | | /* Iterate over all properties in property list, encoding them */ |
433 | 0 | idx = 0; |
434 | 0 | if (H5P__iterate_plist(plist, enc_all_prop, &idx, H5P__encode_cb, &udata) < 0) |
435 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_BADITER, FAIL, "can't iterate over properties"); |
436 | | |
437 | | /* Encode a terminator for list of properties */ |
438 | 0 | if (encode) |
439 | 0 | *p++ = 0; |
440 | 0 | encode_size++; |
441 | | |
442 | | /* Set the size of the buffer needed/used to encode the property list */ |
443 | 0 | *nalloc = encode_size; |
444 | |
|
445 | 0 | done: |
446 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
447 | 0 | } /* end H5P__encode() */ |
448 | | |
449 | | /*------------------------------------------------------------------------- |
450 | | * Function: H5P__decode_size_t |
451 | | * |
452 | | * Purpose: Generic decoding callback routine for 'size_t' properties. |
453 | | * |
454 | | * Return: Success: Non-negative |
455 | | * Failure: Negative |
456 | | * |
457 | | *------------------------------------------------------------------------- |
458 | | */ |
459 | | herr_t |
460 | | H5P__decode_size_t(const void **_pp, void *_value) |
461 | 0 | { |
462 | 0 | size_t *value = (size_t *)_value; /* Property value to return */ |
463 | 0 | const uint8_t **pp = (const uint8_t **)_pp; |
464 | 0 | uint64_t enc_value; /* Decoded property value */ |
465 | 0 | unsigned enc_size; /* Size of encoded property */ |
466 | |
|
467 | 0 | FUNC_ENTER_PACKAGE_NOERR |
468 | | |
469 | | /* Sanity check */ |
470 | 0 | HDcompile_assert(sizeof(size_t) <= sizeof(uint64_t)); |
471 | 0 | assert(pp); |
472 | 0 | assert(*pp); |
473 | 0 | assert(value); |
474 | | |
475 | | /* Decode the size */ |
476 | 0 | enc_size = *(*pp)++; |
477 | 0 | assert(enc_size < 256); |
478 | | |
479 | | /* Decode the value */ |
480 | 0 | UINT64DECODE_VAR(*pp, enc_value, enc_size); |
481 | 0 | H5_CHECKED_ASSIGN(*value, size_t, enc_value, uint64_t); |
482 | |
|
483 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
484 | 0 | } /* end H5P__decode_size_t() */ |
485 | | |
486 | | /*------------------------------------------------------------------------- |
487 | | * Function: H5P__decode_hsize_t |
488 | | * |
489 | | * Purpose: Generic decoding callback routine for 'hsize_t' properties. |
490 | | * |
491 | | * Return: Success: Non-negative |
492 | | * Failure: Negative |
493 | | * |
494 | | *------------------------------------------------------------------------- |
495 | | */ |
496 | | herr_t |
497 | | H5P__decode_hsize_t(const void **_pp, void *_value) |
498 | 0 | { |
499 | 0 | hsize_t *value = (hsize_t *)_value; /* Property value to return */ |
500 | 0 | const uint8_t **pp = (const uint8_t **)_pp; |
501 | 0 | uint64_t enc_value; /* Decoded property value */ |
502 | 0 | unsigned enc_size; /* Size of encoded property */ |
503 | |
|
504 | 0 | FUNC_ENTER_PACKAGE_NOERR |
505 | | |
506 | | /* Sanity check */ |
507 | 0 | HDcompile_assert(sizeof(hsize_t) <= sizeof(uint64_t)); |
508 | 0 | assert(pp); |
509 | 0 | assert(*pp); |
510 | 0 | assert(value); |
511 | | |
512 | | /* Decode the size */ |
513 | 0 | enc_size = *(*pp)++; |
514 | 0 | assert(enc_size < 256); |
515 | | |
516 | | /* Decode the value */ |
517 | 0 | UINT64DECODE_VAR(*pp, enc_value, enc_size); |
518 | 0 | H5_CHECKED_ASSIGN(*value, hsize_t, enc_value, uint64_t); |
519 | |
|
520 | 0 | FUNC_LEAVE_NOAPI(SUCCEED) |
521 | 0 | } /* end H5P__decode_hsize_t() */ |
522 | | |
523 | | /*------------------------------------------------------------------------- |
524 | | * Function: H5P__decode_unsigned |
525 | | * |
526 | | * Purpose: Generic decoding callback routine for 'unsigned' properties. |
527 | | * |
528 | | * Return: Success: Non-negative |
529 | | * Failure: Negative |
530 | | * |
531 | | *------------------------------------------------------------------------- |
532 | | */ |
533 | | herr_t |
534 | | H5P__decode_unsigned(const void **_pp, void *_value) |
535 | 0 | { |
536 | 0 | unsigned *value = (unsigned *)_value; /* Property value to return */ |
537 | 0 | const uint8_t **pp = (const uint8_t **)_pp; |
538 | 0 | unsigned enc_size; /* Size of encoded property */ |
539 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
540 | |
|
541 | 0 | FUNC_ENTER_PACKAGE |
542 | | |
543 | | /* Sanity checks */ |
544 | 0 | assert(pp); |
545 | 0 | assert(*pp); |
546 | 0 | assert(value); |
547 | | |
548 | | /* Decode the size */ |
549 | 0 | enc_size = *(*pp)++; |
550 | 0 | if (enc_size != sizeof(unsigned)) |
551 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "unsigned value can't be decoded"); |
552 | | |
553 | 0 | H5_DECODE_UNSIGNED(*pp, *value); |
554 | |
|
555 | 0 | done: |
556 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
557 | 0 | } /* end H5P__decode_unsigned() */ |
558 | | |
559 | | /*------------------------------------------------------------------------- |
560 | | * Function: H5P__decode_uint8_t |
561 | | * |
562 | | * Purpose: Generic decoding callback routine for 'uint8_t' properties. |
563 | | * |
564 | | * Return: Success: Non-negative |
565 | | * Failure: Negative |
566 | | * |
567 | | *------------------------------------------------------------------------- |
568 | | */ |
569 | | herr_t |
570 | | H5P__decode_uint8_t(const void **_pp, void *_value) |
571 | 0 | { |
572 | 0 | uint8_t *value = (uint8_t *)_value; /* Property value to return */ |
573 | 0 | const uint8_t **pp = (const uint8_t **)_pp; |
574 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
575 | |
|
576 | 0 | FUNC_ENTER_PACKAGE_NOERR |
577 | | |
578 | | /* Sanity checks */ |
579 | 0 | assert(pp); |
580 | 0 | assert(*pp); |
581 | 0 | assert(value); |
582 | | |
583 | | /* Decode the value */ |
584 | 0 | *value = *(*pp)++; |
585 | |
|
586 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
587 | 0 | } /* end H5P__decode_uint8_t() */ |
588 | | |
589 | | /*------------------------------------------------------------------------- |
590 | | * Function: H5P__decode_bool |
591 | | * |
592 | | * Purpose: Generic decoding callback routine for 'bool' properties. |
593 | | * |
594 | | * Return: Success: Non-negative |
595 | | * Failure: Negative |
596 | | * |
597 | | *------------------------------------------------------------------------- |
598 | | */ |
599 | | herr_t |
600 | | H5P__decode_bool(const void **_pp, void *_value) |
601 | 0 | { |
602 | 0 | bool *value = (bool *)_value; /* Property value to return */ |
603 | 0 | const uint8_t **pp = (const uint8_t **)_pp; |
604 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
605 | |
|
606 | 0 | FUNC_ENTER_PACKAGE_NOERR |
607 | | |
608 | | /* Sanity checks */ |
609 | 0 | assert(pp); |
610 | 0 | assert(*pp); |
611 | 0 | assert(value); |
612 | | |
613 | | /* Decode the value */ |
614 | 0 | *value = (bool)*(*pp)++; |
615 | |
|
616 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
617 | 0 | } /* end H5P__decode_bool() */ |
618 | | |
619 | | /*------------------------------------------------------------------------- |
620 | | * Function: H5P__decode_double |
621 | | * |
622 | | * Purpose: Generic decoding callback routine for 'double' properties. |
623 | | * |
624 | | * Return: Success: Non-negative |
625 | | * Failure: Negative |
626 | | * |
627 | | *------------------------------------------------------------------------- |
628 | | */ |
629 | | herr_t |
630 | | H5P__decode_double(const void **_pp, void *_value) |
631 | 0 | { |
632 | 0 | double *value = (double *)_value; /* Property value to return */ |
633 | 0 | const uint8_t **pp = (const uint8_t **)_pp; |
634 | 0 | unsigned enc_size; /* Size of encoded property */ |
635 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
636 | |
|
637 | 0 | FUNC_ENTER_PACKAGE |
638 | | |
639 | | /* Sanity checks */ |
640 | 0 | assert(pp); |
641 | 0 | assert(*pp); |
642 | 0 | assert(value); |
643 | | |
644 | | /* Decode the size */ |
645 | 0 | enc_size = *(*pp)++; |
646 | 0 | if (enc_size != sizeof(double)) |
647 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "double value can't be decoded"); |
648 | | |
649 | 0 | H5_DECODE_DOUBLE(*pp, *value); |
650 | |
|
651 | 0 | done: |
652 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
653 | 0 | } /* end H5P__decode_double() */ |
654 | | |
655 | | /*------------------------------------------------------------------------- |
656 | | * Function: H5P__decode_uint64_t |
657 | | * |
658 | | * Purpose: Generic decoding callback routine for 'uint64_t' properties. |
659 | | * |
660 | | * Return: Success: Non-negative |
661 | | * Failure: Negative |
662 | | * |
663 | | *------------------------------------------------------------------------- |
664 | | */ |
665 | | herr_t |
666 | | H5P__decode_uint64_t(const void **_pp, void *_value) |
667 | 0 | { |
668 | 0 | uint64_t *value = (uint64_t *)_value; /* Property value to return */ |
669 | 0 | const uint8_t **pp = (const uint8_t **)_pp; |
670 | 0 | unsigned enc_size; /* Size of encoded property */ |
671 | 0 | herr_t ret_value = SUCCEED; /* Return value */ |
672 | |
|
673 | 0 | FUNC_ENTER_PACKAGE |
674 | | |
675 | | /* Sanity checks */ |
676 | 0 | assert(pp); |
677 | 0 | assert(*pp); |
678 | 0 | assert(value); |
679 | | |
680 | | /* Decode the size */ |
681 | 0 | enc_size = *(*pp)++; |
682 | 0 | if (enc_size != sizeof(uint64_t)) |
683 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "uint64_t value can't be decoded"); |
684 | | |
685 | 0 | UINT64DECODE(*pp, *value); |
686 | |
|
687 | 0 | done: |
688 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
689 | 0 | } /* end H5P__decode_uint64_t() */ |
690 | | |
691 | | /*------------------------------------------------------------------------- |
692 | | NAME |
693 | | H5P__decode |
694 | | PURPOSE |
695 | | Internal routine to decode a property list from a binary buffer. |
696 | | USAGE |
697 | | H5P_genplist_t *H5P__decode(buf) |
698 | | const void *buf; IN: buffer that holds the encoded plist |
699 | | RETURNS |
700 | | Returns non-negative ID of new property list object on success, negative |
701 | | on failure. |
702 | | DESCRIPTION |
703 | | Decodes a property list from a binary buffer. The contents of the buffer |
704 | | contain the values for the corresponding properties of the plist. The decode |
705 | | callback of a certain property decodes its value from the buffer and sets it |
706 | | in the property list. |
707 | | GLOBAL VARIABLES |
708 | | COMMENTS, BUGS, ASSUMPTIONS |
709 | | Properties in the property list that are not encoded in the serialized |
710 | | form retain their default value. |
711 | | EXAMPLES |
712 | | REVISION LOG |
713 | | --------------------------------------------------------------------------*/ |
714 | | hid_t |
715 | | H5P__decode(const void *buf) |
716 | 0 | { |
717 | 0 | H5P_genplist_t *plist; /* Property list to decode into */ |
718 | 0 | void *value_buf = NULL; /* Pointer to buffer to use when decoding values */ |
719 | 0 | const uint8_t *p = (const uint8_t *)buf; /* Current pointer into buffer */ |
720 | 0 | H5P_plist_type_t type; /* Type of encoded property list */ |
721 | 0 | hid_t plist_id = -1; /* ID of new property list */ |
722 | 0 | size_t value_buf_size = 0; /* Size of current value buffer */ |
723 | 0 | uint8_t vers; /* Version of encoded property list */ |
724 | 0 | hid_t ret_value = H5I_INVALID_HID; /* Return value */ |
725 | |
|
726 | 0 | FUNC_ENTER_PACKAGE |
727 | | |
728 | | /* Sanity check */ |
729 | 0 | if (NULL == p) |
730 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_BADVALUE, FAIL, "decode buffer is NULL"); |
731 | | |
732 | | /* Get the version number of the encoded property list */ |
733 | 0 | vers = (uint8_t)*p++; |
734 | 0 | if ((uint8_t)H5P_ENCODE_VERS != vers) |
735 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_VERSION, FAIL, "bad version # of encoded information, expected %u, got %u", |
736 | 0 | (unsigned)H5P_ENCODE_VERS, (unsigned)vers); |
737 | | |
738 | | /* Get the type of the property list */ |
739 | 0 | type = (H5P_plist_type_t)*p++; |
740 | 0 | if (type <= H5P_TYPE_USER || type >= H5P_TYPE_MAX_TYPE) |
741 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_BADRANGE, FAIL, "bad type of encoded information: %u", (unsigned)type); |
742 | | |
743 | | /* Create new property list of the specified type */ |
744 | 0 | if ((plist_id = H5P__new_plist_of_type(type)) < 0) |
745 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_VERSION, FAIL, "can't create property list of type: %u\n", (unsigned)type); |
746 | | |
747 | | /* Get the property list object */ |
748 | 0 | if (NULL == (plist = (H5P_genplist_t *)H5I_object(plist_id))) |
749 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_BADTYPE, FAIL, "not a property class"); |
750 | | |
751 | | /* Loop over encoded properties, deserializing their values */ |
752 | 0 | while (p) { |
753 | 0 | H5P_genprop_t *prop; /* Pointer to property with same name */ |
754 | 0 | const char *name; /* Pointer to property list name */ |
755 | | |
756 | | /* Check for end of serialized list of properties */ |
757 | 0 | if (0 == *p) |
758 | 0 | break; |
759 | | |
760 | | /* Get property list name */ |
761 | 0 | name = (const char *)p; |
762 | 0 | p += strlen(name) + 1; |
763 | | |
764 | | /* Find property with name */ |
765 | 0 | if (NULL == (prop = H5P__find_prop_plist(plist, name))) |
766 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "property doesn't exist: '%s'", name); |
767 | | |
768 | | /* Check if we should increase the size of the value buffer */ |
769 | 0 | if (prop->size > value_buf_size) { |
770 | 0 | if (NULL == (value_buf = H5MM_realloc(value_buf, prop->size))) |
771 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_CANTALLOC, FAIL, "decoding buffer allocation failed"); |
772 | 0 | value_buf_size = prop->size; |
773 | 0 | } /* end if */ |
774 | | |
775 | | /* Decode serialized value */ |
776 | 0 | if (prop->decode) { |
777 | | /* Prepare & restore library for user callback */ |
778 | 0 | H5_BEFORE_USER_CB(FAIL) |
779 | 0 | { |
780 | 0 | ret_value = (prop->decode)((const void **)&p, value_buf); |
781 | 0 | } |
782 | 0 | H5_AFTER_USER_CB(FAIL) |
783 | 0 | if (ret_value < 0) |
784 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_CANTDECODE, FAIL, |
785 | 0 | "property decoding routine failed, property: '%s'", name); |
786 | 0 | } /* end if */ |
787 | 0 | else |
788 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_NOTFOUND, FAIL, "no decode callback for property: '%s'", name); |
789 | | |
790 | | /* Set the value for the property */ |
791 | 0 | if (H5P_poke(plist, name, value_buf) < 0) |
792 | 0 | HGOTO_ERROR(H5E_PLIST, H5E_CANTSET, FAIL, "unable to set value for property: '%s'", name); |
793 | 0 | } /* end while */ |
794 | | |
795 | | /* Set return value */ |
796 | 0 | ret_value = plist_id; |
797 | |
|
798 | 0 | done: |
799 | | /* Release resources */ |
800 | 0 | if (value_buf) |
801 | 0 | value_buf = H5MM_xfree(value_buf); |
802 | | |
803 | | /* Cleanup on error */ |
804 | 0 | if (ret_value < 0) { |
805 | 0 | if (plist_id > 0 && H5I_dec_ref(plist_id) < 0) |
806 | 0 | HDONE_ERROR(H5E_PLIST, H5E_CANTCLOSEOBJ, FAIL, |
807 | 0 | "unable to close partially initialized property list"); |
808 | 0 | } /* end if */ |
809 | |
|
810 | 0 | FUNC_LEAVE_NOAPI(ret_value) |
811 | 0 | } /* end H5P__decode() */ |