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 /* Programmer: Robb Matzke <matzke@llnl.gov>
15 * Wednesday, September 30, 1998
16 *
17 * Purpose: The fill message indicates a bit pattern to use for
18 * uninitialized data points of a dataset.
19 */
20
21 #include "H5Omodule.h" /* This source code file is part of the H5O module */
22
23
24 #include "H5private.h" /* Generic Functions */
25 #include "H5Dprivate.h" /* Datasets */
26 #include "H5Eprivate.h" /* Error handling */
27 #include "H5FLprivate.h" /* Free Lists */
28 #include "H5Iprivate.h" /* IDs */
29 #include "H5MMprivate.h" /* Memory management */
30 #include "H5Opkg.h" /* Object headers */
31 #include "H5Pprivate.h" /* Property lists */
32 #include "H5Sprivate.h" /* Dataspaces */
33
34
35 static void *H5O_fill_old_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags,
36 unsigned *ioflags, size_t p_size, const uint8_t *p);
37 static herr_t H5O_fill_old_encode(H5F_t *f, uint8_t *p, const void *_mesg);
38 static size_t H5O_fill_old_size(const H5F_t *f, const void *_mesg);
39 static void *H5O_fill_new_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags,
40 unsigned *ioflags, size_t p_size, const uint8_t *p);
41 static herr_t H5O_fill_new_encode(H5F_t *f, uint8_t *p, const void *_mesg);
42 static size_t H5O_fill_new_size(const H5F_t *f, const void *_mesg);
43 static void *H5O_fill_copy(const void *_mesg, void *_dest);
44 static herr_t H5O__fill_reset(void *_mesg);
45 static herr_t H5O__fill_free(void *_mesg);
46 static herr_t H5O__fill_pre_copy_file(H5F_t *file_src, const void *mesg_src,
47 hbool_t *deleted, const H5O_copy_t *cpy_info, void *udata);
48 static herr_t H5O__fill_debug(H5F_t *f, const void *_mesg, FILE *stream,
49 int indent, int fwidth);
50
51 /* Set up & include shared message "interface" info */
52 #define H5O_SHARED_TYPE H5O_MSG_FILL
53 #define H5O_SHARED_DECODE H5O_fill_shared_decode
54 #define H5O_SHARED_DECODE_REAL H5O_fill_old_decode
55 #define H5O_SHARED_ENCODE H5O_fill_shared_encode
56 #define H5O_SHARED_ENCODE_REAL H5O_fill_old_encode
57 #define H5O_SHARED_SIZE H5O_fill_shared_size
58 #define H5O_SHARED_SIZE_REAL H5O_fill_old_size
59 #define H5O_SHARED_DELETE H5O__fill_shared_delete
60 #undef H5O_SHARED_DELETE_REAL
61 #define H5O_SHARED_LINK H5O__fill_shared_link
62 #undef H5O_SHARED_LINK_REAL
63 #define H5O_SHARED_COPY_FILE H5O__fill_shared_copy_file
64 #undef H5O_SHARED_COPY_FILE_REAL
65 #define H5O_SHARED_POST_COPY_FILE H5O_fill_shared_post_copy_file
66 #undef H5O_SHARED_POST_COPY_FILE_REAL
67 #undef H5O_SHARED_POST_COPY_FILE_UPD
68 #define H5O_SHARED_DEBUG H5O_fill_shared_debug
69 #define H5O_SHARED_DEBUG_REAL H5O__fill_debug
70 #include "H5Oshared.h" /* Shared Object Header Message Callbacks */
71
72 /* Set up & include shared message "interface" info */
73 /* (Kludgy 'undef's in order to re-include the H5Oshared.h header) */
74 #undef H5O_SHARED_TYPE
75 #define H5O_SHARED_TYPE H5O_MSG_FILL_NEW
76 #undef H5O_SHARED_DECODE
77 #define H5O_SHARED_DECODE H5O_fill_new_shared_decode
78 #undef H5O_SHARED_DECODE_REAL
79 #define H5O_SHARED_DECODE_REAL H5O_fill_new_decode
80 #undef H5O_SHARED_ENCODE
81 #define H5O_SHARED_ENCODE H5O_fill_new_shared_encode
82 #undef H5O_SHARED_ENCODE_REAL
83 #define H5O_SHARED_ENCODE_REAL H5O_fill_new_encode
84 #undef H5O_SHARED_SIZE
85 #define H5O_SHARED_SIZE H5O_fill_new_shared_size
86 #undef H5O_SHARED_SIZE_REAL
87 #define H5O_SHARED_SIZE_REAL H5O_fill_new_size
88 #undef H5O_SHARED_DELETE
89 #define H5O_SHARED_DELETE H5O__fill_new_shared_delete
90 #undef H5O_SHARED_DELETE_REAL
91 #undef H5O_SHARED_LINK
92 #define H5O_SHARED_LINK H5O__fill_new_shared_link
93 #undef H5O_SHARED_LINK_REAL
94 #undef H5O_SHARED_COPY_FILE
95 #define H5O_SHARED_COPY_FILE H5O__fill_new_shared_copy_file
96 #undef H5O_SHARED_COPY_FILE_REAL
97 #undef H5O_SHARED_POST_COPY_FILE
98 #define H5O_SHARED_POST_COPY_FILE H5O_fill_new_shared_post_copy_file
99 #undef H5O_SHARED_POST_COPY_FILE_REAL
100 #undef H5O_SHARED_POST_COPY_FILE_UPD
101 #undef H5O_SHARED_DEBUG
102 #define H5O_SHARED_DEBUG H5O_fill_new_shared_debug
103 #undef H5O_SHARED_DEBUG_REAL
104 #define H5O_SHARED_DEBUG_REAL H5O__fill_debug
105 #undef H5Oshared_H
106 #include "H5Oshared.h" /* Shared Object Header Message Callbacks */
107
108 /* This message derives from H5O message class, for old fill value before version 1.5 */
109 const H5O_msg_class_t H5O_MSG_FILL[1] = {{
110 H5O_FILL_ID, /*message id number */
111 "fill", /*message name for debugging */
112 sizeof(H5O_fill_t), /*native message size */
113 H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */
114 H5O_fill_shared_decode, /*decode message */
115 H5O_fill_shared_encode, /*encode message */
116 H5O_fill_copy, /*copy the native value */
117 H5O_fill_shared_size, /*raw message size */
118 H5O__fill_reset, /*free internal memory */
119 H5O__fill_free, /* free method */
120 H5O__fill_shared_delete, /* file delete method */
121 H5O__fill_shared_link, /* link method */
122 NULL, /* set share method */
123 NULL, /*can share method */
124 H5O__fill_pre_copy_file, /* pre copy native value to file */
125 H5O__fill_shared_copy_file, /* copy native value to file */
126 H5O_fill_shared_post_copy_file, /* post copy native value to file */
127 NULL, /* get creation index */
128 NULL, /* set creation index */
129 H5O_fill_shared_debug /*debug the message */
130 }};
131
132 /* This message derives from H5O message class, for new fill value after version 1.4 */
133 const H5O_msg_class_t H5O_MSG_FILL_NEW[1] = {{
134 H5O_FILL_NEW_ID, /*message id number */
135 "fill_new", /*message name for debugging */
136 sizeof(H5O_fill_t), /*native message size */
137 H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */
138 H5O_fill_new_shared_decode, /*decode message */
139 H5O_fill_new_shared_encode, /*encode message */
140 H5O_fill_copy, /*copy the native value */
141 H5O_fill_new_shared_size, /*raw message size */
142 H5O__fill_reset, /*free internal memory */
143 H5O__fill_free, /* free method */
144 H5O__fill_new_shared_delete, /* file delete method */
145 H5O__fill_new_shared_link, /* link method */
146 NULL, /* set share method */
147 NULL, /*can share method */
148 H5O__fill_pre_copy_file, /* pre copy native value to file */
149 H5O__fill_new_shared_copy_file, /* copy native value to file */
150 H5O_fill_new_shared_post_copy_file, /* post copy native value to file */
151 NULL, /* get creation index */
152 NULL, /* set creation index */
153 H5O_fill_new_shared_debug /*debug the message */
154 }};
155
156 /* Format version bounds for fill value */
157 const unsigned H5O_fill_ver_bounds[] = {
158 H5O_FILL_VERSION_1, /* H5F_LIBVER_EARLIEST */
159 H5O_FILL_VERSION_3, /* H5F_LIBVER_V18 */
160 H5O_FILL_VERSION_LATEST /* H5F_LIBVER_LATEST */
161 };
162
163 /* Masks, shift values & flags for fill value message */
164 #define H5O_FILL_MASK_ALLOC_TIME 0x03
165 #define H5O_FILL_SHIFT_ALLOC_TIME 0
166 #define H5O_FILL_MASK_FILL_TIME 0x03
167 #define H5O_FILL_SHIFT_FILL_TIME 2
168 #define H5O_FILL_FLAG_UNDEFINED_VALUE 0x10
169 #define H5O_FILL_FLAG_HAVE_VALUE 0x20
170 #define H5O_FILL_FLAGS_ALL (H5O_FILL_MASK_ALLOC_TIME | (H5O_FILL_MASK_FILL_TIME << H5O_FILL_SHIFT_FILL_TIME) | H5O_FILL_FLAG_UNDEFINED_VALUE | H5O_FILL_FLAG_HAVE_VALUE)
171
172 /* Declare a free list to manage the H5O_fill_t struct */
173 H5FL_DEFINE(H5O_fill_t);
174
175 /* Declare extern the free list to manage blocks of type conversion data */
176 H5FL_BLK_EXTERN(type_conv);
177
178
179 /*-------------------------------------------------------------------------
180 * Function: H5O_fill_new_decode
181 *
182 * Purpose: Decode a new fill value message. The new fill value
183 * message is fill value plus space allocation time and
184 * fill value writing time and whether fill value is defined.
185 *
186 * Return: Success: Ptr to new message in native struct.
187 * Failure: NULL
188 *
189 * Programmer: Raymond Lu
190 * Feb 26, 2002
191 *
192 *-------------------------------------------------------------------------
193 */
194 static void *
H5O_fill_new_decode(H5F_t H5_ATTR_UNUSED * f,H5O_t H5_ATTR_UNUSED * open_oh,unsigned H5_ATTR_UNUSED mesg_flags,unsigned H5_ATTR_UNUSED * ioflags,size_t p_size,const uint8_t * p)195 H5O_fill_new_decode(H5F_t H5_ATTR_UNUSED *f, H5O_t H5_ATTR_UNUSED *open_oh,
196 unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
197 size_t p_size, const uint8_t *p)
198 {
199 H5O_fill_t *fill = NULL;
200 void *ret_value = NULL; /* Return value */
201
202 FUNC_ENTER_NOAPI_NOINIT
203
204 HDassert(f);
205 HDassert(p);
206
207 if(NULL == (fill = H5FL_CALLOC(H5O_fill_t)))
208 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message")
209
210 /* Version */
211 fill->version = *p++;
212 if(fill->version < H5O_FILL_VERSION_1 || fill->version > H5O_FILL_VERSION_LATEST)
213 HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "bad version number for fill value message")
214
215 /* Decode each version */
216 if(fill->version < H5O_FILL_VERSION_3) {
217 /* Space allocation time */
218 fill->alloc_time = (H5D_alloc_time_t)*p++;
219
220 /* Fill value write time */
221 fill->fill_time = (H5D_fill_time_t)*p++;
222
223 /* Whether fill value is defined */
224 fill->fill_defined = *p++;
225
226 /* Only decode fill value information if one is defined */
227 if(fill->fill_defined) {
228 INT32DECODE(p, fill->size);
229 if(fill->size > 0) {
230 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
231 if((size_t)fill->size > p_size)
232 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "destination buffer too small")
233 if(NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
234 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
235 HDmemcpy(fill->buf, p, (size_t)fill->size);
236 } /* end if */
237 } /* end if */
238 else
239 fill->size = (-1);
240 } /* end if */
241 else {
242 unsigned flags; /* Status flags */
243
244 /* Flags */
245 flags = *p++;
246
247 /* Check for unknown flags */
248 if(flags & (unsigned)~H5O_FILL_FLAGS_ALL)
249 HGOTO_ERROR(H5E_OHDR, H5E_CANTLOAD, NULL, "unknown flag for fill value message")
250
251 /* Space allocation time */
252 fill->alloc_time = (H5D_alloc_time_t)((flags >> H5O_FILL_SHIFT_ALLOC_TIME) & H5O_FILL_MASK_ALLOC_TIME);
253
254 /* Fill value write time */
255 fill->fill_time = (H5D_fill_time_t)((flags >> H5O_FILL_SHIFT_FILL_TIME) & H5O_FILL_MASK_FILL_TIME);
256
257 /* Check for undefined fill value */
258 if(flags & H5O_FILL_FLAG_UNDEFINED_VALUE) {
259 /* Sanity check */
260 HDassert(!(flags & H5O_FILL_FLAG_HAVE_VALUE));
261
262 /* Set value for "undefined" fill value */
263 fill->size = (-1);
264 } /* end if */
265 else if(flags & H5O_FILL_FLAG_HAVE_VALUE) {
266 /* Fill value size */
267 UINT32DECODE(p, fill->size);
268
269 /* Fill value */
270 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
271 if(NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
272 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
273 HDmemcpy(fill->buf, p, (size_t)fill->size);
274
275 /* Set the "defined" flag */
276 fill->fill_defined = TRUE;
277 } /* end else */
278 else {
279 /* Set the "defined" flag */
280 fill->fill_defined = TRUE;
281 } /* end else */
282 } /* end else */
283
284 /* Set return value */
285 ret_value = (void *)fill;
286
287 done:
288 if(!ret_value && fill) {
289 if(fill->buf)
290 H5MM_xfree(fill->buf);
291 fill = H5FL_FREE(H5O_fill_t, fill);
292 } /* end if */
293
294 FUNC_LEAVE_NOAPI(ret_value)
295 } /* end H5O_fill_new_decode() */
296
297
298 /*-------------------------------------------------------------------------
299 * Function: H5O_fill_old_decode
300 *
301 * Purpose: Decode an old fill value message.
302 *
303 * Return: Success: Ptr to new message in native struct.
304 * Failure: NULL
305 *
306 * Programmer: Robb Matzke
307 * Wednesday, September 30, 1998
308 *
309 *-------------------------------------------------------------------------
310 */
311 static void *
H5O_fill_old_decode(H5F_t * f,H5O_t * open_oh,unsigned H5_ATTR_UNUSED mesg_flags,unsigned H5_ATTR_UNUSED * ioflags,size_t p_size,const uint8_t * p)312 H5O_fill_old_decode(H5F_t *f, H5O_t *open_oh,
313 unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
314 size_t p_size, const uint8_t *p)
315 {
316 H5O_fill_t *fill = NULL; /* Decoded fill value message */
317 htri_t exists = FALSE;
318 H5T_t *dt = NULL;
319 void *ret_value = NULL; /* Return value */
320
321 FUNC_ENTER_NOAPI_NOINIT
322
323 HDassert(f);
324 HDassert(p);
325
326 if(NULL == (fill = H5FL_CALLOC(H5O_fill_t)))
327 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value message")
328
329 /* Set non-zero default fields */
330 fill->version = H5O_FILL_VERSION_2;
331 fill->alloc_time = H5D_ALLOC_TIME_LATE;
332 fill->fill_time = H5D_FILL_TIME_IFSET;
333
334 /* Fill value size */
335 UINT32DECODE(p, fill->size);
336
337 /* Only decode the fill value itself if there is one */
338 if(fill->size > 0) {
339 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
340 if((size_t)fill->size > p_size)
341 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "destination buffer too small")
342
343 /* Get the datatype message */
344 if((exists = H5O_msg_exists_oh(open_oh, H5O_DTYPE_ID)) < 0)
345 HGOTO_ERROR(H5E_SYM, H5E_NOTFOUND, NULL, "unable to read object header")
346 if(exists) {
347 if((dt = H5O_msg_read_oh(f, open_oh, H5O_DTYPE_ID, NULL)) < 0)
348 HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "can't read DTYPE message")
349 /* Verify size */
350 if(fill->size != H5T_GET_SIZE(dt))
351 HGOTO_ERROR(H5E_SYM, H5E_CANTGET, NULL, "inconsistent fill value size")
352 }
353
354 if(NULL == (fill->buf = H5MM_malloc((size_t)fill->size)))
355 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
356 HDmemcpy(fill->buf, p, (size_t)fill->size);
357 fill->fill_defined = TRUE;
358 } /* end if */
359 else
360 fill->size = (-1);
361
362 /* Set return value */
363 ret_value = (void*)fill;
364
365 done:
366 if(dt)
367 H5O_msg_free(H5O_DTYPE_ID, dt);
368
369 if(!ret_value && fill) {
370 if(fill->buf)
371 H5MM_xfree(fill->buf);
372 fill = H5FL_FREE(H5O_fill_t, fill);
373 } /* end if */
374
375 FUNC_LEAVE_NOAPI(ret_value)
376 } /* end H5O_fill_old_decode() */
377
378
379 /*-------------------------------------------------------------------------
380 * Function: H5O_fill_new_encode
381 *
382 * Purpose: Encode a new fill value message. The new fill value
383 * message is fill value plus space allocation time and
384 * fill value writing time and whether fill value is defined.
385 *
386 * Return: Non-negative on success/Negative on failure
387 *
388 * Programmer: Raymond Lu
389 * Feb 26, 2002
390 *
391 *-------------------------------------------------------------------------
392 */
393 static herr_t
H5O_fill_new_encode(H5F_t H5_ATTR_UNUSED * f,uint8_t * p,const void * _fill)394 H5O_fill_new_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *_fill)
395 {
396 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
397
398 FUNC_ENTER_NOAPI_NOINIT_NOERR
399
400 HDassert(f);
401 HDassert(p);
402 HDassert(fill && NULL == fill->type);
403
404 /* Version */
405 *p++ = (uint8_t)fill->version;
406
407 if(fill->version < H5O_FILL_VERSION_3) {
408 /* Space allocation time */
409 *p++ = fill->alloc_time;
410
411 /* Fill value writing time */
412 *p++ = fill->fill_time;
413
414 /* Whether fill value is defined */
415 *p++ = (uint8_t)fill->fill_defined;
416
417 /* Only write out the size and fill value if it is defined */
418 if(fill->fill_defined) {
419 UINT32ENCODE(p, fill->size);
420 if(fill->size > 0)
421 if(fill->buf) {
422 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
423 HDmemcpy(p, fill->buf, (size_t)fill->size);
424 } /* end if */
425 } /* end if */
426 } /* end if */
427 else {
428 uint8_t flags = 0; /* Fill value setting flags */
429
430 /* Encode space allocation time */
431 HDassert(fill->alloc_time == (H5O_FILL_MASK_ALLOC_TIME & fill->alloc_time));
432 flags = (uint8_t)(flags | ((H5O_FILL_MASK_ALLOC_TIME & fill->alloc_time) << H5O_FILL_SHIFT_ALLOC_TIME));
433
434 /* Encode fill value writing time */
435 HDassert(fill->fill_time == (H5O_FILL_MASK_FILL_TIME & fill->fill_time));
436 flags = (uint8_t)(flags | ((H5O_FILL_MASK_FILL_TIME & fill->fill_time) << H5O_FILL_SHIFT_FILL_TIME));
437
438 /* Check if we need to encode a fill value size */
439 if(fill->size < 0) {
440 /* Indicate that the fill value has been "undefined" by the user */
441 flags |= H5O_FILL_FLAG_UNDEFINED_VALUE;
442
443 /* Flags */
444 *p++ = (uint8_t)flags;
445
446 /* Sanity check */
447 HDassert(!fill->buf);
448 } /* end if */
449 else if(fill->size > 0) {
450 /* Indicate that a fill value size is present */
451 flags |= H5O_FILL_FLAG_HAVE_VALUE;
452
453 /* Flags */
454 *p++ = (uint8_t)flags;
455
456 /* Encode the size of fill value */
457 INT32ENCODE(p, fill->size);
458
459 /* Encode the fill value */
460 HDassert(fill->buf);
461 H5_CHECK_OVERFLOW(fill->size, ssize_t, size_t);
462 HDmemcpy(p, fill->buf, (size_t)fill->size);
463 } /* end if */
464 else {
465 /* Flags */
466 *p++ = (uint8_t)flags;
467
468 /* Sanity check */
469 HDassert(!fill->buf);
470 } /* end else */
471 } /* end else */
472
473 FUNC_LEAVE_NOAPI(SUCCEED)
474 } /* end H5O_fill_new_encode() */
475
476
477 /*-------------------------------------------------------------------------
478 * Function: H5O_fill_old_encode
479 *
480 * Purpose: Encode an old fill value message.
481 *
482 * Return: Non-negative on success/Negative on failure
483 *
484 * Programmer: Robb Matzke
485 * Thursday, October 1, 1998
486 *
487 *-------------------------------------------------------------------------
488 */
489 static herr_t
H5O_fill_old_encode(H5F_t H5_ATTR_UNUSED * f,uint8_t * p,const void * _fill)490 H5O_fill_old_encode(H5F_t H5_ATTR_UNUSED *f, uint8_t *p, const void *_fill)
491 {
492 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
493
494 FUNC_ENTER_NOAPI_NOINIT_NOERR
495
496 HDassert(f);
497 HDassert(p);
498 HDassert(fill && NULL == fill->type);
499
500 UINT32ENCODE(p, fill->size);
501 if(fill->buf)
502 HDmemcpy(p, fill->buf, (size_t)fill->size);
503
504 FUNC_LEAVE_NOAPI(SUCCEED)
505 } /* end H5O_fill_old_encode() */
506
507
508 /*-------------------------------------------------------------------------
509 * Function: H5O_fill_copy
510 *
511 * Purpose: Copies a message from _MESG to _DEST, allocating _DEST if
512 * necessary. The new fill value message is fill value plus
513 * space allocation time and fill value writing time and
514 * whether fill value is defined.
515 *
516 * Return: Success: Ptr to _DEST
517 * Failure: NULL
518 *
519 * Programmer: Raymond Lu
520 * Feb 26, 2002
521 *
522 *-------------------------------------------------------------------------
523 */
524 static void *
H5O_fill_copy(const void * _src,void * _dst)525 H5O_fill_copy(const void *_src, void *_dst)
526 {
527 const H5O_fill_t *src = (const H5O_fill_t *)_src;
528 H5O_fill_t *dst = (H5O_fill_t *)_dst;
529 void *ret_value = NULL; /* Return value */
530
531 FUNC_ENTER_NOAPI_NOINIT
532
533 HDassert(src);
534
535 if(!dst && NULL == (dst = H5FL_MALLOC(H5O_fill_t)))
536 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill message")
537
538 /* Shallow copy basic fields */
539 *dst = *src;
540
541 /* Copy data type of fill value */
542 if(src->type) {
543 if(NULL == (dst->type = H5T_copy(src->type, H5T_COPY_TRANSIENT)))
544 HGOTO_ERROR(H5E_OHDR, H5E_CANTCOPY, NULL, "can't copy datatype")
545 } /* end if */
546 else
547 dst->type = NULL;
548
549 /* Copy fill value and its size */
550 if(src->buf) {
551 H5_CHECK_OVERFLOW(src->size, ssize_t, size_t);
552 if(NULL == (dst->buf = H5MM_malloc((size_t)src->size)))
553 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed for fill value")
554 HDmemcpy(dst->buf, src->buf, (size_t)src->size);
555
556 /* Check for needing to convert/copy fill value */
557 if(src->type) {
558 H5T_path_t *tpath; /* Conversion information */
559
560 /* Set up type conversion function */
561 if(NULL == (tpath = H5T_path_find(src->type, dst->type)))
562 HGOTO_ERROR(H5E_OHDR, H5E_UNSUPPORTED, NULL, "unable to convert between src and dst data types")
563
564 /* If necessary, convert fill value datatypes (which copies VL components, etc.) */
565 if(!H5T_path_noop(tpath)) {
566 hid_t dst_id, src_id; /* Source & destination datatypes for type conversion */
567 uint8_t *bkg_buf = NULL; /* Background conversion buffer */
568 size_t bkg_size; /* Size of background buffer */
569
570 /* Wrap copies of types to convert */
571 dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dst->type, H5T_COPY_TRANSIENT), FALSE);
572 if(dst_id < 0)
573 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy/register datatype")
574 src_id = H5I_register(H5I_DATATYPE, H5T_copy(src->type, H5T_COPY_ALL), FALSE);
575 if(src_id < 0) {
576 H5I_dec_ref(dst_id);
577 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "unable to copy/register datatype")
578 } /* end if */
579
580 /* Allocate a background buffer */
581 bkg_size = MAX(H5T_get_size(dst->type), H5T_get_size(src->type));
582 if(H5T_path_bkg(tpath) && NULL == (bkg_buf = H5FL_BLK_CALLOC(type_conv, bkg_size))) {
583 H5I_dec_ref(src_id);
584 H5I_dec_ref(dst_id);
585 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
586 } /* end if */
587
588 /* Convert fill value */
589 if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, dst->buf, bkg_buf) < 0) {
590 H5I_dec_ref(src_id);
591 H5I_dec_ref(dst_id);
592 if(bkg_buf)
593 bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
594 HGOTO_ERROR(H5E_OHDR, H5E_CANTCONVERT, NULL, "datatype conversion failed")
595 } /* end if */
596
597 /* Release the background buffer */
598 H5I_dec_ref(src_id);
599 H5I_dec_ref(dst_id);
600 if(bkg_buf)
601 bkg_buf = H5FL_BLK_FREE(type_conv, bkg_buf);
602 } /* end if */
603 } /* end if */
604 } /* end if */
605 else
606 dst->buf = NULL;
607
608 /* Set return value */
609 ret_value = dst;
610
611 done:
612 if(!ret_value && dst) {
613 if(dst->buf)
614 H5MM_xfree(dst->buf);
615 if(dst->type)
616 (void)H5T_close_real(dst->type);
617 if(!_dst)
618 dst = H5FL_FREE(H5O_fill_t, dst);
619 } /* end if */
620
621 FUNC_LEAVE_NOAPI(ret_value)
622 } /* end H5O_fill_copy() */
623
624
625 /*-------------------------------------------------------------------------
626 * Function: H5O_fill_new_size
627 *
628 * Purpose: Returns the size of the raw message in bytes not counting the
629 * message type or size fields, but only the data fields. This
630 * function doesn't take into account alignment. The new fill
631 * value message is fill value plus space allocation time and
632 * fill value writing time and whether fill value is defined.
633 *
634 * Return: Success: Message data size in bytes w/o alignment.
635 * Failure: 0
636 *
637 * Programmer: Raymond Lu
638 * Feb 26, 2002
639 *
640 *-------------------------------------------------------------------------
641 */
642 static size_t
H5O_fill_new_size(const H5F_t H5_ATTR_UNUSED * f,const void * _fill)643 H5O_fill_new_size(const H5F_t H5_ATTR_UNUSED *f, const void *_fill)
644 {
645 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
646 size_t ret_value = 0; /* Return value */
647
648 FUNC_ENTER_NOAPI_NOINIT_NOERR
649
650 HDassert(f);
651 HDassert(fill);
652
653 /* Determine size for different versions */
654 if(fill->version < H5O_FILL_VERSION_3) {
655 ret_value = 1 + /* Version number */
656 1 + /* Space allocation time */
657 1 + /* Fill value write time */
658 1; /* Fill value defined */
659 if(fill->fill_defined)
660 ret_value += 4 + /* Fill value size */
661 (fill->size > 0 ? (size_t)fill->size : 0); /* Size of fill value */
662 } /* end if */
663 else {
664 ret_value = 1 + /* Version number */
665 1; /* Status flags */
666 if(fill->size > 0)
667 ret_value += 4 + /* Fill value size */
668 (size_t)fill->size; /* Size of fill value */
669 } /* end else */
670
671 FUNC_LEAVE_NOAPI(ret_value)
672 } /* end H5O_fill_new_size() */
673
674
675 /*-------------------------------------------------------------------------
676 * Function: H5O_fill_old_size
677 *
678 * Purpose: Returns the size of the raw message in bytes not counting the
679 * message type or size fields, but only the data fields. This
680 * function doesn't take into account alignment.
681 *
682 * Return: Success: Message data size in bytes w/o alignment.
683 * Failure: 0
684 *
685 * Programmer: Robb Matzke
686 * Thursday, October 1, 1998
687 *
688 *-------------------------------------------------------------------------
689 */
690 static size_t
H5O_fill_old_size(const H5F_t H5_ATTR_UNUSED * f,const void * _fill)691 H5O_fill_old_size(const H5F_t H5_ATTR_UNUSED *f, const void *_fill)
692 {
693 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
694
695 FUNC_ENTER_NOAPI_NOINIT_NOERR
696
697 HDassert(fill);
698
699 FUNC_LEAVE_NOAPI(4 + (size_t)fill->size)
700 } /* end H5O_fill_old_size() */
701
702
703 /*-------------------------------------------------------------------------
704 * Function: H5O_fill_reset_dyn
705 *
706 * Purpose: Resets dynamic fill value fields
707 *
708 * Return: Non-negative on success/Negative on failure
709 *
710 * Programmer: Quincey Koziol
711 * Monday, January 22, 2007
712 *
713 *-------------------------------------------------------------------------
714 */
715 herr_t
H5O_fill_reset_dyn(H5O_fill_t * fill)716 H5O_fill_reset_dyn(H5O_fill_t *fill)
717 {
718 hid_t fill_type_id = -1; /* Datatype ID for fill value datatype when reclaiming VL fill values */
719 herr_t ret_value = SUCCEED; /* Return value */
720
721 FUNC_ENTER_NOAPI(FAIL)
722
723 HDassert(fill);
724
725 if(fill->buf) {
726 if(fill->type && H5T_detect_class(fill->type, H5T_VLEN, FALSE) > 0) {
727 H5T_t *fill_type; /* Copy of fill value datatype */
728 H5S_t *fill_space; /* Scalar dataspace for fill value element */
729
730 /* Copy the fill value datatype and get an ID for it */
731 if(NULL == (fill_type = H5T_copy(fill->type, H5T_COPY_TRANSIENT)))
732 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy fill value datatype")
733 if((fill_type_id = H5I_register(H5I_DATATYPE, fill_type, FALSE)) < 0) {
734 (void)H5T_close_real(fill_type);
735 HGOTO_ERROR(H5E_OHDR, H5E_CANTREGISTER, FAIL, "unable to register fill value datatype")
736 } /* end if */
737
738 /* Create a scalar dataspace for the fill value element */
739 if(NULL == (fill_space = H5S_create(H5S_SCALAR)))
740 HGOTO_ERROR(H5E_OHDR, H5E_CANTCREATE, FAIL, "can't create scalar dataspace")
741
742 /* Reclaim any variable length components of the fill value */
743 if(H5D_vlen_reclaim(fill_type_id, fill_space, fill->buf) < 0) {
744 H5S_close(fill_space);
745 HGOTO_ERROR(H5E_OHDR, H5E_BADITER, FAIL, "unable to reclaim variable-length fill value data")
746 } /* end if */
747
748 /* Release the scalar fill value dataspace */
749 H5S_close(fill_space);
750 } /* end if */
751
752 /* Release the fill value buffer now */
753 fill->buf = H5MM_xfree(fill->buf);
754 } /* end if */
755 fill->size = 0;
756 if(fill->type) {
757 (void)H5T_close_real(fill->type);
758 fill->type = NULL;
759 } /* end if */
760
761 done:
762 if(fill_type_id > 0 && H5I_dec_ref(fill_type_id) < 0)
763 HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement ref count for temp ID")
764
765 FUNC_LEAVE_NOAPI(ret_value)
766 } /* end H5O_fill_reset_dyn() */
767
768
769 /*-------------------------------------------------------------------------
770 * Function: H5O__fill_reset
771 *
772 * Purpose: Resets a message to an initial state.
773 *
774 * Return: Non-negative on success/Negative on failure
775 *
776 * Programmer: Robb Matzke
777 * Thursday, October 1, 1998
778 *
779 *-------------------------------------------------------------------------
780 */
781 static herr_t
H5O__fill_reset(void * _fill)782 H5O__fill_reset(void *_fill)
783 {
784 H5O_fill_t *fill = (H5O_fill_t *)_fill;
785
786 FUNC_ENTER_STATIC_NOERR
787
788 HDassert(fill);
789
790 /* Reset dynamic fields */
791 H5O_fill_reset_dyn(fill);
792
793 /* Reset value fields */
794 fill->alloc_time = H5D_ALLOC_TIME_LATE;
795 fill->fill_time = H5D_FILL_TIME_IFSET;
796 fill->fill_defined = FALSE;
797
798 FUNC_LEAVE_NOAPI(SUCCEED)
799 } /* end H5O__fill_reset() */
800
801
802 /*-------------------------------------------------------------------------
803 * Function: H5O__fill_free
804 *
805 * Purpose: Frees the message
806 *
807 * Return: Non-negative on success/Negative on failure
808 *
809 * Programmer: Quincey Koziol
810 * Thursday, December 5, 2002
811 *
812 *-------------------------------------------------------------------------
813 */
814 static herr_t
H5O__fill_free(void * fill)815 H5O__fill_free(void *fill)
816 {
817 FUNC_ENTER_STATIC_NOERR
818
819 HDassert(fill);
820
821 fill = H5FL_FREE(H5O_fill_t, fill);
822
823 FUNC_LEAVE_NOAPI(SUCCEED)
824 } /* end H5O__fill_free() */
825
826
827 /*-------------------------------------------------------------------------
828 * Function: H5O__fill_pre_copy_file
829 *
830 * Purpose: Perform any necessary actions before copying message between
831 * files.
832 *
833 * Return: Success: Non-negative
834 * Failure: Negative
835 *
836 * Programmer: Vailin Choi; Dec 2017
837 *
838 *-------------------------------------------------------------------------
839 */
840 static herr_t
H5O__fill_pre_copy_file(H5F_t H5_ATTR_UNUSED * file_src,const void * mesg_src,hbool_t H5_ATTR_UNUSED * deleted,const H5O_copy_t * cpy_info,void H5_ATTR_UNUSED * udata)841 H5O__fill_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src,
842 hbool_t H5_ATTR_UNUSED *deleted, const H5O_copy_t *cpy_info, void H5_ATTR_UNUSED *udata)
843 {
844 const H5O_fill_t *fill_src = (const H5O_fill_t *)mesg_src; /* Source fill value */
845 herr_t ret_value = SUCCEED; /* Return value */
846
847 FUNC_ENTER_STATIC
848
849 /* check args */
850 HDassert(cpy_info);
851 HDassert(cpy_info->file_dst);
852
853 /* Check to ensure that the version of the message to be copied does not exceed
854 the message version allowed by the destination file's high bound */
855 if(fill_src->version > H5O_fill_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)])
856 HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "fill value message version out of bounds")
857
858 done:
859 FUNC_LEAVE_NOAPI(ret_value)
860 } /* end H5O__fill_pre_copy_file() */
861
862
863 /*-------------------------------------------------------------------------
864 * Function: H5O__fill_debug
865 *
866 * Purpose: Prints debugging info for the message.
867 *
868 * Return: Non-negative on success/Negative on failure
869 *
870 * Programmer: Robb Matzke
871 * Thursday, October 1, 1998
872 *
873 *-------------------------------------------------------------------------
874 */
875 static herr_t
H5O__fill_debug(H5F_t H5_ATTR_UNUSED * f,const void * _fill,FILE * stream,int indent,int fwidth)876 H5O__fill_debug(H5F_t H5_ATTR_UNUSED *f, const void *_fill, FILE *stream,
877 int indent, int fwidth)
878 {
879 const H5O_fill_t *fill = (const H5O_fill_t *)_fill;
880 H5D_fill_value_t fill_status; /* Whether the fill value is defined */
881
882 FUNC_ENTER_STATIC_NOERR
883
884 HDassert(f);
885 HDassert(fill);
886 HDassert(stream);
887 HDassert(indent >= 0);
888 HDassert(fwidth >= 0);
889
890 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Space Allocation Time:");
891 switch(fill->alloc_time) {
892 case H5D_ALLOC_TIME_EARLY:
893 HDfprintf(stream,"Early\n");
894 break;
895
896 case H5D_ALLOC_TIME_LATE:
897 HDfprintf(stream,"Late\n");
898 break;
899
900 case H5D_ALLOC_TIME_INCR:
901 HDfprintf(stream,"Incremental\n");
902 break;
903
904 case H5D_ALLOC_TIME_DEFAULT:
905 case H5D_ALLOC_TIME_ERROR:
906 default:
907 HDfprintf(stream,"Unknown!\n");
908 break;
909 } /* end switch */
910 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Fill Time:");
911 switch(fill->fill_time) {
912 case H5D_FILL_TIME_ALLOC:
913 HDfprintf(stream,"On Allocation\n");
914 break;
915
916 case H5D_FILL_TIME_NEVER:
917 HDfprintf(stream,"Never\n");
918 break;
919
920 case H5D_FILL_TIME_IFSET:
921 HDfprintf(stream,"If Set\n");
922 break;
923
924 case H5D_FILL_TIME_ERROR:
925 default:
926 HDfprintf(stream,"Unknown!\n");
927 break;
928
929 } /* end switch */
930 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Fill Value Defined:");
931 H5P_is_fill_value_defined((const H5O_fill_t *)fill, &fill_status);
932 switch(fill_status) {
933 case H5D_FILL_VALUE_UNDEFINED:
934 HDfprintf(stream,"Undefined\n");
935 break;
936
937 case H5D_FILL_VALUE_DEFAULT:
938 HDfprintf(stream,"Default\n");
939 break;
940
941 case H5D_FILL_VALUE_USER_DEFINED:
942 HDfprintf(stream,"User Defined\n");
943 break;
944
945 case H5D_FILL_VALUE_ERROR:
946 default:
947 HDfprintf(stream,"Unknown!\n");
948 break;
949
950 } /* end switch */
951 HDfprintf(stream, "%*s%-*s %Zd\n", indent, "", fwidth,
952 "Size:", fill->size);
953 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Data type:");
954 if(fill->type) {
955 H5T_debug(fill->type, stream);
956 HDfprintf(stream, "\n");
957 } /* end if */
958 else
959 HDfprintf(stream, "<dataset type>\n");
960
961 FUNC_LEAVE_NOAPI(SUCCEED)
962 } /* end H5O__fill_debug() */
963
964
965 /*-------------------------------------------------------------------------
966 * Function: H5O_fill_convert
967 *
968 * Purpose: Convert a fill value from whatever data type it currently has
969 * to the specified dataset type. The `type' field of the fill
970 * value struct will be set to NULL to indicate that it has the
971 * same type as the dataset.
972 *
973 * Return: Non-negative on success/Negative on failure
974 *
975 * Programmer: Robb Matzke
976 * Thursday, October 1, 1998
977 *
978 *-------------------------------------------------------------------------
979 */
980 herr_t
H5O_fill_convert(H5O_fill_t * fill,H5T_t * dset_type,hbool_t * fill_changed)981 H5O_fill_convert(H5O_fill_t *fill, H5T_t *dset_type, hbool_t *fill_changed)
982 {
983 H5T_path_t *tpath; /* Type conversion info */
984 void *buf = NULL, *bkg = NULL; /* Conversion buffers */
985 hid_t src_id = -1, dst_id = -1; /* Datatype identifiers */
986 herr_t ret_value = SUCCEED; /* Return value */
987
988 FUNC_ENTER_NOAPI_NOINIT
989
990 HDassert(fill);
991 HDassert(dset_type);
992 HDassert(fill_changed);
993
994 /* No-op cases */
995 if(!fill->buf || !fill->type || 0 == H5T_cmp(fill->type, dset_type, FALSE)) {
996 /* Don't need datatype for fill value */
997 if(fill->type)
998 (void)H5T_close_real(fill->type);
999 fill->type = NULL;
1000
1001 /* Note that the fill value info has changed */
1002 *fill_changed = TRUE;
1003
1004 HGOTO_DONE(SUCCEED);
1005 } /* end if */
1006
1007 /*
1008 * Can we convert between source and destination data types?
1009 */
1010 if(NULL == (tpath = H5T_path_find(fill->type, dset_type)))
1011 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to convert between src and dst datatypes")
1012
1013 /* Don't bother doing anything if there will be no actual conversion */
1014 if(!H5T_path_noop(tpath)) {
1015 if((src_id = H5I_register(H5I_DATATYPE, H5T_copy(fill->type, H5T_COPY_ALL), FALSE)) < 0 ||
1016 (dst_id = H5I_register(H5I_DATATYPE, H5T_copy(dset_type, H5T_COPY_ALL), FALSE)) < 0)
1017 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "unable to copy/register data type")
1018
1019 /*
1020 * Datatype conversions are always done in place, so we need a buffer
1021 * that is large enough for both source and destination.
1022 */
1023 if(H5T_get_size(fill->type) >= H5T_get_size(dset_type))
1024 buf = fill->buf;
1025 else {
1026 if(NULL == (buf = H5MM_malloc(H5T_get_size(dset_type))))
1027 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
1028 HDmemcpy(buf, fill->buf, H5T_get_size(fill->type));
1029 } /* end else */
1030
1031 /* Use CALLOC here to clear the buffer in case later the library thinks there's
1032 * data in the background. */
1033 if(H5T_path_bkg(tpath) && NULL == (bkg = H5MM_calloc(H5T_get_size(dset_type))))
1034 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, FAIL, "memory allocation failed for type conversion")
1035
1036 /* Do the conversion */
1037 if(H5T_convert(tpath, src_id, dst_id, (size_t)1, (size_t)0, (size_t)0, buf, bkg) < 0)
1038 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, FAIL, "datatype conversion failed")
1039
1040 /* Update the fill message */
1041 if(buf != fill->buf) {
1042 H5T_vlen_reclaim_elmt(fill->buf, fill->type);
1043 H5MM_xfree(fill->buf);
1044 fill->buf = buf;
1045 } /* end if */
1046 (void)H5T_close_real(fill->type);
1047 fill->type = NULL;
1048 H5_CHECKED_ASSIGN(fill->size, ssize_t, H5T_get_size(dset_type), size_t);
1049
1050 /* Note that the fill value info has changed */
1051 *fill_changed = TRUE;
1052 } /* end if */
1053
1054 done:
1055 if(src_id >= 0 && H5I_dec_ref(src_id) < 0)
1056 HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement ref count for temp ID")
1057 if(dst_id >= 0 && H5I_dec_ref(dst_id) < 0)
1058 HDONE_ERROR(H5E_OHDR, H5E_CANTDEC, FAIL, "unable to decrement ref count for temp ID")
1059 if(buf != fill->buf)
1060 H5MM_xfree(buf);
1061 if(bkg)
1062 H5MM_xfree(bkg);
1063
1064 FUNC_LEAVE_NOAPI(ret_value)
1065 } /* end H5O_fill_convert() */
1066
1067
1068 /*-------------------------------------------------------------------------
1069 * Function: H5O_fill_set_version
1070 *
1071 * Purpose: Set the version to encode a fill value with.
1072 *
1073 * Return: Non-negative on success/Negative on failure
1074 *
1075 * Programmer: Vailin Choi; December 2017
1076 *
1077 *-------------------------------------------------------------------------
1078 */
1079 herr_t
H5O_fill_set_version(H5F_t * f,H5O_fill_t * fill)1080 H5O_fill_set_version(H5F_t *f, H5O_fill_t *fill)
1081 {
1082 unsigned version; /* Message version */
1083 herr_t ret_value = SUCCEED; /* Return value */
1084
1085 FUNC_ENTER_NOAPI(FAIL)
1086
1087 /* Sanity check */
1088 HDassert(f);
1089 HDassert(fill);
1090
1091 /* Upgrade to the version indicated by the file's low bound if higher */
1092 version = MAX(fill->version, H5O_fill_ver_bounds[H5F_LOW_BOUND(f)]);
1093
1094 /* Version bounds check */
1095 if(version > H5O_fill_ver_bounds[H5F_HIGH_BOUND(f)])
1096 HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "Filter pipeline version out of bounds")
1097
1098 /* Set the message version */
1099 fill->version = version;
1100
1101 done:
1102 FUNC_LEAVE_NOAPI(ret_value)
1103 } /* end H5O_fill_set_version() */
1104
1105