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