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://www.hdfgroup.org/licenses.               *
10  * If you do not have access to either file, you may request a copy from     *
11  * help@hdfgroup.org.                                                        *
12  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
13 
14 /****************/
15 /* Module Setup */
16 /****************/
17 
18 #include "H5Smodule.h" /* This source code file is part of the H5S module */
19 
20 /***********/
21 /* Headers */
22 /***********/
23 #include "H5private.h"   /* Generic Functions            */
24 #include "H5Eprivate.h"  /* Error handling              */
25 #include "H5CXprivate.h" /* API Contexts         */
26 #include "H5Fprivate.h"  /* Files                */
27 #include "H5FLprivate.h" /* Free lists                           */
28 #include "H5Iprivate.h"  /* IDs                      */
29 #include "H5MMprivate.h" /* Memory management            */
30 #include "H5Oprivate.h"  /* Object headers              */
31 #include "H5Spkg.h"      /* Dataspaces                 */
32 
33 /****************/
34 /* Local Macros */
35 /****************/
36 
37 /* Version of dataspace encoding */
38 #define H5S_ENCODE_VERSION 0
39 
40 /******************/
41 /* Local Typedefs */
42 /******************/
43 
44 /********************/
45 /* Local Prototypes */
46 /********************/
47 static htri_t H5S__is_simple(const H5S_t *sdim);
48 
49 /*****************************/
50 /* Library Private Variables */
51 /*****************************/
52 
53 /*********************/
54 /* Package Variables */
55 /*********************/
56 
57 /* Package initialization variable */
58 hbool_t H5_PKG_INIT_VAR = FALSE;
59 
60 /* Format version bounds for dataspace */
61 const unsigned H5O_sdspace_ver_bounds[] = {
62     H5O_SDSPACE_VERSION_1,     /* H5F_LIBVER_EARLIEST */
63     H5O_SDSPACE_VERSION_2,     /* H5F_LIBVER_V18 */
64     H5O_SDSPACE_VERSION_2,     /* H5F_LIBVER_V110 */
65     H5O_SDSPACE_VERSION_LATEST /* H5F_LIBVER_LATEST */
66 };
67 
68 /* Declare a free list to manage the H5S_extent_t struct */
69 H5FL_DEFINE(H5S_extent_t);
70 
71 /* Declare a free list to manage the H5S_t struct */
72 H5FL_DEFINE(H5S_t);
73 
74 /* Declare a free list to manage the array's of hsize_t's */
75 H5FL_ARR_DEFINE(hsize_t, H5S_MAX_RANK);
76 
77 /*******************/
78 /* Local Variables */
79 /*******************/
80 
81 /* Dataspace ID class */
82 static const H5I_class_t H5I_DATASPACE_CLS[1] = {{
83     H5I_DATASPACE,        /* ID class value */
84     0,                    /* Class flags */
85     2,                    /* # of reserved IDs for class */
86     (H5I_free_t)H5S_close /* Callback routine for closing objects of this class */
87 }};
88 
89 /* Dataspace selection iterator ID class */
90 static const H5I_class_t H5I_SPACE_SEL_ITER_CLS[1] = {{
91     H5I_SPACE_SEL_ITER,            /* ID class value */
92     0,                             /* Class flags */
93     0,                             /* # of reserved IDs for class */
94     (H5I_free_t)H5S_sel_iter_close /* Callback routine for closing objects of this class */
95 }};
96 
97 /* Flag indicating "top" of interface has been initialized */
98 static hbool_t H5S_top_package_initialize_s = FALSE;
99 
100 /*--------------------------------------------------------------------------
101 NAME
102    H5S__init_package -- Initialize interface-specific information
103 USAGE
104     herr_t H5S__init_package()
105 RETURNS
106     Non-negative on success/Negative on failure
107 DESCRIPTION
108     Initializes any interface-specific data or routines.
109 --------------------------------------------------------------------------*/
110 herr_t
H5S__init_package(void)111 H5S__init_package(void)
112 {
113     herr_t ret_value = SUCCEED; /* Return value */
114 
115     FUNC_ENTER_PACKAGE
116 
117     /* Initialize the atom group for the dataspace IDs */
118     if (H5I_register_type(H5I_DATASPACE_CLS) < 0)
119         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to initialize dataspace ID class")
120 
121     /* Initialize the atom group for the dataspace selction iterator IDs */
122     if (H5I_register_type(H5I_SPACE_SEL_ITER_CLS) < 0)
123         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL,
124                     "unable to initialize dataspace selection iterator ID class")
125 
126     /* Mark "top" of interface as initialized, too */
127     H5S_top_package_initialize_s = TRUE;
128 
129 done:
130     FUNC_LEAVE_NOAPI(ret_value)
131 } /* end H5S__init_package() */
132 
133 /*--------------------------------------------------------------------------
134  NAME
135     H5S_top_term_package
136  PURPOSE
137     Terminate various H5S objects
138  USAGE
139     void H5S_top_term_package()
140  RETURNS
141     Non-negative on success/Negative on failure
142  DESCRIPTION
143     Release IDs for the atom group, deferring full interface shutdown
144     until later (in H5S_term_package).
145  GLOBAL VARIABLES
146  COMMENTS, BUGS, ASSUMPTIONS
147      Can't report errors...
148  EXAMPLES
149  REVISION LOG
150 --------------------------------------------------------------------------*/
151 int
H5S_top_term_package(void)152 H5S_top_term_package(void)
153 {
154     int n = 0;
155 
156     FUNC_ENTER_NOAPI_NOINIT_NOERR
157 
158     if (H5S_top_package_initialize_s) {
159         if (H5I_nmembers(H5I_DATASPACE) > 0) {
160             (void)H5I_clear_type(H5I_DATASPACE, FALSE, FALSE);
161             n++; /*H5I*/
162         }        /* end if */
163 
164         if (H5I_nmembers(H5I_SPACE_SEL_ITER) > 0) {
165             (void)H5I_clear_type(H5I_SPACE_SEL_ITER, FALSE, FALSE);
166             n++; /*H5I*/
167         }        /* end if */
168 
169         /* Mark "top" of interface as closed */
170         if (0 == n)
171             H5S_top_package_initialize_s = FALSE;
172     } /* end if */
173 
174     FUNC_LEAVE_NOAPI(n)
175 } /* end H5S_top_term_package() */
176 
177 /*--------------------------------------------------------------------------
178  NAME
179     H5S_term_package
180  PURPOSE
181     Terminate various H5S objects
182  USAGE
183     void H5S_term_package()
184  RETURNS
185     Non-negative on success/Negative on failure
186  DESCRIPTION
187     Release the atom group and any other resources allocated.
188  GLOBAL VARIABLES
189  COMMENTS, BUGS, ASSUMPTIONS
190      Can't report errors...
191 
192      Finishes shutting down the interface, after H5S_top_term_package()
193      is called
194  EXAMPLES
195  REVISION LOG
196 --------------------------------------------------------------------------*/
197 int
H5S_term_package(void)198 H5S_term_package(void)
199 {
200     int n = 0;
201 
202     FUNC_ENTER_NOAPI_NOINIT_NOERR
203 
204     if (H5_PKG_INIT_VAR) {
205         /* Sanity checks */
206         HDassert(0 == H5I_nmembers(H5I_DATASPACE));
207         HDassert(0 == H5I_nmembers(H5I_SPACE_SEL_ITER));
208         HDassert(FALSE == H5S_top_package_initialize_s);
209 
210         /* Destroy the dataspace object id group */
211         n += (H5I_dec_type_ref(H5I_DATASPACE) > 0);
212 
213         /* Destroy the dataspace selection iterator object id group */
214         n += (H5I_dec_type_ref(H5I_SPACE_SEL_ITER) > 0);
215 
216         /* Mark interface as closed */
217         if (0 == n)
218             H5_PKG_INIT_VAR = FALSE;
219     } /* end if */
220 
221     FUNC_LEAVE_NOAPI(n)
222 } /* end H5S_term_package() */
223 
224 /*--------------------------------------------------------------------------
225  NAME
226     H5S_get_validiated_dataspace
227  PURPOSE
228     Get a pointer to a validated H5S_t pointer
229  USAGE
230    H5S_t *H5S_get_validated_space(dataspace_id, space)
231     hid_t           space_id;       IN: The ID of the dataspace
232     const H5S_t *   space;          OUT: A pointer to the dataspace
233  RETURNS
234     SUCCEED/FAIL
235  DESCRIPTION
236     Gets a pointer to a dataspace struct after validating it. The pointer
237     can be NULL (if the ID is H5S_ALL, for example).
238  GLOBAL VARIABLES
239  COMMENTS, BUGS, ASSUMPTIONS
240  EXAMPLES
241  REVISION LOG
242 --------------------------------------------------------------------------*/
243 herr_t
H5S_get_validated_dataspace(hid_t space_id,const H5S_t ** space)244 H5S_get_validated_dataspace(hid_t space_id, const H5S_t **space)
245 {
246     herr_t ret_value = SUCCEED; /* Return value */
247 
248     FUNC_ENTER_NOAPI(FAIL)
249 
250     HDassert(space);
251 
252     /* Check for invalid ID */
253     if (space_id < 0)
254         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "invalid space_id (ID cannot be a negative number)")
255 
256     /* No special dataspace struct for H5S_ALL */
257     if (H5S_ALL == space_id)
258         *space = NULL;
259     else {
260         /* Get the dataspace pointer */
261         if (NULL == (*space = (const H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
262             HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "space_id is not a dataspace ID")
263 
264         /* Check for valid selection */
265         if (H5S_SELECT_VALID(*space) != TRUE)
266             HGOTO_ERROR(H5E_DATASPACE, H5E_BADRANGE, FAIL, "selection + offset not within extent")
267     }
268 
269 done:
270     FUNC_LEAVE_NOAPI(ret_value)
271 } /* end H5S_get_validated_dataspace() */
272 
273 /*--------------------------------------------------------------------------
274  NAME
275     H5S_create
276  PURPOSE
277     Create empty, typed dataspace
278  USAGE
279    H5S_t *H5S_create(type)
280     H5S_type_t  type;           IN: Dataspace type to create
281  RETURNS
282     Pointer to dataspace on success, NULL on failure
283  DESCRIPTION
284     Creates a new dataspace of a given type.  The extent is undefined and the
285     selection is set to the "all" selection.
286  GLOBAL VARIABLES
287  COMMENTS, BUGS, ASSUMPTIONS
288  EXAMPLES
289  REVISION LOG
290 --------------------------------------------------------------------------*/
291 H5S_t *
H5S_create(H5S_class_t type)292 H5S_create(H5S_class_t type)
293 {
294     H5S_t *new_ds    = NULL; /* New dataspace created */
295     H5S_t *ret_value = NULL; /* Return value */
296 
297     FUNC_ENTER_NOAPI(NULL)
298 
299     /* Create a new dataspace */
300     if (NULL == (new_ds = H5FL_CALLOC(H5S_t)))
301         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
302 
303     /* Initialize default dataspace state */
304     new_ds->extent.type = type;
305     if (type == H5S_NULL)
306         new_ds->extent.version = H5O_SDSPACE_VERSION_2;
307     else
308         new_ds->extent.version = H5O_SDSPACE_VERSION_1;
309     new_ds->extent.rank = 0;
310     new_ds->extent.size = new_ds->extent.max = NULL;
311 
312     switch (type) {
313         case H5S_SCALAR:
314             new_ds->extent.nelem = 1;
315             break;
316 
317         case H5S_SIMPLE:
318         case H5S_NULL:
319             new_ds->extent.nelem = 0;
320             break;
321 
322         case H5S_NO_CLASS:
323         default:
324             HDassert("unknown dataspace (extent) type" && 0);
325             break;
326     } /* end switch */
327 
328     /* Start with "all" selection */
329     if (H5S_select_all(new_ds, FALSE) < 0)
330         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
331 
332     /* Reset common selection info pointer */
333     new_ds->select.sel_info.hslab = NULL;
334 
335     /* Reset "shared" info on extent */
336     if (H5O_msg_reset_share(H5O_SDSPACE_ID, &(new_ds->extent.sh_loc)) < 0)
337         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, NULL, "unable to reset shared component info")
338 
339     /* Set return value */
340     ret_value = new_ds;
341 
342 done:
343     if (ret_value == NULL)
344         if (new_ds && H5S_close(new_ds) < 0)
345             HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, NULL, "unable to release dataspace")
346 
347     FUNC_LEAVE_NOAPI(ret_value)
348 } /* end H5S_create() */
349 
350 /*--------------------------------------------------------------------------
351  NAME
352     H5Screate
353  PURPOSE
354     Create empty, typed dataspace
355  USAGE
356    hid_t  H5Screate(type)
357     H5S_type_t  type;           IN: Dataspace type to create
358  RETURNS
359     Valid dataspace ID on success, negative on failure
360  DESCRIPTION
361     Creates a new dataspace of a given type.  The extent & selection are
362     undefined
363  GLOBAL VARIABLES
364  COMMENTS, BUGS, ASSUMPTIONS
365  EXAMPLES
366  REVISION LOG
367 --------------------------------------------------------------------------*/
368 hid_t
H5Screate(H5S_class_t type)369 H5Screate(H5S_class_t type)
370 {
371     H5S_t *new_ds = NULL; /* New dataspace structure */
372     hid_t  ret_value;     /* Return value */
373 
374     FUNC_ENTER_API(FAIL)
375     H5TRACE1("i", "Sc", type);
376 
377     /* Check args */
378     if (type <= H5S_NO_CLASS || type > H5S_NULL) /* don't allow complex dataspace yet */
379         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid dataspace type")
380 
381     if (NULL == (new_ds = H5S_create(type)))
382         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, FAIL, "unable to create dataspace")
383 
384     /* Atomize */
385     if ((ret_value = H5I_register(H5I_DATASPACE, new_ds, TRUE)) < 0)
386         HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, FAIL, "unable to register dataspace atom")
387 
388 done:
389     if (ret_value < 0)
390         if (new_ds && H5S_close(new_ds) < 0)
391             HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace")
392 
393     FUNC_LEAVE_API(ret_value)
394 } /* end H5Screate() */
395 
396 /*-------------------------------------------------------------------------
397  * Function:    H5S__extent_release
398  *
399  * Purpose:     Releases all memory associated with a dataspace extent.
400  *
401  * Return:      Non-negative on success/Negative on failure
402  *
403  * Programmer:  Quincey Koziol
404  *              Thursday, July 23, 1998
405  *
406  *-------------------------------------------------------------------------
407  */
408 herr_t
H5S__extent_release(H5S_extent_t * extent)409 H5S__extent_release(H5S_extent_t *extent)
410 {
411     FUNC_ENTER_PACKAGE_NOERR
412 
413     HDassert(extent);
414 
415     /* Release extent */
416     if (extent->type == H5S_SIMPLE) {
417         if (extent->size)
418             extent->size = H5FL_ARR_FREE(hsize_t, extent->size);
419         if (extent->max)
420             extent->max = H5FL_ARR_FREE(hsize_t, extent->max);
421     } /* end if */
422 
423     extent->rank  = 0;
424     extent->nelem = 0;
425 
426     FUNC_LEAVE_NOAPI(SUCCEED)
427 } /* end H5S__extent_release() */
428 
429 /*-------------------------------------------------------------------------
430  * Function:    H5S_close
431  *
432  * Purpose:     Releases all memory associated with a dataspace.
433  *
434  * Return:      Non-negative on success/Negative on failure
435  *
436  * Programmer:  Robb Matzke
437  *              Tuesday, December  9, 1997
438  *
439  *-------------------------------------------------------------------------
440  */
441 herr_t
H5S_close(H5S_t * ds)442 H5S_close(H5S_t *ds)
443 {
444     herr_t ret_value = SUCCEED; /* Return value */
445 
446     FUNC_ENTER_NOAPI(FAIL)
447 
448     HDassert(ds);
449 
450     /* Release selection (this should come before the extent release) */
451     if (H5S_SELECT_RELEASE(ds) < 0)
452         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace selection")
453 
454     /* Release extent */
455     if (H5S__extent_release(&ds->extent) < 0)
456         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent")
457 
458 done:
459     /* Release the main structure.
460      * Always do this to ensure that we don't leak memory when calling this
461      * function on partially constructed dataspaces (which will fail one or
462      * both of the above calls)
463      */
464     H5FL_FREE(H5S_t, ds);
465 
466     FUNC_LEAVE_NOAPI(ret_value)
467 } /* end H5S_close() */
468 
469 /*-------------------------------------------------------------------------
470  * Function:    H5Sclose
471  *
472  * Purpose:     Release access to a dataspace object.
473  *
474  * Return:      Non-negative on success/Negative on failure
475  *
476  * Programmer:  Robb Matzke
477  *              Tuesday, December  9, 1997
478  *
479  *-------------------------------------------------------------------------
480  */
481 herr_t
H5Sclose(hid_t space_id)482 H5Sclose(hid_t space_id)
483 {
484     herr_t ret_value = SUCCEED; /* Return value */
485 
486     FUNC_ENTER_API(FAIL)
487     H5TRACE1("e", "i", space_id);
488 
489     /* Check args */
490     if (NULL == H5I_object_verify(space_id, H5I_DATASPACE))
491         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
492 
493     /* When the reference count reaches zero the resources are freed */
494     if (H5I_dec_app_ref(space_id) < 0)
495         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDEC, FAIL, "problem freeing id")
496 
497 done:
498     FUNC_LEAVE_API(ret_value)
499 } /* end H5Sclose() */
500 
501 /*-------------------------------------------------------------------------
502  * Function:    H5Scopy
503  *
504  * Purpose:     Copies a dataspace.
505  *
506  * Return:      Success:    ID of the new dataspace
507  *
508  *              Failure:    H5I_INVALID_HID
509  *
510  * Programmer:  Robb Matzke
511  *              Friday, January 30, 1998
512  *
513  *-------------------------------------------------------------------------
514  */
515 hid_t
H5Scopy(hid_t space_id)516 H5Scopy(hid_t space_id)
517 {
518     H5S_t *src       = NULL;
519     H5S_t *dst       = NULL;
520     hid_t  ret_value = H5I_INVALID_HID;
521 
522     FUNC_ENTER_API(H5I_INVALID_HID)
523     H5TRACE1("i", "i", space_id);
524 
525     /* Check args */
526     if (NULL == (src = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
527         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5I_INVALID_HID, "not a dataspace")
528 
529     /* Copy */
530     if (NULL == (dst = H5S_copy(src, FALSE, TRUE)))
531         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, H5I_INVALID_HID, "unable to copy dataspace")
532 
533     /* Atomize */
534     if ((ret_value = H5I_register(H5I_DATASPACE, dst, TRUE)) < 0)
535         HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace atom")
536 
537 done:
538     if (ret_value < 0)
539         if (dst && H5S_close(dst) < 0)
540             HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace")
541 
542     FUNC_LEAVE_API(ret_value)
543 } /* end H5Scopy() */
544 
545 /*-------------------------------------------------------------------------
546  * Function:    H5Sextent_copy
547  *
548  * Purpose:     Copies a dataspace extent.
549  *
550  * Return:      Non-negative on success/Negative on failure
551  *
552  * Programmer:  Quincey Koziol
553  *              Thursday, July 23, 1998
554  *
555  *-------------------------------------------------------------------------
556  */
557 herr_t
H5Sextent_copy(hid_t dst_id,hid_t src_id)558 H5Sextent_copy(hid_t dst_id, hid_t src_id)
559 {
560     H5S_t *src;
561     H5S_t *dst;
562     herr_t ret_value = SUCCEED;
563 
564     FUNC_ENTER_API(FAIL)
565     H5TRACE2("e", "ii", dst_id, src_id);
566 
567     /* Check args */
568     if (NULL == (src = (H5S_t *)H5I_object_verify(src_id, H5I_DATASPACE)))
569         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
570     if (NULL == (dst = (H5S_t *)H5I_object_verify(dst_id, H5I_DATASPACE)))
571         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
572 
573     /* Copy */
574     if (H5S_extent_copy(dst, src) < 0)
575         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
576 
577 done:
578     FUNC_LEAVE_API(ret_value)
579 } /* end H5Sextent_copy() */
580 
581 /*-------------------------------------------------------------------------
582  * Function:    H5S_extent_copy
583  *
584  * Purpose:     Copies a dataspace extent
585  *
586  * Return:      Non-negative on success/Negative on failure
587  *
588  * Programmer:  Neil Fortner
589  *              Monday, February 23, 2015
590  *
591  *-------------------------------------------------------------------------
592  */
593 herr_t
H5S_extent_copy(H5S_t * dst,const H5S_t * src)594 H5S_extent_copy(H5S_t *dst, const H5S_t *src)
595 {
596     herr_t ret_value = SUCCEED; /* Return value */
597 
598     FUNC_ENTER_NOAPI(FAIL)
599 
600     HDassert(dst);
601     HDassert(src);
602 
603     /* Copy extent */
604     if (H5S__extent_copy_real(&(dst->extent), &(src->extent), TRUE) < 0)
605         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy extent")
606 
607     /* If the selection is 'all', update the number of elements selected in the
608      * destination space */
609     if (H5S_SEL_ALL == H5S_GET_SELECT_TYPE(dst))
610         if (H5S_select_all(dst, FALSE) < 0)
611             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
612 
613 done:
614     FUNC_LEAVE_NOAPI(ret_value)
615 } /* end H5S_extent_copy() */
616 
617 /*-------------------------------------------------------------------------
618  * Function:    H5S__extent_copy_real
619  *
620  * Purpose:     Copies a dataspace extent
621  *
622  * Return:      Non-negative on success/Negative on failure
623  *
624  * Programmer:  Quincey Koziol
625  *              Wednesday, June  3, 1998
626  *
627  *-------------------------------------------------------------------------
628  */
629 herr_t
H5S__extent_copy_real(H5S_extent_t * dst,const H5S_extent_t * src,hbool_t copy_max)630 H5S__extent_copy_real(H5S_extent_t *dst, const H5S_extent_t *src, hbool_t copy_max)
631 {
632     unsigned u;
633     herr_t   ret_value = SUCCEED; /* Return value */
634 
635     FUNC_ENTER_PACKAGE
636 
637     /* Release destination extent before we copy over it */
638     if (H5S__extent_release(dst) < 0)
639         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release dataspace extent")
640 
641     /* Copy the regular fields */
642     dst->type    = src->type;
643     dst->version = src->version;
644     dst->nelem   = src->nelem;
645     dst->rank    = src->rank;
646 
647     switch (src->type) {
648         case H5S_NULL:
649         case H5S_SCALAR:
650             dst->size = NULL;
651             dst->max  = NULL;
652             break;
653 
654         case H5S_SIMPLE:
655             if (src->size) {
656                 dst->size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)src->rank);
657                 for (u = 0; u < src->rank; u++)
658                     dst->size[u] = src->size[u];
659             } /* end if */
660             else
661                 dst->size = NULL;
662             if (copy_max && src->max) {
663                 dst->max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)src->rank);
664                 for (u = 0; u < src->rank; u++)
665                     dst->max[u] = src->max[u];
666             } /* end if */
667             else
668                 dst->max = NULL;
669             break;
670 
671         case H5S_NO_CLASS:
672         default:
673             HDassert("unknown dataspace type" && 0);
674             break;
675     } /* end switch */
676 
677     /* Copy the shared object info */
678     if (H5O_set_shared(&(dst->sh_loc), &(src->sh_loc)) < 0)
679         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, FAIL, "can't copy shared information")
680 
681 done:
682     FUNC_LEAVE_NOAPI(ret_value)
683 } /* end H5S__extent_copy_real() */
684 
685 /*-------------------------------------------------------------------------
686  * Function:    H5S_copy
687  *
688  * Purpose:     Copies a dataspace, by copying the extent and selection through
689  *              H5S_extent_copy and H5S_select_copy.  If the SHARE_SELECTION flag
690  *              is set, then the selection can be shared between the source and
691  *              destination dataspaces.  (This should only occur in situations
692  *              where the destination dataspace will immediately change to a new
693  *              selection)
694  *
695  * Return:      Success:    A pointer to a new copy of SRC
696  *
697  *              Failure:    NULL
698  *
699  * Programmer:  Robb Matzke
700  *              Thursday, December  4, 1997
701  *
702  *-------------------------------------------------------------------------
703  */
704 H5S_t *
H5S_copy(const H5S_t * src,hbool_t share_selection,hbool_t copy_max)705 H5S_copy(const H5S_t *src, hbool_t share_selection, hbool_t copy_max)
706 {
707     H5S_t *dst       = NULL;
708     H5S_t *ret_value = NULL; /* Return value */
709 
710     FUNC_ENTER_NOAPI(NULL)
711 
712     if (NULL == (dst = H5FL_CALLOC(H5S_t)))
713         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
714 
715     /* Copy the source dataspace's extent */
716     if (H5S__extent_copy_real(&(dst->extent), &(src->extent), copy_max) < 0)
717         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy extent")
718 
719     /* Copy the source dataspace's selection */
720     if (H5S_select_copy(dst, src, share_selection) < 0)
721         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy select")
722 
723     /* Set the return value */
724     ret_value = dst;
725 
726 done:
727     if (NULL == ret_value)
728         if (dst)
729             dst = H5FL_FREE(H5S_t, dst);
730 
731     FUNC_LEAVE_NOAPI(ret_value)
732 } /* end H5S_copy() */
733 
734 /*-------------------------------------------------------------------------
735  * Function:    H5S_get_simple_extent_npoints
736  *
737  * Purpose:     Determines how many data points a dataset extent has.
738  *
739  * Return:      Success:    Number of data points in the dataset extent.
740  *
741  *              Failure:    Negative
742  *
743  * Programmer:  Robb Matzke
744  *              Tuesday, December  9, 1997
745  *
746  * Note:        This routine participates in the "Inlining C function pointers"
747  *              pattern, don't call it directly, use the appropriate macro
748  *              defined in H5Sprivate.h.
749  *
750  *-------------------------------------------------------------------------
751  */
752 hssize_t
H5S_get_simple_extent_npoints(const H5S_t * ds)753 H5S_get_simple_extent_npoints(const H5S_t *ds)
754 {
755     hssize_t ret_value = -1; /* Return value */
756 
757     FUNC_ENTER_NOAPI(-1)
758 
759     /* check args */
760     HDassert(ds);
761 
762     /* Get the number of elements in extent */
763     ret_value = (hssize_t)ds->extent.nelem;
764 
765 done:
766     FUNC_LEAVE_NOAPI(ret_value)
767 } /* end H5S_get_simple_extent_npoints() */
768 
769 /*-------------------------------------------------------------------------
770  * Function:    H5Sget_simple_extent_npoints
771  *
772  * Purpose:     Determines how many data points a dataset extent has.
773  *
774  * Return:      Success:    Number of data points in the dataset.
775  *              Failure:    Negative
776  *
777  * Programmer:  Robb Matzke
778  *              Tuesday, December  9, 1997
779  *
780  *-------------------------------------------------------------------------
781  */
782 hssize_t
H5Sget_simple_extent_npoints(hid_t space_id)783 H5Sget_simple_extent_npoints(hid_t space_id)
784 {
785     H5S_t *  ds;
786     hssize_t ret_value;
787 
788     FUNC_ENTER_API(FAIL)
789     H5TRACE1("Hs", "i", space_id);
790 
791     /* Check args */
792     if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
793         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
794 
795     ret_value = (hssize_t)H5S_GET_EXTENT_NPOINTS(ds);
796 
797 done:
798     FUNC_LEAVE_API(ret_value)
799 } /* end H5Sget_simple_extent_npoints() */
800 
801 /*-------------------------------------------------------------------------
802  * Function:    H5S_get_npoints_max
803  *
804  * Purpose:     Determines the maximum number of data points a dataspace may
805  *              have.  If the `max' array is null then the maximum number of
806  *              data points is the same as the current number of data points
807  *              without regard to the hyperslab.  If any element of the `max'
808  *              array is zero then the maximum possible size is returned.
809  *
810  * Return:      Success:    Maximum number of data points the dataspace
811  *                          may have.
812  *              Failure:    0
813  *
814  * Programmer:  Robb Matzke
815  *              Tuesday, December  9, 1997
816  *
817  *-------------------------------------------------------------------------
818  */
819 hsize_t
H5S_get_npoints_max(const H5S_t * ds)820 H5S_get_npoints_max(const H5S_t *ds)
821 {
822     unsigned u;
823     hsize_t  ret_value = 0; /* Return value */
824 
825     FUNC_ENTER_NOAPI(0)
826 
827     /* check args */
828     HDassert(ds);
829 
830     switch (H5S_GET_EXTENT_TYPE(ds)) {
831         case H5S_NULL:
832             ret_value = 0;
833             break;
834 
835         case H5S_SCALAR:
836             ret_value = 1;
837             break;
838 
839         case H5S_SIMPLE:
840             if (ds->extent.max) {
841                 for (ret_value = 1, u = 0; u < ds->extent.rank; u++) {
842                     if (H5S_UNLIMITED == ds->extent.max[u]) {
843                         ret_value = HSIZET_MAX;
844                         break;
845                     }
846                     else
847                         ret_value *= ds->extent.max[u];
848                 }
849             }
850             else
851                 for (ret_value = 1, u = 0; u < ds->extent.rank; u++)
852                     ret_value *= ds->extent.size[u];
853             break;
854 
855         case H5S_NO_CLASS:
856         default:
857             HDassert("unknown dataspace class" && 0);
858             HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, 0, "internal error (unknown dataspace class)")
859     }
860 
861 done:
862     FUNC_LEAVE_NOAPI(ret_value)
863 } /* end H5S_get_npoints_max() */
864 
865 /*-------------------------------------------------------------------------
866  * Function:    H5Sget_simple_extent_ndims
867  *
868  * Purpose:     Determines the dimensionality of a dataspace.
869  *
870  * Return:      Success:    The number of dimensions in a dataspace.
871  *              Failure:    Negative
872  *
873  * Programmer:  Robb Matzke
874  *              Thursday, December 11, 1997
875  *
876  *-------------------------------------------------------------------------
877  */
878 int
H5Sget_simple_extent_ndims(hid_t space_id)879 H5Sget_simple_extent_ndims(hid_t space_id)
880 {
881     H5S_t *ds;
882     int    ret_value = -1;
883 
884     FUNC_ENTER_API((-1))
885     H5TRACE1("Is", "i", space_id);
886 
887     /* Check args */
888     if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
889         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a dataspace")
890 
891     ret_value = (int)H5S_GET_EXTENT_NDIMS(ds);
892 
893 done:
894     FUNC_LEAVE_API(ret_value)
895 } /* end H5Sget_simple_extent_ndims() */
896 
897 /*-------------------------------------------------------------------------
898  * Function:    H5S_get_simple_extent_ndims
899  *
900  * Purpose:     Returns the number of dimensions in a dataspace.
901  *
902  * Return:      Success:    Non-negative number of dimensions.
903  *                          Zero implies a scalar.
904  *
905  *              Failure:    Negative
906  *
907  * Programmer:  Robb Matzke
908  *              hursday, December 11, 1997
909  *
910  * Note:        This routine participates in the "Inlining C function pointers"
911  *              pattern, don't call it directly, use the appropriate macro
912  *              defined in H5Sprivate.h.
913  *
914  *-------------------------------------------------------------------------
915  */
916 int
H5S_get_simple_extent_ndims(const H5S_t * ds)917 H5S_get_simple_extent_ndims(const H5S_t *ds)
918 {
919     int ret_value = -1; /* Return value */
920 
921     FUNC_ENTER_NOAPI(FAIL)
922 
923     /* check args */
924     HDassert(ds);
925 
926     switch (H5S_GET_EXTENT_TYPE(ds)) {
927         case H5S_NULL:
928         case H5S_SCALAR:
929         case H5S_SIMPLE:
930             ret_value = (int)ds->extent.rank;
931             break;
932 
933         case H5S_NO_CLASS:
934         default:
935             HDassert("unknown dataspace class" && 0);
936             HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown dataspace class)")
937     } /* end switch */
938 
939 done:
940     FUNC_LEAVE_NOAPI(ret_value)
941 } /* end H5S_get_simple_extent_ndims() */
942 
943 /*-------------------------------------------------------------------------
944  * Function:    H5Sget_simple_extent_dims
945  *
946  * Purpose:     Returns the size and maximum sizes in each dimension of
947  *              a dataspace DS through the DIMS and MAXDIMS arguments.
948  *
949  * Return:      Success:    Number of dimensions, the same value as
950  *                          returned by H5Sget_simple_extent_ndims().
951  *
952  *              Failure:    Negative
953  *
954  * Programmer:  Robb Matzke
955  *              Thursday, December 11, 1997
956  *
957  *-------------------------------------------------------------------------
958  */
959 int
H5Sget_simple_extent_dims(hid_t space_id,hsize_t dims[],hsize_t maxdims[])960 H5Sget_simple_extent_dims(hid_t space_id, hsize_t dims[] /*out*/, hsize_t maxdims[] /*out*/)
961 {
962     H5S_t *ds;
963     int    ret_value = -1;
964 
965     FUNC_ENTER_API((-1))
966     H5TRACE3("Is", "ixx", space_id, dims, maxdims);
967 
968     /* Check args */
969     if (NULL == (ds = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
970         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, (-1), "not a dataspace")
971 
972     ret_value = H5S_get_simple_extent_dims(ds, dims, maxdims);
973 
974 done:
975     FUNC_LEAVE_API(ret_value)
976 } /* end H5Sget_simple_extent_dims() */
977 
978 /*-------------------------------------------------------------------------
979  * Function:    H5S_extent_get_dims
980  *
981  * Purpose:     Returns the size in each dimension of a dataspace.  This
982  *              function may not be meaningful for all types of dataspaces.
983  *
984  * Return:      Success:    Number of dimensions.  Zero implies scalar.
985  *              Failure:    Negative
986  *
987  * Programmer:  Quincey Koziol
988  *              Tuesday, June 30, 2009
989  *
990  *-------------------------------------------------------------------------
991  */
992 int
H5S_extent_get_dims(const H5S_extent_t * ext,hsize_t dims[],hsize_t max_dims[])993 H5S_extent_get_dims(const H5S_extent_t *ext, hsize_t dims[], hsize_t max_dims[])
994 {
995     int i;              /* Local index variable */
996     int ret_value = -1; /* Return value */
997 
998     FUNC_ENTER_NOAPI(FAIL)
999 
1000     /* check args */
1001     HDassert(ext);
1002 
1003     switch (ext->type) {
1004         case H5S_NULL:
1005         case H5S_SCALAR:
1006             ret_value = 0;
1007             break;
1008 
1009         case H5S_SIMPLE:
1010             ret_value = (int)ext->rank;
1011             for (i = 0; i < ret_value; i++) {
1012                 if (dims)
1013                     dims[i] = ext->size[i];
1014                 if (max_dims) {
1015                     if (ext->max)
1016                         max_dims[i] = ext->max[i];
1017                     else
1018                         max_dims[i] = ext->size[i];
1019                 } /* end if */
1020             }     /* end for */
1021             break;
1022 
1023         case H5S_NO_CLASS:
1024         default:
1025             HDassert("unknown dataspace class" && 0);
1026             HGOTO_ERROR(H5E_DATASPACE, H5E_UNSUPPORTED, FAIL, "internal error (unknown dataspace class)")
1027     } /* end switch */
1028 
1029 done:
1030     FUNC_LEAVE_NOAPI(ret_value)
1031 } /* end H5S_extent_get_dims() */
1032 
1033 /*-------------------------------------------------------------------------
1034  * Function:    H5S_get_simple_extent_dims
1035  *
1036  * Purpose:     Returns the size in each dimension of a dataspace.  This
1037  *              function may not be meaningful for all types of dataspaces.
1038  *
1039  * Return:      Success:    Number of dimensions.  Zero implies scalar.
1040  *              Failure:    Negative
1041  *
1042  * Programmer:  Robb Matzke
1043  *              Thursday, December 11, 1997
1044  *
1045  *-------------------------------------------------------------------------
1046  */
1047 int
H5S_get_simple_extent_dims(const H5S_t * ds,hsize_t dims[],hsize_t max_dims[])1048 H5S_get_simple_extent_dims(const H5S_t *ds, hsize_t dims[], hsize_t max_dims[])
1049 {
1050     int ret_value = -1; /* Return value */
1051 
1052     FUNC_ENTER_NOAPI(FAIL)
1053 
1054     /* check args */
1055     HDassert(ds);
1056 
1057     /* Get dims for extent */
1058     if ((ret_value = H5S_extent_get_dims(&ds->extent, dims, max_dims)) < 0)
1059         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTGET, FAIL, "can't retrieve dataspace extent dims")
1060 
1061 done:
1062     FUNC_LEAVE_NOAPI(ret_value)
1063 } /* end H5S_get_simple_extent_dims() */
1064 
1065 /*-------------------------------------------------------------------------
1066  * Function:    H5S_write
1067  *
1068  * Purpose:     Updates a dataspace by writing a message to an object
1069  *              header.
1070  *
1071  * Return:      Non-negative on success/Negative on failure
1072  *
1073  * Programmer:  Robb Matzke
1074  *              Tuesday, December  9, 1997
1075  *
1076  *-------------------------------------------------------------------------
1077  */
1078 herr_t
H5S_write(H5F_t * f,H5O_t * oh,unsigned update_flags,H5S_t * ds)1079 H5S_write(H5F_t *f, H5O_t *oh, unsigned update_flags, H5S_t *ds)
1080 {
1081     herr_t ret_value = SUCCEED; /* Return value */
1082 
1083     FUNC_ENTER_NOAPI(FAIL)
1084 
1085     HDassert(f);
1086     HDassert(oh);
1087     HDassert(ds);
1088     HDassert(H5S_GET_EXTENT_TYPE(ds) >= 0);
1089 
1090     /* Write the current dataspace extent to the dataspace message */
1091     if (H5O_msg_write_oh(f, oh, H5O_SDSPACE_ID, 0, update_flags, &(ds->extent)) < 0)
1092         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't update simple dataspace message")
1093 
1094 done:
1095     FUNC_LEAVE_NOAPI(ret_value)
1096 } /* end H5S_write() */
1097 
1098 /*-------------------------------------------------------------------------
1099  * Function:    H5S_append
1100  *
1101  * Purpose:     Updates a dataspace by adding a message to an object header.
1102  *
1103  * Return:      Non-negative on success/Negative on failure
1104  *
1105  * Programmer:  Quincey Koziol
1106  *              Tuesday, December 31, 2002
1107  *
1108  *-------------------------------------------------------------------------
1109  */
1110 herr_t
H5S_append(H5F_t * f,H5O_t * oh,H5S_t * ds)1111 H5S_append(H5F_t *f, H5O_t *oh, H5S_t *ds)
1112 {
1113     herr_t ret_value = SUCCEED; /* Return value */
1114 
1115     FUNC_ENTER_NOAPI(FAIL)
1116 
1117     HDassert(f);
1118     HDassert(oh);
1119     HDassert(ds);
1120     HDassert(H5S_GET_EXTENT_TYPE(ds) >= 0);
1121 
1122     /* Add the dataspace message to the object header */
1123     if (H5O_msg_append_oh(f, oh, H5O_SDSPACE_ID, 0, 0, &(ds->extent)) < 0)
1124         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "can't add simple dataspace message")
1125 
1126 done:
1127     FUNC_LEAVE_NOAPI(ret_value)
1128 } /* end H5S_append() */
1129 
1130 /*-------------------------------------------------------------------------
1131  * Function:    H5S_read
1132  *
1133  * Purpose:     Reads the dataspace from an object header.
1134  *
1135  * Return:      Success:    Pointer to a new dataspace.
1136  *
1137  *              Failure:    NULL
1138  *
1139  * Programmer:  Robb Matzke
1140  *              Tuesday, December  9, 1997
1141  *
1142  *-------------------------------------------------------------------------
1143  */
1144 H5S_t *
H5S_read(const H5O_loc_t * loc)1145 H5S_read(const H5O_loc_t *loc)
1146 {
1147     H5S_t *ds        = NULL; /* Dataspace to return */
1148     H5S_t *ret_value = NULL; /* Return value */
1149 
1150     FUNC_ENTER_NOAPI(NULL)
1151 
1152     /* check args */
1153     HDassert(loc);
1154 
1155     if (NULL == (ds = H5FL_CALLOC(H5S_t)))
1156         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL, "memory allocation failed")
1157 
1158     if (NULL == H5O_msg_read(loc, H5O_SDSPACE_ID, &(ds->extent)))
1159         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "unable to load dataspace info from dataset header")
1160 
1161     /* Default to entire dataspace being selected */
1162     if (H5S_select_all(ds, FALSE) < 0)
1163         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
1164 
1165     /* Set the value for successful return */
1166     ret_value = ds;
1167 
1168 done:
1169     if (ret_value == NULL)
1170         if (ds != NULL)
1171             ds = H5FL_FREE(H5S_t, ds);
1172 
1173     FUNC_LEAVE_NOAPI(ret_value)
1174 } /* end H5S_read() */
1175 
1176 /*--------------------------------------------------------------------------
1177  NAME
1178     H5S__is_simple
1179  PURPOSE
1180     Check if a dataspace is simple (internal)
1181  USAGE
1182     htri_t H5S__is_simple(sdim)
1183     H5S_t *sdim;        IN: Pointer to dataspace object to query
1184  RETURNS
1185     TRUE/FALSE/FAIL
1186  DESCRIPTION
1187     This function determines the if a dataspace is "simple". ie. if it
1188     has orthogonal, evenly spaced dimensions.
1189 --------------------------------------------------------------------------*/
1190 static htri_t
H5S__is_simple(const H5S_t * sdim)1191 H5S__is_simple(const H5S_t *sdim)
1192 {
1193     htri_t ret_value = FAIL; /* Return value */
1194 
1195     FUNC_ENTER_STATIC_NOERR
1196 
1197     /* Check args and all the boring stuff. */
1198     HDassert(sdim);
1199 
1200     /* H5S_NULL shouldn't be simple dataspace */
1201     ret_value =
1202         (H5S_GET_EXTENT_TYPE(sdim) == H5S_SIMPLE || H5S_GET_EXTENT_TYPE(sdim) == H5S_SCALAR) ? TRUE : FALSE;
1203 
1204     FUNC_LEAVE_NOAPI(ret_value)
1205 } /* end H5S__is_simple() */
1206 
1207 /*--------------------------------------------------------------------------
1208  NAME
1209     H5Sis_simple
1210  PURPOSE
1211     Check if a dataspace is simple
1212  USAGE
1213     htri_t H5Sis_simple(space_id)
1214     hid_t space_id;         IN: ID of dataspace object to query
1215  RETURNS
1216     TRUE/FALSE/FAIL
1217  DESCRIPTION
1218     This function determines the if a dataspace is "simple". ie. if it
1219     has orthogonal, evenly spaced dimensions.
1220 --------------------------------------------------------------------------*/
1221 htri_t
H5Sis_simple(hid_t space_id)1222 H5Sis_simple(hid_t space_id)
1223 {
1224     H5S_t *space;     /* Dataspace to check */
1225     htri_t ret_value; /* Return value */
1226 
1227     FUNC_ENTER_API(FAIL)
1228     H5TRACE1("t", "i", space_id);
1229 
1230     /* Check args and all the boring stuff. */
1231     if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
1232         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
1233 
1234     ret_value = H5S__is_simple(space);
1235 
1236 done:
1237     FUNC_LEAVE_API(ret_value)
1238 } /* end H5Sis_simple() */
1239 
1240 /*--------------------------------------------------------------------------
1241  NAME
1242     H5Sset_extent_simple
1243  PURPOSE
1244     Sets the size of a simple dataspace
1245  USAGE
1246     herr_t H5Sset_extent_simple(space_id, rank, dims, max)
1247         hid_t space_id;         IN: Dataspace object to query
1248         int rank;               IN: # of dimensions for the dataspace
1249         const size_t *dims;     IN: Size of each dimension for the dataspace
1250         const size_t *max;      IN: Maximum size of each dimension for the
1251                                     dataspace
1252  RETURNS
1253     Non-negative on success/Negative on failure
1254  DESCRIPTION
1255     This function sets the number and size of each dimension in the
1256     dataspace. Setting RANK to a value of zero converts the dataspace to a
1257     scalar dataspace.  Dimensions are specified from slowest to fastest
1258     changing in the DIMS array (i.e. 'C' order).  Setting the size of a
1259     dimension in the MAX array to zero indicates that the dimension is of
1260     unlimited size and should be allowed to expand.  If MAX is NULL, the
1261     dimensions in the DIMS array are used as the maximum dimensions.
1262     Currently, only the first dimension in the array (the slowest) may be
1263     unlimited in size.
1264 
1265 --------------------------------------------------------------------------*/
1266 herr_t
H5Sset_extent_simple(hid_t space_id,int rank,const hsize_t dims[],const hsize_t max[])1267 H5Sset_extent_simple(hid_t space_id, int rank, const hsize_t dims[/*rank*/], const hsize_t max[/*rank*/])
1268 {
1269     H5S_t *space;               /* Dataspace to modify */
1270     int    u;                   /* Local counting variable */
1271     herr_t ret_value = SUCCEED; /* Return value */
1272 
1273     FUNC_ENTER_API(FAIL)
1274     H5TRACE4("e", "iIs*[a1]h*[a1]h", space_id, rank, dims, max);
1275 
1276     /* Check args */
1277     if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
1278         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
1279     if (rank > 0 && dims == NULL)
1280         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "no dimensions specified")
1281     if (rank < 0 || rank > H5S_MAX_RANK)
1282         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid rank")
1283     if (dims)
1284         for (u = 0; u < rank; u++)
1285             if (H5S_UNLIMITED == dims[u])
1286                 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
1287                             "current dimension must have a specific size, not H5S_UNLIMITED")
1288     if (max != NULL) {
1289         if (dims == NULL)
1290             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL,
1291                         "maximum dimension specified, but no current dimensions specified")
1292         for (u = 0; u < rank; u++)
1293             if (max[u] != H5S_UNLIMITED && max[u] < dims[u])
1294                 HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, FAIL, "invalid maximum dimension size")
1295     }
1296 
1297     /* Do it */
1298     if (H5S_set_extent_simple(space, (unsigned)rank, dims, max) < 0)
1299         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, FAIL, "unable to set simple extent")
1300 
1301 done:
1302     FUNC_LEAVE_API(ret_value)
1303 } /* end H5Sset_extent_simple() */
1304 
1305 /*-------------------------------------------------------------------------
1306  * Function:    H5S_set_extent_simple
1307  *
1308  * Purpose:     This is where the real work happens for H5Sset_extent_simple().
1309  *
1310  * Return:      Non-negative on success/Negative on failure
1311  *
1312  * Programmer:  Robb Matzke
1313  *              Wednesday, July  8, 1998
1314  *
1315  *-------------------------------------------------------------------------
1316  */
1317 herr_t
H5S_set_extent_simple(H5S_t * space,unsigned rank,const hsize_t * dims,const hsize_t * max)1318 H5S_set_extent_simple(H5S_t *space, unsigned rank, const hsize_t *dims, const hsize_t *max)
1319 {
1320     unsigned u;                   /* Local index variable */
1321     herr_t   ret_value = SUCCEED; /* Return value */
1322 
1323     FUNC_ENTER_NOAPI(FAIL)
1324 
1325     /* Check args */
1326     HDassert(rank <= H5S_MAX_RANK);
1327 
1328     /* shift out of the previous state to a "simple" dataspace.  */
1329     if (H5S__extent_release(&space->extent) < 0)
1330         HGOTO_ERROR(H5E_RESOURCE, H5E_CANTFREE, FAIL, "failed to release previous dataspace extent")
1331 
1332     if (rank == 0) { /* scalar variable */
1333         space->extent.type  = H5S_SCALAR;
1334         space->extent.nelem = 1;
1335         space->extent.rank  = 0; /* set to scalar rank */
1336     }                            /* end if */
1337     else {
1338         hsize_t nelem; /* Number of elements in extent */
1339 
1340         space->extent.type = H5S_SIMPLE;
1341 
1342         /* Set the rank and allocate space for the dims */
1343         space->extent.rank = rank;
1344         space->extent.size = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)rank);
1345 
1346         /* Copy the dimensions & compute the number of elements in the extent */
1347         for (u = 0, nelem = 1; dims && (u < space->extent.rank); u++) {
1348             space->extent.size[u] = dims[u];
1349             nelem *= dims[u];
1350         } /* end for */
1351         space->extent.nelem = nelem;
1352 
1353         /* Copy the maximum dimensions if specified. Otherwise, the maximal dimensions are the
1354          * same as the dimension */
1355         space->extent.max = (hsize_t *)H5FL_ARR_MALLOC(hsize_t, (size_t)rank);
1356         if (max != NULL)
1357             H5MM_memcpy(space->extent.max, max, sizeof(hsize_t) * rank);
1358         else
1359             for (u = 0; dims && (u < space->extent.rank); u++)
1360                 space->extent.max[u] = dims[u];
1361     } /* end else */
1362 
1363     /* Selection related cleanup */
1364 
1365     /* Set offset to zeros */
1366     HDmemset(space->select.offset, 0, sizeof(hsize_t) * space->extent.rank);
1367     space->select.offset_changed = FALSE;
1368 
1369     /* If the selection is 'all', update the number of elements selected */
1370     if (H5S_GET_SELECT_TYPE(space) == H5S_SEL_ALL)
1371         if (H5S_select_all(space, FALSE) < 0)
1372             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
1373 
1374 done:
1375     FUNC_LEAVE_NOAPI(ret_value)
1376 } /* end H5S_set_extent_simple() */
1377 
1378 /*-------------------------------------------------------------------------
1379  * Function:    H5Screate_simple
1380  *
1381  * Purpose:     Creates a new simple dataspace object and opens it for
1382  *              access. The DIMS argument is the size of the simple dataset
1383  *              and the MAXDIMS argument is the upper limit on the size of
1384  *              the dataset.  MAXDIMS may be the null pointer in which case
1385  *              the upper limit is the same as DIMS.  If an element of
1386  *              MAXDIMS is H5S_UNLIMITED then the corresponding dimension is
1387  *              unlimited, otherwise no element of MAXDIMS should be smaller
1388  *              than the corresponding element of DIMS.
1389  *
1390  * Return:      Success:    The ID for the new simple dataspace object.
1391  *
1392  *              Failure:    H5I_INVALID_HID
1393  *
1394  * Programmer:  Quincey Koziol
1395  *              Tuesday, January  27, 1998
1396  *
1397  *-------------------------------------------------------------------------
1398  */
1399 hid_t
H5Screate_simple(int rank,const hsize_t dims[],const hsize_t maxdims[])1400 H5Screate_simple(int rank, const hsize_t dims[/*rank*/], const hsize_t maxdims[/*rank*/])
1401 {
1402     H5S_t *space = NULL;
1403     int    i;
1404     hid_t  ret_value = H5I_INVALID_HID;
1405 
1406     FUNC_ENTER_API(H5I_INVALID_HID)
1407     H5TRACE3("i", "Is*[a0]h*[a0]h", rank, dims, maxdims);
1408 
1409     /* Check arguments */
1410     if (rank < 0)
1411         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dimensionality cannot be negative")
1412     if (rank > H5S_MAX_RANK)
1413         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "dimensionality is too large")
1414 
1415     /* We allow users to use this function to create scalar or null dataspace.
1416      * Check DIMS isn't set when the RANK is 0.
1417      */
1418     if (!dims && rank != 0)
1419         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "invalid dataspace information")
1420 
1421     /* Check whether the current dimensions are valid */
1422     for (i = 0; i < rank; i++) {
1423         if (H5S_UNLIMITED == dims[i])
1424             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID,
1425                         "current dimension must have a specific size, not H5S_UNLIMITED")
1426         if (maxdims && H5S_UNLIMITED != maxdims[i] && maxdims[i] < dims[i])
1427             HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "maxdims is smaller than dims")
1428     } /* end for */
1429 
1430     /* Create the space and set the extent */
1431     if (NULL == (space = H5S_create_simple((unsigned)rank, dims, maxdims)))
1432         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, H5I_INVALID_HID, "can't create simple dataspace")
1433 
1434     /* Atomize */
1435     if ((ret_value = H5I_register(H5I_DATASPACE, space, TRUE)) < 0)
1436         HGOTO_ERROR(H5E_ATOM, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace ID")
1437 
1438 done:
1439     if (ret_value < 0)
1440         if (space && H5S_close(space) < 0)
1441             HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, H5I_INVALID_HID, "unable to release dataspace")
1442 
1443     FUNC_LEAVE_API(ret_value)
1444 } /* end H5Screate_simple() */
1445 
1446 /*-------------------------------------------------------------------------
1447  * Function:    H5S_create_simple
1448  *
1449  * Purpose:     Internal function to create simple dataspace
1450  *
1451  * Return:      Success:    A pointer to a dataspace object
1452  *              Failure:    NULL
1453  *
1454  * Programmer:  Quincey Koziol
1455  *              Thursday, April  3, 2003
1456  *
1457  *-------------------------------------------------------------------------
1458  */
1459 H5S_t *
H5S_create_simple(unsigned rank,const hsize_t dims[],const hsize_t maxdims[])1460 H5S_create_simple(unsigned rank, const hsize_t dims[/*rank*/], const hsize_t maxdims[/*rank*/])
1461 {
1462     H5S_t *ret_value = NULL; /* Return value */
1463 
1464     FUNC_ENTER_NOAPI(NULL)
1465 
1466     /* Check arguments */
1467     HDassert(rank <= H5S_MAX_RANK);
1468 
1469     /* Create the space and set the extent */
1470     if (NULL == (ret_value = H5S_create(H5S_SIMPLE)))
1471         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCREATE, NULL, "can't create simple dataspace")
1472     if (H5S_set_extent_simple(ret_value, rank, dims, maxdims) < 0)
1473         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTINIT, NULL, "can't set dimensions")
1474 
1475 done:
1476     FUNC_LEAVE_NOAPI(ret_value)
1477 } /* end H5S_create_simple() */
1478 
1479 /*-------------------------------------------------------------------------
1480  * Function:    H5Sencode2
1481  *
1482  * Purpose:     Given a dataspace ID, converts the object description
1483  *              (including selection) into binary in a buffer.
1484  *              The selection will be encoded according to the file
1485  *              format setting in the fapl.
1486  *
1487  * Return:      Success:    Non-negative
1488  *              Failure:    Negative
1489  *
1490  * Programmer:  Raymond Lu
1491  *              July 14, 2004
1492  *
1493  *-------------------------------------------------------------------------
1494  */
1495 herr_t
H5Sencode2(hid_t obj_id,void * buf,size_t * nalloc,hid_t fapl_id)1496 H5Sencode2(hid_t obj_id, void *buf, size_t *nalloc, hid_t fapl_id)
1497 {
1498     H5S_t *dspace;
1499     herr_t ret_value = SUCCEED;
1500 
1501     FUNC_ENTER_API(FAIL)
1502     H5TRACE4("e", "i*x*zi", obj_id, buf, nalloc, fapl_id);
1503 
1504     /* Check argument and retrieve object */
1505     if (NULL == (dspace = (H5S_t *)H5I_object_verify(obj_id, H5I_DATASPACE)))
1506         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
1507 
1508     /* Verify access property list and set up collective metadata if appropriate */
1509     if (H5CX_set_apl(&fapl_id, H5P_CLS_FACC, H5I_INVALID_HID, TRUE) < 0)
1510         HGOTO_ERROR(H5E_FILE, H5E_CANTSET, H5I_INVALID_HID, "can't set access property list info")
1511 
1512     if (H5S_encode(dspace, (unsigned char **)&buf, nalloc) < 0)
1513         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode dataspace")
1514 
1515 done:
1516     FUNC_LEAVE_API(ret_value)
1517 } /* end H5Sencode2() */
1518 
1519 /*-------------------------------------------------------------------------
1520  * Function:    H5S_encode
1521  *
1522  * Purpose:     Private function for H5Sencode.  Converts an object
1523  *              description for dataspace and its selection into binary
1524  *              in a buffer.
1525  *
1526  * Return:      SUCCEED/FAIL
1527  *
1528  * Programmer:  Raymond Lu
1529  *              July 14, 2004
1530  *
1531  *-------------------------------------------------------------------------
1532  */
1533 herr_t
H5S_encode(H5S_t * obj,unsigned char ** p,size_t * nalloc)1534 H5S_encode(H5S_t *obj, unsigned char **p, size_t *nalloc)
1535 {
1536     H5F_t *  f = NULL;            /* Fake file structure*/
1537     size_t   extent_size;         /* Size of serialized dataspace extent */
1538     hssize_t sselect_size;        /* Signed size of serialized dataspace selection */
1539     size_t   select_size;         /* Size of serialized dataspace selection */
1540     herr_t   ret_value = SUCCEED; /* Return value */
1541 
1542     FUNC_ENTER_NOAPI_NOINIT
1543 
1544     /* Allocate "fake" file structure */
1545     if (NULL == (f = H5F_fake_alloc((uint8_t)0)))
1546         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, FAIL, "can't allocate fake file struct")
1547 
1548     /* Find out the size of buffer needed for extent */
1549     if ((extent_size = H5O_msg_raw_size(f, H5O_SDSPACE_ID, TRUE, obj)) == 0)
1550         HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace size")
1551 
1552     /* Find out the size of buffer needed for selection */
1553     if ((sselect_size = H5S_SELECT_SERIAL_SIZE(obj)) < 0)
1554         HGOTO_ERROR(H5E_DATASPACE, H5E_BADSIZE, FAIL, "can't find dataspace selection size")
1555     H5_CHECKED_ASSIGN(select_size, size_t, sselect_size, hssize_t);
1556 
1557     /* Verify the size of buffer.  If it's not big enough, simply return the
1558      * right size without filling the buffer. */
1559     if (!*p || *nalloc < (extent_size + select_size + 1 + 1 + 1 + 4))
1560         *nalloc = extent_size + select_size + 1 + 1 + 1 + 4;
1561     else {
1562         unsigned char *pp = (*p); /* Local pointer for decoding */
1563 
1564         /* Encode the type of the information */
1565         *pp++ = H5O_SDSPACE_ID;
1566 
1567         /* Encode the version of the dataspace information */
1568         *pp++ = H5S_ENCODE_VERSION;
1569 
1570         /* Encode the "size of size" information */
1571         *pp++ = (unsigned char)H5F_SIZEOF_SIZE(f);
1572 
1573         /* Encode size of extent information. Pointer is actually moved in this macro. */
1574         UINT32ENCODE(pp, extent_size);
1575 
1576         /* Encode the extent part of dataspace */
1577         if (H5O_msg_encode(f, H5O_SDSPACE_ID, TRUE, pp, obj) < 0)
1578             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode extent space")
1579         pp += extent_size;
1580 
1581         /* Encode the selection part of dataspace.  */
1582         *p = pp;
1583         if (H5S_SELECT_SERIALIZE(obj, p) < 0)
1584             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTENCODE, FAIL, "can't encode select space")
1585     } /* end else */
1586 
1587 done:
1588     /* Release fake file structure */
1589     if (f && H5F_fake_free(f) < 0)
1590         HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, FAIL, "unable to release fake file struct")
1591 
1592     FUNC_LEAVE_NOAPI(ret_value)
1593 } /* end H5S_encode() */
1594 
1595 /*-------------------------------------------------------------------------
1596  * Function:    H5Sdecode
1597  *
1598  * Purpose:     Decode a binary object description of dataspace and
1599  *              return a new object handle.
1600  *
1601  * Return:      Success:    dataspace ID(non-negative)
1602  *
1603  *              Failure:    H5I_INVALID_HID
1604  *
1605  * Programmer:  Raymond Lu
1606  *              July 14, 2004
1607  *
1608  *-------------------------------------------------------------------------
1609  */
1610 hid_t
H5Sdecode(const void * buf)1611 H5Sdecode(const void *buf)
1612 {
1613     H5S_t *ds;
1614     hid_t  ret_value;
1615 
1616     FUNC_ENTER_API(H5I_INVALID_HID)
1617     H5TRACE1("i", "*x", buf);
1618 
1619     if (buf == NULL)
1620         HGOTO_ERROR(H5E_ARGS, H5E_BADVALUE, H5I_INVALID_HID, "empty buffer")
1621 
1622     if ((ds = H5S_decode((const unsigned char **)&buf)) == NULL)
1623         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, H5I_INVALID_HID, "can't decode object")
1624 
1625     /* Register the type and return the ID */
1626     if ((ret_value = H5I_register(H5I_DATASPACE, ds, TRUE)) < 0)
1627         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register dataspace")
1628 
1629 done:
1630     FUNC_LEAVE_API(ret_value)
1631 } /* end H5Sdecode() */
1632 
1633 /*-------------------------------------------------------------------------
1634  * Function:    H5S_decode
1635  *
1636  * Purpose:     Private function for H5Sdecode.  Reconstructs a binary
1637  *              description of dataspace and returns a new object handle.
1638  *
1639  * Return:      Success:    Pointer to a dataspace buffer
1640  *
1641  *              Failure:	NULL
1642  *
1643  * Programmer:  Raymond Lu
1644  *              July 14, 2004
1645  *
1646  *-------------------------------------------------------------------------
1647  */
1648 H5S_t *
H5S_decode(const unsigned char ** p)1649 H5S_decode(const unsigned char **p)
1650 {
1651     H5F_t *              f = NULL;         /* Fake file structure*/
1652     H5S_t *              ds;               /* Decoded dataspace */
1653     H5S_extent_t *       extent;           /* Entent of decoded dataspace */
1654     const unsigned char *pp = (*p);        /* Local pointer for decoding */
1655     size_t               extent_size;      /* size of the extent message*/
1656     uint8_t              sizeof_size;      /* 'Size of sizes' for file */
1657     H5S_t *              ret_value = NULL; /* Return value */
1658 
1659     FUNC_ENTER_NOAPI_NOINIT
1660 
1661     /* Decode the type of the information */
1662     if (*pp++ != H5O_SDSPACE_ID)
1663         HGOTO_ERROR(H5E_DATASPACE, H5E_BADMESG, NULL, "not an encoded dataspace")
1664 
1665     /* Decode the version of the dataspace information */
1666     if (*pp++ != H5S_ENCODE_VERSION)
1667         HGOTO_ERROR(H5E_DATASPACE, H5E_VERSION, NULL, "unknown version of encoded dataspace")
1668 
1669     /* Decode the "size of size" information */
1670     sizeof_size = *pp++;
1671 
1672     /* Allocate "fake" file structure */
1673     if (NULL == (f = H5F_fake_alloc(sizeof_size)))
1674         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTALLOC, NULL, "can't allocate fake file struct")
1675 
1676     /* Decode size of extent information */
1677     UINT32DECODE(pp, extent_size);
1678 
1679     /* Decode the extent part of dataspace */
1680     /* (pass mostly bogus file pointer and bogus DXPL) */
1681     if (NULL == (extent = (H5S_extent_t *)H5O_msg_decode(f, NULL, H5O_SDSPACE_ID, extent_size, pp)))
1682         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, NULL, "can't decode object")
1683     pp += extent_size;
1684 
1685     /* Copy the extent into dataspace structure */
1686     if (NULL == (ds = H5FL_CALLOC(H5S_t)))
1687         HGOTO_ERROR(H5E_RESOURCE, H5E_NOSPACE, NULL,
1688                     "memory allocation failed for dataspace conversion path table")
1689     if (NULL == H5O_msg_copy(H5O_SDSPACE_ID, extent, &(ds->extent)))
1690         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOPY, NULL, "can't copy object")
1691     if (H5S__extent_release(extent) < 0)
1692         HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, NULL, "can't release previous dataspace")
1693     extent = H5FL_FREE(H5S_extent_t, extent);
1694 
1695     /* Initialize to "all" selection. Deserialization relies on valid existing selection. */
1696     if (H5S_select_all(ds, FALSE) < 0)
1697         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, NULL, "unable to set all selection")
1698 
1699     /* Decode the select part of dataspace.  I believe this part always exists. */
1700     *p = pp;
1701     if (H5S_SELECT_DESERIALIZE(&ds, p) < 0)
1702         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDECODE, NULL, "can't decode space selection")
1703 
1704     /* Set return value */
1705     ret_value = ds;
1706 
1707 done:
1708     /* Release fake file structure */
1709     if (f && H5F_fake_free(f) < 0)
1710         HDONE_ERROR(H5E_DATASPACE, H5E_CANTRELEASE, NULL, "unable to release fake file struct")
1711 
1712     FUNC_LEAVE_NOAPI(ret_value)
1713 } /* end H5S_decode() */
1714 
1715 /*-------------------------------------------------------------------------
1716  * Function:    H5S_get_simple_extent_type
1717  *
1718  * Purpose:     Internal function for retrieving the type of extent for a dataspace object
1719  *
1720  * Return:      Success:    The class of the dataspace object
1721  *
1722  *              Failure:    N5S_NO_CLASS
1723  *
1724  * Programmer:  Quincey Koziol
1725  *              Thursday, September 28, 2000
1726  *
1727  * Note:        This routine participates in the "Inlining C function pointers"
1728  *              pattern, don't call it directly, use the appropriate macro
1729  *              defined in H5Sprivate.h.
1730  *
1731  *-------------------------------------------------------------------------
1732  */
1733 H5S_class_t
H5S_get_simple_extent_type(const H5S_t * space)1734 H5S_get_simple_extent_type(const H5S_t *space)
1735 {
1736     H5S_class_t ret_value = H5S_NO_CLASS; /* Return value */
1737 
1738     FUNC_ENTER_NOAPI(H5S_NO_CLASS)
1739 
1740     HDassert(space);
1741 
1742     ret_value = H5S_GET_EXTENT_TYPE(space);
1743 
1744 done:
1745     FUNC_LEAVE_NOAPI(ret_value)
1746 } /* end H5S_get_simple_extent_type() */
1747 
1748 /*-------------------------------------------------------------------------
1749  * Function:    H5Sget_simple_extent_type
1750  *
1751  * Purpose:     Retrieves the type of extent for a dataspace object
1752  *
1753  * Return:      Success:    The class of the dataspace object
1754  *
1755  *              Failure:    N5S_NO_CLASS
1756  *
1757  * Programmer:  Quincey Koziol
1758  *              Thursday, July 23, 1998
1759  *
1760  *-------------------------------------------------------------------------
1761  */
1762 H5S_class_t
H5Sget_simple_extent_type(hid_t sid)1763 H5Sget_simple_extent_type(hid_t sid)
1764 {
1765     H5S_t *     space;
1766     H5S_class_t ret_value; /* Return value */
1767 
1768     FUNC_ENTER_API(H5S_NO_CLASS)
1769     H5TRACE1("Sc", "i", sid);
1770 
1771     /* Check arguments */
1772     if (NULL == (space = (H5S_t *)H5I_object_verify(sid, H5I_DATASPACE)))
1773         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, H5S_NO_CLASS, "not a dataspace")
1774 
1775     ret_value = H5S_GET_EXTENT_TYPE(space);
1776 
1777 done:
1778     FUNC_LEAVE_API(ret_value)
1779 } /* end H5Sget_simple_extent_type() */
1780 
1781 /*--------------------------------------------------------------------------
1782  NAME
1783     H5Sset_extent_none
1784  PURPOSE
1785     Resets the extent of a dataspace back to "none"
1786  USAGE
1787     herr_t H5Sset_extent_none(space_id)
1788         hid_t space_id;         IN: Dataspace object to reset
1789  RETURNS
1790     Non-negative on success/Negative on failure
1791  DESCRIPTION
1792     This function resets the type of a dataspace to H5S_NULL with no
1793     extent information stored for the dataspace.
1794 --------------------------------------------------------------------------*/
1795 herr_t
H5Sset_extent_none(hid_t space_id)1796 H5Sset_extent_none(hid_t space_id)
1797 {
1798     H5S_t *space;               /* Dataspace to modify */
1799     herr_t ret_value = SUCCEED; /* Return value */
1800 
1801     FUNC_ENTER_API(FAIL)
1802     H5TRACE1("e", "i", space_id);
1803 
1804     /* Check args */
1805     if (NULL == (space = (H5S_t *)H5I_object_verify(space_id, H5I_DATASPACE)))
1806         HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, FAIL, "not a dataspace")
1807 
1808     /* Clear the previous extent from the dataspace */
1809     if (H5S__extent_release(&space->extent) < 0)
1810         HGOTO_ERROR(H5E_RESOURCE, H5E_CANTDELETE, FAIL, "can't release previous dataspace")
1811 
1812     space->extent.type = H5S_NULL;
1813 
1814 done:
1815     FUNC_LEAVE_API(ret_value)
1816 } /* end H5Sset_extent_none() */
1817 
1818 /*-------------------------------------------------------------------------
1819  * Function:    H5S_set_extent
1820  *
1821  * Purpose:     Modify the dimensions of a dataspace.
1822  *
1823  * Return:      TRUE/FALSE/FAIL
1824  *
1825  * Programmer:  Pedro Vicente
1826  *              March 13, 2002
1827  *
1828  *-------------------------------------------------------------------------
1829  */
1830 htri_t
H5S_set_extent(H5S_t * space,const hsize_t * size)1831 H5S_set_extent(H5S_t *space, const hsize_t *size)
1832 {
1833     unsigned u;                 /* Local index variable */
1834     htri_t   ret_value = FALSE; /* Return value */
1835 
1836     FUNC_ENTER_NOAPI(FAIL)
1837 
1838     /* Check args */
1839     HDassert(space && H5S_SIMPLE == H5S_GET_EXTENT_TYPE(space));
1840     HDassert(size);
1841 
1842     /* Verify that the dimensions being changed are allowed to change */
1843     for (u = 0; u < space->extent.rank; u++)
1844         if (space->extent.size[u] != size[u]) {
1845             /* Check for invalid dimension size modification */
1846             if (space->extent.max && H5S_UNLIMITED != space->extent.max[u] && space->extent.max[u] < size[u])
1847                 HGOTO_ERROR(H5E_DATASPACE, H5E_BADVALUE, FAIL,
1848                             "dimension cannot exceed the existing maximal size (new: %llu max: %llu)",
1849                             (unsigned long long)size[u], (unsigned long long)space->extent.max[u])
1850 
1851             /* Indicate that dimension size can be modified */
1852             ret_value = TRUE;
1853         } /* end if */
1854 
1855     /* Update dimension size(s) */
1856     if (ret_value)
1857         if (H5S_set_extent_real(space, size) < 0)
1858             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTSET, FAIL, "failed to change dimension size(s)")
1859 
1860 done:
1861     FUNC_LEAVE_NOAPI(ret_value)
1862 } /* end H5S_set_extent() */
1863 
1864 /*-------------------------------------------------------------------------
1865  * Function: H5S_has_extent
1866  *
1867  * Purpose: Determines if a simple dataspace's extent has been set (e.g.,
1868  *          by H5Sset_extent_simple() ).  Helps avoid write errors.
1869  *
1870  * Return: TRUE if dataspace has extent set
1871  *         FALSE if dataspace's extent is uninitialized
1872  *
1873  * Programmer: James Laird
1874  *
1875  * Date: July 23, 2004
1876  *
1877  *-------------------------------------------------------------------------
1878  */
1879 H5_ATTR_PURE hbool_t
H5S_has_extent(const H5S_t * ds)1880 H5S_has_extent(const H5S_t *ds)
1881 {
1882     hbool_t ret_value = FALSE; /* Return value */
1883 
1884     FUNC_ENTER_NOAPI_NOINIT_NOERR
1885 
1886     HDassert(ds);
1887 
1888     if (0 == ds->extent.rank && 0 == ds->extent.nelem && H5S_NULL != ds->extent.type)
1889         ret_value = FALSE;
1890     else
1891         ret_value = TRUE;
1892 
1893     FUNC_LEAVE_NOAPI(ret_value)
1894 } /* end H5S_has_extent() */
1895 
1896 /*-------------------------------------------------------------------------
1897  * Function:    H5S_set_extent_real
1898  *
1899  * Purpose:     Modify the dimensions of a dataspace.
1900  *
1901  * Return:      Success: Non-negative
1902  *              Failure: Negative
1903  *
1904  * Programmer:  Pedro Vicente
1905  *              March 13, 2002
1906  *
1907  *-------------------------------------------------------------------------
1908  */
1909 herr_t
H5S_set_extent_real(H5S_t * space,const hsize_t * size)1910 H5S_set_extent_real(H5S_t *space, const hsize_t *size)
1911 {
1912     hsize_t  nelem;               /* Number of elements in extent */
1913     unsigned u;                   /* Local index variable */
1914     herr_t   ret_value = SUCCEED; /* Return value */
1915 
1916     FUNC_ENTER_NOAPI(FAIL)
1917 
1918     /* Check args */
1919     HDassert(space && H5S_SIMPLE == H5S_GET_EXTENT_TYPE(space));
1920     HDassert(size);
1921 
1922     /* Change the dataspace size & re-compute the number of elements in the extent */
1923     for (u = 0, nelem = 1; u < space->extent.rank; u++) {
1924         space->extent.size[u] = size[u];
1925         nelem *= size[u];
1926     } /* end for */
1927     space->extent.nelem = nelem;
1928 
1929     /* If the selection is 'all', update the number of elements selected */
1930     if (H5S_SEL_ALL == H5S_GET_SELECT_TYPE(space))
1931         if (H5S_select_all(space, FALSE) < 0)
1932             HGOTO_ERROR(H5E_DATASPACE, H5E_CANTDELETE, FAIL, "can't change selection")
1933 
1934     /* Mark the dataspace as no longer shared if it was before */
1935     if (H5O_msg_reset_share(H5O_SDSPACE_ID, space) < 0)
1936         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTRESET, FAIL, "can't stop sharing dataspace")
1937 
1938 done:
1939     FUNC_LEAVE_NOAPI(ret_value)
1940 } /* end H5S_set_extent_real() */
1941 
1942 /*-------------------------------------------------------------------------
1943  * Function:    H5Sextent_equal
1944  *
1945  * Purpose:     Determines if two dataspace extents are equal.
1946  *
1947  * Return:      Success:    TRUE if equal, FALSE if unequal
1948  *
1949  *              Failure:    FAIL
1950  *
1951  * Programmer:  Quincey Koziol
1952  *              Monday, October 24, 2005
1953  *
1954  *-------------------------------------------------------------------------
1955  */
1956 htri_t
H5Sextent_equal(hid_t space1_id,hid_t space2_id)1957 H5Sextent_equal(hid_t space1_id, hid_t space2_id)
1958 {
1959     const H5S_t *ds1; /* Dataspaces to compare */
1960     const H5S_t *ds2;
1961     htri_t       ret_value;
1962 
1963     FUNC_ENTER_API(FAIL)
1964     H5TRACE2("t", "ii", space1_id, space2_id);
1965 
1966     /* check args */
1967     if (NULL == (ds1 = (const H5S_t *)H5I_object_verify(space1_id, H5I_DATASPACE)) ||
1968         NULL == (ds2 = (const H5S_t *)H5I_object_verify(space2_id, H5I_DATASPACE)))
1969         HGOTO_ERROR(H5E_ARGS, H5E_BADTYPE, FAIL, "not a dataspace")
1970 
1971     /* Check dataspaces for extent's equality */
1972     if ((ret_value = H5S_extent_equal(ds1, ds2)) < 0)
1973         HGOTO_ERROR(H5E_DATASPACE, H5E_CANTCOMPARE, FAIL, "dataspace comparison failed")
1974 
1975 done:
1976     FUNC_LEAVE_API(ret_value)
1977 } /* end H5Sextent_equal() */
1978 
1979 /*--------------------------------------------------------------------------
1980  NAME
1981     H5S_extent_equal
1982  PURPOSE
1983     Check if two dataspaces have equal extents
1984  USAGE
1985     htri_t H5S_extent_equal(ds1, ds2)
1986         H5S_t *ds1, *ds2;            IN: Dataspace objects to compare
1987  RETURNS
1988      TRUE if equal, FALSE if unequal on succeess/Negative on failure
1989  DESCRIPTION
1990     Compare two dataspaces if their extents are identical.
1991 --------------------------------------------------------------------------*/
1992 H5_ATTR_PURE htri_t
H5S_extent_equal(const H5S_t * ds1,const H5S_t * ds2)1993 H5S_extent_equal(const H5S_t *ds1, const H5S_t *ds2)
1994 {
1995     unsigned u;                /* Local index variable */
1996     htri_t   ret_value = TRUE; /* Return value */
1997 
1998     FUNC_ENTER_NOAPI_NOINIT_NOERR
1999 
2000     /* Check args */
2001     HDassert(ds1);
2002     HDassert(ds2);
2003 
2004     /* Make certain the dataspaces are the same type */
2005     if (ds1->extent.type != ds2->extent.type)
2006         HGOTO_DONE(FALSE)
2007 
2008     /* Make certain the dataspaces are the same rank */
2009     if (ds1->extent.rank != ds2->extent.rank)
2010         HGOTO_DONE(FALSE)
2011 
2012     /* Make certain the dataspaces' current dimensions are the same size */
2013     if (ds1->extent.rank > 0) {
2014         HDassert(ds1->extent.size);
2015         HDassert(ds2->extent.size);
2016         for (u = 0; u < ds1->extent.rank; u++)
2017             if (ds1->extent.size[u] != ds2->extent.size[u])
2018                 HGOTO_DONE(FALSE)
2019     } /* end if */
2020 
2021     /* Make certain the dataspaces' maximum dimensions are the same size */
2022     if (ds1->extent.rank > 0) {
2023         /* Check for no maximum dimensions on dataspaces */
2024         if (ds1->extent.max != NULL && ds2->extent.max != NULL) {
2025             for (u = 0; u < ds1->extent.rank; u++)
2026                 if (ds1->extent.max[u] != ds2->extent.max[u])
2027                     HGOTO_DONE(FALSE)
2028         } /* end if */
2029         else if ((ds1->extent.max == NULL && ds2->extent.max != NULL) ||
2030                  (ds1->extent.max != NULL && ds2->extent.max == NULL))
2031             HGOTO_DONE(FALSE)
2032     } /* end if */
2033 
2034 done:
2035     FUNC_LEAVE_NOAPI(ret_value)
2036 } /* end H5S_extent_equal() */
2037 
2038 /*-------------------------------------------------------------------------
2039  * Function:    H5S_extent_nelem
2040  *
2041  * Purpose:     Determines how many elements a dataset extent describes.
2042  *
2043  * Return:      Success:    Number of data points in the dataset extent.
2044  *              Failure:    Negative
2045  *
2046  * Programmer:  Quincey Koziol
2047  *              Thursday, November 30, 2006
2048  *
2049  *-------------------------------------------------------------------------
2050  */
2051 H5_ATTR_PURE hsize_t
H5S_extent_nelem(const H5S_extent_t * ext)2052 H5S_extent_nelem(const H5S_extent_t *ext)
2053 {
2054     FUNC_ENTER_NOAPI_NOINIT_NOERR
2055 
2056     /* check args */
2057     HDassert(ext);
2058 
2059     /* Return the number of elements in extent */
2060     FUNC_LEAVE_NOAPI(ext->nelem)
2061 } /* end H5S_extent_nelem() */
2062 
2063 /*-------------------------------------------------------------------------
2064  * Function:    H5S_set_version
2065  *
2066  * Purpose:     Set the version to encode a dataspace with.
2067  *
2068  * Return:      Non-negative on success/Negative on failure
2069  *
2070  * Programmer:  Vailin Choi; December 2017
2071  *
2072  *-------------------------------------------------------------------------
2073  */
2074 herr_t
H5S_set_version(H5F_t * f,H5S_t * ds)2075 H5S_set_version(H5F_t *f, H5S_t *ds)
2076 {
2077     unsigned version;             /* Message version */
2078     herr_t   ret_value = SUCCEED; /* Return value */
2079 
2080     FUNC_ENTER_NOAPI(FAIL)
2081 
2082     /* Sanity check */
2083     HDassert(f);
2084     HDassert(ds);
2085 
2086     /* Upgrade to the version indicated by the file's low bound if higher */
2087     version = MAX(ds->extent.version, H5O_sdspace_ver_bounds[H5F_LOW_BOUND(f)]);
2088 
2089     /* Version bounds check */
2090     if (version > H5O_sdspace_ver_bounds[H5F_HIGH_BOUND(f)])
2091         HGOTO_ERROR(H5E_DATASET, H5E_BADRANGE, FAIL, "Dataspace version out of bounds")
2092 
2093     /* Set the message version */
2094     ds->extent.version = version;
2095 
2096 done:
2097     FUNC_LEAVE_NOAPI(ret_value)
2098 } /* end H5S_set_version() */
2099