1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2 * Copyright by The HDF Group. *
3 * Copyright by the Board of Trustees of the University of Illinois. *
4 * All rights reserved. *
5 * *
6 * This file is part of HDF5. The full HDF5 copyright notice, including *
7 * terms governing use, modification, and redistribution, is contained in *
8 * the COPYING file, which can be found at the root of the source code *
9 * distribution tree, or in https://support.hdfgroup.org/ftp/HDF5/releases. *
10 * If you do not have access to either file, you may request a copy from *
11 * help@hdfgroup.org. *
12 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13
14 #include "H5Omodule.h" /* This source code file is part of the H5O module */
15 #define H5S_FRIEND /*prevent warning from including H5Spkg.h */
16
17 #include "H5private.h" /* Generic Functions */
18 #include "H5Dprivate.h" /* Datasets */
19 #include "H5Eprivate.h" /* Error handling */
20 #include "H5FLprivate.h" /* Free lists */
21 #include "H5Gprivate.h" /* Groups */
22 #include "H5MMprivate.h" /* Memory management */
23 #include "H5Opkg.h" /* Object headers */
24 #include "H5Spkg.h" /* Dataspaces */
25
26
27 /* PRIVATE PROTOTYPES */
28 static void *H5O__sdspace_decode(H5F_t *f, H5O_t *open_oh, unsigned mesg_flags,
29 unsigned *ioflags, size_t p_size, const uint8_t *p);
30 static herr_t H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg);
31 static void *H5O_sdspace_copy(const void *_mesg, void *_dest);
32 static size_t H5O_sdspace_size(const H5F_t *f, const void *_mesg);
33 static herr_t H5O__sdspace_reset(void *_mesg);
34 static herr_t H5O__sdspace_free(void *_mesg);
35 static herr_t H5O_sdspace_pre_copy_file(H5F_t *file_src, const void *mesg_src,
36 hbool_t *deleted, const H5O_copy_t *cpy_info, void *_udata);
37 static herr_t H5O__sdspace_debug(H5F_t *f, const void *_mesg, FILE * stream,
38 int indent, int fwidth);
39
40 /* Set up & include shared message "interface" info */
41 #define H5O_SHARED_TYPE H5O_MSG_SDSPACE
42 #define H5O_SHARED_DECODE H5O_sdspace_shared_decode
43 #define H5O_SHARED_DECODE_REAL H5O__sdspace_decode
44 #define H5O_SHARED_ENCODE H5O_sdspace_shared_encode
45 #define H5O_SHARED_ENCODE_REAL H5O_sdspace_encode
46 #define H5O_SHARED_SIZE H5O_sdspace_shared_size
47 #define H5O_SHARED_SIZE_REAL H5O_sdspace_size
48 #define H5O_SHARED_DELETE H5O__sdspace_shared_delete
49 #undef H5O_SHARED_DELETE_REAL
50 #define H5O_SHARED_LINK H5O__sdspace_shared_link
51 #undef H5O_SHARED_LINK_REAL
52 #define H5O_SHARED_COPY_FILE H5O__sdspace_shared_copy_file
53 #undef H5O_SHARED_COPY_FILE_REAL
54 #define H5O_SHARED_POST_COPY_FILE H5O_sdspace_shared_post_copy_file
55 #undef H5O_SHARED_POST_COPY_FILE_REAL
56 #undef H5O_SHARED_POST_COPY_FILE_UPD
57 #define H5O_SHARED_DEBUG H5O_sdspace_shared_debug
58 #define H5O_SHARED_DEBUG_REAL H5O__sdspace_debug
59 #include "H5Oshared.h" /* Shared Object Header Message Callbacks */
60
61 /* This message derives from H5O message class */
62 const H5O_msg_class_t H5O_MSG_SDSPACE[1] = {{
63 H5O_SDSPACE_ID, /* message id number */
64 "dataspace", /* message name for debugging */
65 sizeof(H5S_extent_t), /* native message size */
66 H5O_SHARE_IS_SHARABLE|H5O_SHARE_IN_OHDR, /* messages are sharable? */
67 H5O_sdspace_shared_decode, /* decode message */
68 H5O_sdspace_shared_encode, /* encode message */
69 H5O_sdspace_copy, /* copy the native value */
70 H5O_sdspace_shared_size, /* size of symbol table entry */
71 H5O__sdspace_reset, /* default reset method */
72 H5O__sdspace_free, /* free method */
73 H5O__sdspace_shared_delete, /* file delete method */
74 H5O__sdspace_shared_link, /* link method */
75 NULL, /* set share method */
76 NULL, /*can share method */
77 H5O_sdspace_pre_copy_file, /* pre copy native value to file */
78 H5O__sdspace_shared_copy_file,/* copy native value to file */
79 H5O_sdspace_shared_post_copy_file,/* post copy native value to file */
80 NULL, /* get creation index */
81 NULL, /* set creation index */
82 H5O_sdspace_shared_debug /* debug the message */
83 }};
84
85 /* Declare external the free list for H5S_extent_t's */
86 H5FL_EXTERN(H5S_extent_t);
87
88 /* Declare external the free list for hsize_t arrays */
89 H5FL_ARR_EXTERN(hsize_t);
90
91
92 /*--------------------------------------------------------------------------
93 NAME
94 H5O__sdspace_decode
95 PURPOSE
96 Decode a simple dimensionality message and return a pointer to a memory
97 struct with the decoded information
98 USAGE
99 void *H5O__sdspace_decode(f, mesg_flags, p)
100 H5F_t *f; IN: pointer to the HDF5 file struct
101 unsigned mesg_flags; IN: Message flags to influence decoding
102 const uint8 *p; IN: the raw information buffer
103 RETURNS
104 Pointer to the new message in native order on success, NULL on failure
105 DESCRIPTION
106 This function decodes the "raw" disk form of a simple dimensionality
107 message into a struct in memory native format. The struct is allocated
108 within this function using malloc() and is returned to the caller.
109 --------------------------------------------------------------------------*/
110 static void *
H5O__sdspace_decode(H5F_t * f,H5O_t H5_ATTR_UNUSED * open_oh,unsigned H5_ATTR_UNUSED mesg_flags,unsigned H5_ATTR_UNUSED * ioflags,size_t H5_ATTR_UNUSED p_size,const uint8_t * p)111 H5O__sdspace_decode(H5F_t *f, H5O_t H5_ATTR_UNUSED *open_oh,
112 unsigned H5_ATTR_UNUSED mesg_flags, unsigned H5_ATTR_UNUSED *ioflags,
113 size_t H5_ATTR_UNUSED p_size, const uint8_t *p)
114 {
115 H5S_extent_t *sdim = NULL;/* New extent dimensionality structure */
116 unsigned flags, version;
117 unsigned i; /* Local counting variable */
118 void *ret_value = NULL; /* Return value */
119
120 FUNC_ENTER_STATIC
121
122 /* check args */
123 HDassert(f);
124 HDassert(p);
125
126 /* decode */
127 if(NULL == (sdim = H5FL_CALLOC(H5S_extent_t)))
128 HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, NULL, "dataspace structure allocation failed")
129
130 /* Check version */
131 version = *p++;
132 if(version < H5O_SDSPACE_VERSION_1 || version > H5O_SDSPACE_VERSION_2)
133 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "wrong version number in dataspace message")
134 sdim->version = version;
135
136 /* Get rank */
137 sdim->rank = *p++;
138 if(sdim->rank > H5S_MAX_RANK)
139 HGOTO_ERROR(H5E_OHDR, H5E_CANTINIT, NULL, "simple dataspace dimensionality is too large")
140
141 /* Get dataspace flags for later */
142 flags = *p++;
143
144 /* Get or determine the type of the extent */
145 if(version >= H5O_SDSPACE_VERSION_2)
146 sdim->type = (H5S_class_t)*p++;
147 else {
148 /* Set the dataspace type to be simple or scalar as appropriate */
149 if(sdim->rank > 0)
150 sdim->type = H5S_SIMPLE;
151 else
152 sdim->type = H5S_SCALAR;
153
154 /* Increment past reserved byte */
155 p++;
156 } /* end else */
157 HDassert(sdim->type != H5S_NULL || sdim->version >= H5O_SDSPACE_VERSION_2);
158
159 /* Only Version 1 has these reserved bytes */
160 if(version == H5O_SDSPACE_VERSION_1)
161 p += 4; /*reserved*/
162
163 /* Decode dimension sizes */
164 if(sdim->rank > 0) {
165 if(NULL == (sdim->size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)sdim->rank)))
166 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
167
168 for(i = 0; i < sdim->rank; i++)
169 H5F_DECODE_LENGTH(f, p, sdim->size[i]);
170
171 if(flags & H5S_VALID_MAX) {
172 if(NULL == (sdim->max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)sdim->rank)))
173 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
174 for(i = 0; i < sdim->rank; i++)
175 H5F_DECODE_LENGTH (f, p, sdim->max[i]);
176 } /* end if */
177 } /* end if */
178
179 /* Compute the number of elements in the extent */
180 if(sdim->type == H5S_NULL)
181 sdim->nelem = 0;
182 else {
183 for(i = 0, sdim->nelem = 1; i < sdim->rank; i++)
184 sdim->nelem *= sdim->size[i];
185 } /* end else */
186
187 /* Set return value */
188 ret_value = (void*)sdim; /*success*/
189
190 done:
191 if(!ret_value && sdim) {
192 H5S_extent_release(sdim);
193 sdim = H5FL_FREE(H5S_extent_t, sdim);
194 } /* end if */
195
196 FUNC_LEAVE_NOAPI(ret_value)
197 } /* end H5O__sdspace_decode() */
198
199
200 /*--------------------------------------------------------------------------
201 NAME
202 H5O_sdspace_encode
203 PURPOSE
204 Encode a simple dimensionality message
205 USAGE
206 herr_t H5O_sdspace_encode(f, raw_size, p, mesg)
207 H5F_t *f; IN: pointer to the HDF5 file struct
208 size_t raw_size; IN: size of the raw information buffer
209 const uint8 *p; IN: the raw information buffer
210 const void *mesg; IN: Pointer to the extent dimensionality struct
211 RETURNS
212 Non-negative on success/Negative on failure
213 DESCRIPTION
214 This function encodes the native memory form of the simple
215 dimensionality message in the "raw" disk form.
216
217 MODIFICATIONS
218 Robb Matzke, 1998-04-09
219 The current and maximum dimensions are now H5F_SIZEOF_SIZET bytes
220 instead of just four bytes.
221
222 Robb Matzke, 1998-07-20
223 Added a version number and reformatted the message for aligment.
224
225 Raymond Lu
226 April 8, 2004
227 Added the type of dataspace into this header message using a reserved
228 byte.
229
230 --------------------------------------------------------------------------*/
231 static herr_t
H5O_sdspace_encode(H5F_t * f,uint8_t * p,const void * _mesg)232 H5O_sdspace_encode(H5F_t *f, uint8_t *p, const void *_mesg)
233 {
234 const H5S_extent_t *sdim = (const H5S_extent_t *)_mesg;
235 unsigned flags = 0;
236 unsigned u; /* Local counting variable */
237
238 FUNC_ENTER_NOAPI_NOINIT_NOERR
239
240 /* check args */
241 HDassert(f);
242 HDassert(p);
243 HDassert(sdim);
244
245 /* Version */
246 HDassert(sdim->version > 0);
247 HDassert(sdim->type != H5S_NULL || sdim->version >= H5O_SDSPACE_VERSION_2);
248 *p++ = (uint8_t)sdim->version;
249
250 /* Rank */
251 *p++ = (uint8_t)sdim->rank;
252
253 /* Flags */
254 if(sdim->max)
255 flags |= H5S_VALID_MAX;
256 *p++ = (uint8_t)flags;
257
258 /* Dataspace type */
259 if(sdim->version > H5O_SDSPACE_VERSION_1)
260 *p++ = sdim->type;
261 else {
262 *p++ = 0; /*reserved*/
263 *p++ = 0; /*reserved*/
264 *p++ = 0; /*reserved*/
265 *p++ = 0; /*reserved*/
266 *p++ = 0; /*reserved*/
267 } /* end else */
268
269 /* Current & maximum dimensions */
270 if(sdim->rank > 0) {
271 for(u = 0; u < sdim->rank; u++)
272 H5F_ENCODE_LENGTH(f, p, sdim->size[u]);
273 if(flags & H5S_VALID_MAX) {
274 for(u = 0; u < sdim->rank; u++)
275 H5F_ENCODE_LENGTH(f, p, sdim->max[u]);
276 } /* end if */
277 } /* end if */
278
279 FUNC_LEAVE_NOAPI(SUCCEED)
280 } /* end H5O_sdspace_encode() */
281
282
283 /*--------------------------------------------------------------------------
284 NAME
285 H5O_sdspace_copy
286 PURPOSE
287 Copies a message from MESG to DEST, allocating DEST if necessary.
288 USAGE
289 void *H5O_sdspace_copy(_mesg, _dest)
290 const void *_mesg; IN: Pointer to the source extent dimensionality struct
291 const void *_dest; IN: Pointer to the destination extent dimensionality struct
292 RETURNS
293 Pointer to DEST on success, NULL on failure
294 DESCRIPTION
295 This function copies a native (memory) simple dimensionality message,
296 allocating the destination structure if necessary.
297 --------------------------------------------------------------------------*/
298 static void *
H5O_sdspace_copy(const void * _mesg,void * _dest)299 H5O_sdspace_copy(const void *_mesg, void *_dest)
300 {
301 const H5S_extent_t *mesg = (const H5S_extent_t *)_mesg;
302 H5S_extent_t *dest = (H5S_extent_t *)_dest;
303 void *ret_value = NULL; /* Return value */
304
305 FUNC_ENTER_NOAPI_NOINIT
306
307 /* check args */
308 HDassert(mesg);
309 if(!dest && NULL == (dest = H5FL_CALLOC(H5S_extent_t)))
310 HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
311
312 /* Copy extent information */
313 if(H5S_extent_copy_real(dest, mesg, TRUE) < 0)
314 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent")
315
316 /* Set return value */
317 ret_value = dest;
318
319 done:
320 if(NULL == ret_value)
321 if(dest && NULL == _dest)
322 dest = H5FL_FREE(H5S_extent_t, dest);
323
324 FUNC_LEAVE_NOAPI(ret_value)
325 } /* end H5O_sdspace_copy() */
326
327
328 /*--------------------------------------------------------------------------
329 NAME
330 H5O_sdspace_size
331 PURPOSE
332 Return the raw message size in bytes
333 USAGE
334 void *H5O_sdspace_size(f, mesg)
335 H5F_t *f; IN: pointer to the HDF5 file struct
336 const void *mesg; IN: Pointer to the source extent dimensionality struct
337 RETURNS
338 Size of message on success, zero on failure
339 DESCRIPTION
340 This function returns the size of the raw simple dimensionality message on
341 success. (Not counting the message type or size fields, only the data
342 portion of the message). It doesn't take into account alignment.
343
344 MODIFICATIONS
345 Robb Matzke, 1998-04-09
346 The current and maximum dimensions are now H5F_SIZEOF_SIZET bytes
347 instead of just four bytes.
348 --------------------------------------------------------------------------*/
349 static size_t
H5O_sdspace_size(const H5F_t * f,const void * _mesg)350 H5O_sdspace_size(const H5F_t *f, const void *_mesg)
351 {
352 const H5S_extent_t *space = (const H5S_extent_t *)_mesg;
353 size_t ret_value = 0; /* Return value */
354
355 FUNC_ENTER_NOAPI_NOINIT_NOERR
356
357 /* Basic information for all dataspace messages */
358 ret_value = 1 + /* Version */
359 1 + /* Rank */
360 1 + /* Flags */
361 1 + /* Dataspace type/reserved */
362 ((space->version > H5O_SDSPACE_VERSION_1) ? 0 : 4); /* Eliminated/reserved */
363
364 /* Add in the dimension sizes */
365 ret_value += space->rank * H5F_SIZEOF_SIZE(f);
366
367 /* Add in the space for the maximum dimensions, if they are present */
368 ret_value += space->max ? (space->rank * H5F_SIZEOF_SIZE(f)) : 0;
369
370 FUNC_LEAVE_NOAPI(ret_value)
371 } /* end H5O_sdspace_size() */
372
373
374 /*-------------------------------------------------------------------------
375 * Function: H5O__sdspace_reset
376 *
377 * Purpose: Frees the inside of a dataspace message and resets it to some
378 * initial value.
379 *
380 * Return: Non-negative on success/Negative on failure
381 *
382 * Programmer: Robb Matzke
383 * Thursday, April 30, 1998
384 *
385 *-------------------------------------------------------------------------
386 */
387 static herr_t
H5O__sdspace_reset(void * _mesg)388 H5O__sdspace_reset(void *_mesg)
389 {
390 H5S_extent_t *mesg = (H5S_extent_t*)_mesg;
391
392 FUNC_ENTER_STATIC_NOERR
393
394 H5S_extent_release(mesg);
395
396 FUNC_LEAVE_NOAPI(SUCCEED)
397 } /* end H5O__sdspace_reset() */
398
399
400 /*-------------------------------------------------------------------------
401 * Function: H5O__sdsdpace_free
402 *
403 * Purpose: Frees the message
404 *
405 * Return: Non-negative on success/Negative on failure
406 *
407 * Programmer: Quincey Koziol
408 * Thursday, March 30, 2000
409 *
410 *-------------------------------------------------------------------------
411 */
412 static herr_t
H5O__sdspace_free(void * mesg)413 H5O__sdspace_free(void *mesg)
414 {
415 FUNC_ENTER_STATIC_NOERR
416
417 HDassert(mesg);
418
419 mesg = H5FL_FREE(H5S_extent_t, mesg);
420
421 FUNC_LEAVE_NOAPI(SUCCEED)
422 } /* end H5O__sdspace_free() */
423
424
425 /*-------------------------------------------------------------------------
426 * Function: H5O_sdspace_pre_copy_file
427 *
428 * Purpose: Perform any necessary actions before copying message between
429 * files
430 *
431 * Return: Success: Non-negative
432 *
433 * Failure: Negative
434 *
435 * Programmer: Quincey Koziol
436 * November 30, 2006
437 *
438 *-------------------------------------------------------------------------
439 */
440 static herr_t
H5O_sdspace_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 * _udata)441 H5O_sdspace_pre_copy_file(H5F_t H5_ATTR_UNUSED *file_src, const void *mesg_src,
442 hbool_t H5_ATTR_UNUSED *deleted, const H5O_copy_t *cpy_info, void *_udata)
443 {
444 const H5S_extent_t *src_space_extent = (const H5S_extent_t *)mesg_src; /* Source dataspace extent */
445 H5D_copy_file_ud_t *udata = (H5D_copy_file_ud_t *)_udata; /* Dataset copying user data */
446 herr_t ret_value = SUCCEED; /* Return value */
447
448 FUNC_ENTER_NOAPI_NOINIT
449
450 /* check args */
451 HDassert(file_src);
452 HDassert(src_space_extent);
453 HDassert(cpy_info);
454 HDassert(cpy_info->file_dst);
455
456 /* Check to ensure that the version of the message to be copied does not exceed
457 the message version allowed by the destination file's high bound */
458 if(src_space_extent->version > H5O_sdspace_ver_bounds[H5F_HIGH_BOUND(cpy_info->file_dst)])
459 HGOTO_ERROR(H5E_OHDR, H5E_BADRANGE, FAIL, "dataspace message version out of bounds")
460
461 /* If the user data is non-NULL, assume we are copying a dataset
462 * and make a copy of the dataspace extent for later in the object copying
463 * process. (We currently only need to make a copy of the dataspace extent
464 * if the layout is an early version, but that information isn't
465 * available here, so we just make a copy of it in all cases)
466 */
467 if(udata) {
468 /* Allocate copy of dataspace extent */
469 if(NULL == (udata->src_space_extent = H5FL_CALLOC(H5S_extent_t)))
470 HGOTO_ERROR(H5E_DATASPACE, H5E_NOSPACE, FAIL, "dataspace extent allocation failed")
471
472 /* Create a copy of the dataspace extent */
473 if(H5S_extent_copy_real(udata->src_space_extent, src_space_extent, TRUE) < 0)
474 HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
475 } /* end if */
476
477 done:
478 FUNC_LEAVE_NOAPI(ret_value)
479 } /* end H5O_dspace_pre_copy_file() */
480
481
482 /*--------------------------------------------------------------------------
483 NAME
484 H5O__sdspace_debug
485 PURPOSE
486 Prints debugging information for a simple dimensionality message
487 USAGE
488 void *H5O__sdspace_debug(f, mesg, stream, indent, fwidth)
489 H5F_t *f; IN: pointer to the HDF5 file struct
490 const void *mesg; IN: Pointer to the source extent dimensionality struct
491 FILE *stream; IN: Pointer to the stream for output data
492 int indent; IN: Amount to indent information by
493 int fwidth; IN: Field width (?)
494 RETURNS
495 Non-negative on success/Negative on failure
496 DESCRIPTION
497 This function prints debugging output to the stream passed as a
498 parameter.
499 --------------------------------------------------------------------------*/
500 static herr_t
H5O__sdspace_debug(H5F_t H5_ATTR_UNUSED * f,const void * mesg,FILE * stream,int indent,int fwidth)501 H5O__sdspace_debug(H5F_t H5_ATTR_UNUSED *f, const void *mesg, FILE * stream,
502 int indent, int fwidth)
503 {
504 const H5S_extent_t *sdim = (const H5S_extent_t *)mesg;
505
506 FUNC_ENTER_STATIC_NOERR
507
508 /* check args */
509 HDassert(f);
510 HDassert(sdim);
511 HDassert(stream);
512 HDassert(indent >= 0);
513 HDassert(fwidth >= 0);
514
515 HDfprintf(stream, "%*s%-*s %lu\n", indent, "", fwidth,
516 "Rank:",
517 (unsigned long) (sdim->rank));
518
519 if(sdim->rank > 0) {
520 unsigned u; /* local counting variable */
521
522 HDfprintf(stream, "%*s%-*s {", indent, "", fwidth, "Dim Size:");
523 for(u = 0; u < sdim->rank; u++)
524 HDfprintf (stream, "%s%Hu", u?", ":"", sdim->size[u]);
525 HDfprintf (stream, "}\n");
526
527 HDfprintf(stream, "%*s%-*s ", indent, "", fwidth, "Dim Max:");
528 if(sdim->max) {
529 HDfprintf (stream, "{");
530 for(u = 0; u < sdim->rank; u++) {
531 if(H5S_UNLIMITED==sdim->max[u])
532 HDfprintf (stream, "%sUNLIM", u?", ":"");
533 else
534 HDfprintf (stream, "%s%Hu", u?", ":"", sdim->max[u]);
535 } /* end for */
536 HDfprintf (stream, "}\n");
537 } /* end if */
538 else
539 HDfprintf (stream, "CONSTANT\n");
540 } /* end if */
541
542 FUNC_LEAVE_NOAPI(SUCCEED)
543 } /* end H5O__sdspace_debug() */
544
545