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